mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 20:26:19 +08:00
precompute part 2
This commit is contained in:
parent
2b0119dda7
commit
d6a464f470
@ -2,3 +2,39 @@ This part codes mainly refer two projects:
|
|||||||
|
|
||||||
1. [bn256](https://github.com/cloudflare/bn256), 主要是基域运算
|
1. [bn256](https://github.com/cloudflare/bn256), 主要是基域运算
|
||||||
2. [gmssl sm9](https://github.com/guanzhi/GmSSL/blob/develop/src/sm9_alg.c),主要是2-4-12塔式扩域,以及r-ate等
|
2. [gmssl sm9](https://github.com/guanzhi/GmSSL/blob/develop/src/sm9_alg.c),主要是2-4-12塔式扩域,以及r-ate等
|
||||||
|
|
||||||
|
|
||||||
|
**SM9 Sign Benchmark**
|
||||||
|
|
||||||
|
goos: windows
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/emmansun/gmsm/sm9
|
||||||
|
cpu: Intel(R) Core(TM) i5-9500 CPU @ 3.00GHz
|
||||||
|
BenchmarkSign-6 1344 871597 ns/op 35870 B/op 1013 allocs/op
|
||||||
|
|
||||||
|
|
||||||
|
**SM9 Verify Benchmark**
|
||||||
|
|
||||||
|
goos: windows
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/emmansun/gmsm/sm9
|
||||||
|
cpu: Intel(R) Core(TM) i5-9500 CPU @ 3.00GHz
|
||||||
|
BenchmarkVerify-6 352 3331673 ns/op 237676 B/op 6283 allocs/op
|
||||||
|
|
||||||
|
**SM9 Encrypt(XOR) Benchmark**
|
||||||
|
|
||||||
|
goos: windows
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/emmansun/gmsm/sm9
|
||||||
|
cpu: Intel(R) Core(TM) i5-9500 CPU @ 3.00GHz
|
||||||
|
BenchmarkEncrypt-6 1120 971188 ns/op 38125 B/op 1036 allocs/op
|
||||||
|
|
||||||
|
**SM9 Decrypt(XOR) Benchmark**
|
||||||
|
|
||||||
|
goos: windows
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/emmansun/gmsm/sm9
|
||||||
|
cpu: Intel(R) Core(TM) i5-9500 CPU @ 3.00GHz
|
||||||
|
BenchmarkDecrypt-6 507 2345492 ns/op 202360 B/op 5228 allocs/op
|
||||||
|
|
||||||
|
To further improve `Verify()/Decrypt()` performance, need to improve `Pair()` method performance.
|
||||||
|
@ -367,3 +367,11 @@ func (e *gfP12) Conjugate(a *gfP12) *gfP12 {
|
|||||||
e.x.Conjugate(&a.x)
|
e.x.Conjugate(&a.x)
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select sets q to p1 if cond == 1, and to p2 if cond == 0.
|
||||||
|
func (q *gfP12) Select(p1, p2 *gfP12, cond int) *gfP12 {
|
||||||
|
q.x.Select(&p1.x, &p2.x, cond)
|
||||||
|
q.y.Select(&p1.y, &p2.y, cond)
|
||||||
|
q.z.Select(&p1.z, &p2.z, cond)
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
@ -241,3 +241,10 @@ func (e *gfP4) FrobeniusP3(a *gfP4) *gfP4 {
|
|||||||
|
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select sets q to p1 if cond == 1, and to p2 if cond == 0.
|
||||||
|
func (q *gfP4) Select(p1, p2 *gfP4, cond int) *gfP4 {
|
||||||
|
q.x.Select(&p1.x, &p2.x, cond)
|
||||||
|
q.y.Select(&p1.y, &p2.y, cond)
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
28
sm9/gt.go
28
sm9/gt.go
@ -1,6 +1,7 @@
|
|||||||
package sm9
|
package sm9
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/subtle"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
@ -85,6 +86,15 @@ func (e *GT) Set(a *GT) *GT {
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set sets e to one and then returns e.
|
||||||
|
func (e *GT) SetOne() *GT {
|
||||||
|
if e.p == nil {
|
||||||
|
e.p = &gfP12{}
|
||||||
|
}
|
||||||
|
e.p.SetOne()
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
// Finalize is a linear function from F_p^12 to GT.
|
// Finalize is a linear function from F_p^12 to GT.
|
||||||
func (e *GT) Finalize() *GT {
|
func (e *GT) Finalize() *GT {
|
||||||
ret := finalExponentiation(e.p)
|
ret := finalExponentiation(e.p)
|
||||||
@ -197,3 +207,21 @@ func (e *GT) Unmarshal(m []byte) ([]byte, error) {
|
|||||||
|
|
||||||
return m[12*numBytes:], nil
|
return m[12*numBytes:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A gtPointTable holds the first 15 Exp of a value at offset -1, so P
|
||||||
|
// is at table[0], P^15 is at table[14], and P^0 is implicitly the identity
|
||||||
|
// point.
|
||||||
|
type gtTable [15]*GT
|
||||||
|
|
||||||
|
// Select selects the n-th multiple of the table base point into p. It works in
|
||||||
|
// constant time by iterating over every entry of the table. n must be in [0, 15].
|
||||||
|
func (table *gtTable) Select(p *GT, n uint8) {
|
||||||
|
if n >= 16 {
|
||||||
|
panic("sm9: internal error: gtTable called with out-of-bounds value")
|
||||||
|
}
|
||||||
|
p.p.SetOne()
|
||||||
|
for i := uint8(1); i < 16; i++ {
|
||||||
|
cond := subtle.ConstantTimeByteEq(i, n)
|
||||||
|
p.p.Select(table[i-1].p, p.p, cond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
112
sm9/sm9.go
112
sm9/sm9.go
@ -91,17 +91,68 @@ func (pub *SignMasterPublicKey) Pair() *GT {
|
|||||||
return pub.basePoint
|
return pub.basePoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pub *SignMasterPublicKey) generatorTable() *[32 * 2]gtTable {
|
||||||
|
pub.tableGenOnce.Do(func() {
|
||||||
|
pub.table = new([32 * 2]gtTable)
|
||||||
|
base := >{}
|
||||||
|
base.Set(pub.Pair())
|
||||||
|
for i := 0; i < 32*2; i++ {
|
||||||
|
pub.table[i][0] = >{}
|
||||||
|
pub.table[i][0].Set(base)
|
||||||
|
for j := 1; j < 15; j += 2 {
|
||||||
|
pub.table[i][j] = >{}
|
||||||
|
pub.table[i][j].p = &gfP12{}
|
||||||
|
pub.table[i][j].p.Square(pub.table[i][j/2].p)
|
||||||
|
pub.table[i][j+1] = >{}
|
||||||
|
pub.table[i][j+1].p = &gfP12{}
|
||||||
|
pub.table[i][j+1].Add(pub.table[i][j], base)
|
||||||
|
}
|
||||||
|
base.p.Square(base.p)
|
||||||
|
base.p.Square(base.p)
|
||||||
|
base.p.Square(base.p)
|
||||||
|
base.p.Square(base.p)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return pub.table
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pub *SignMasterPublicKey) ScalarBaseMult(r *big.Int) *GT {
|
||||||
|
scalar := normalizeScalar(r.Bytes())
|
||||||
|
tables := pub.generatorTable()
|
||||||
|
// This is also a scalar multiplication with a four-bit window like in
|
||||||
|
// ScalarMult, but in this case the doublings are precomputed. The value
|
||||||
|
// [windowValue]G added at iteration k would normally get doubled
|
||||||
|
// (totIterations-k)×4 times, but with a larger precomputation we can
|
||||||
|
// instead add [2^((totIterations-k)×4)][windowValue]G and avoid the
|
||||||
|
// doublings between iterations.
|
||||||
|
e, t := >{}, >{}
|
||||||
|
tableIndex := len(tables) - 1
|
||||||
|
e.SetOne()
|
||||||
|
t.SetOne()
|
||||||
|
for _, byte := range scalar {
|
||||||
|
windowValue := byte >> 4
|
||||||
|
tables[tableIndex].Select(t, windowValue)
|
||||||
|
e.Add(e, t)
|
||||||
|
tableIndex--
|
||||||
|
windowValue = byte & 0b1111
|
||||||
|
tables[tableIndex].Select(t, windowValue)
|
||||||
|
e.Add(e, t)
|
||||||
|
tableIndex--
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
// Sign signs a hash (which should be the result of hashing a larger message)
|
// Sign signs a hash (which should be the result of hashing a larger message)
|
||||||
// using the user dsa key. It returns the signature as a pair of h and s.
|
// using the user dsa key. It returns the signature as a pair of h and s.
|
||||||
func Sign(rand io.Reader, priv *SignPrivateKey, hash []byte) (h *big.Int, s *G1, err error) {
|
func Sign(rand io.Reader, priv *SignPrivateKey, hash []byte) (h *big.Int, s *G1, err error) {
|
||||||
g := priv.Pair()
|
|
||||||
var r *big.Int
|
var r *big.Int
|
||||||
for {
|
for {
|
||||||
r, err = randFieldElement(rand)
|
r, err = randFieldElement(rand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w := new(GT).ScalarMult(g, r)
|
|
||||||
|
w := priv.SignMasterPublicKey.ScalarBaseMult(r)
|
||||||
|
|
||||||
var buffer []byte
|
var buffer []byte
|
||||||
buffer = append(buffer, hash...)
|
buffer = append(buffer, hash...)
|
||||||
@ -157,9 +208,8 @@ func Verify(pub *SignMasterPublicKey, uid []byte, hid byte, hash []byte, h *big.
|
|||||||
if !s.p.IsOnCurve() {
|
if !s.p.IsOnCurve() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
g := pub.Pair()
|
|
||||||
|
|
||||||
t := new(GT).ScalarMult(g, h)
|
t := pub.ScalarBaseMult(h)
|
||||||
|
|
||||||
// user sign public key p generation
|
// user sign public key p generation
|
||||||
p := pub.GenerateUserPublicKey(uid, hid)
|
p := pub.GenerateUserPublicKey(uid, hid)
|
||||||
@ -227,6 +277,57 @@ func (pub *EncryptMasterPublicKey) Pair() *GT {
|
|||||||
return pub.basePoint
|
return pub.basePoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pub *EncryptMasterPublicKey) generatorTable() *[32 * 2]gtTable {
|
||||||
|
pub.tableGenOnce.Do(func() {
|
||||||
|
pub.table = new([32 * 2]gtTable)
|
||||||
|
base := >{}
|
||||||
|
base.Set(pub.Pair())
|
||||||
|
for i := 0; i < 32*2; i++ {
|
||||||
|
pub.table[i][0] = >{}
|
||||||
|
pub.table[i][0].Set(base)
|
||||||
|
for j := 1; j < 15; j += 2 {
|
||||||
|
pub.table[i][j] = >{}
|
||||||
|
pub.table[i][j].p = &gfP12{}
|
||||||
|
pub.table[i][j].p.Square(pub.table[i][j/2].p)
|
||||||
|
pub.table[i][j+1] = >{}
|
||||||
|
pub.table[i][j+1].p = &gfP12{}
|
||||||
|
pub.table[i][j+1].Add(pub.table[i][j], base)
|
||||||
|
}
|
||||||
|
base.p.Square(base.p)
|
||||||
|
base.p.Square(base.p)
|
||||||
|
base.p.Square(base.p)
|
||||||
|
base.p.Square(base.p)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return pub.table
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pub *EncryptMasterPublicKey) ScalarBaseMult(r *big.Int) *GT {
|
||||||
|
scalar := normalizeScalar(r.Bytes())
|
||||||
|
tables := pub.generatorTable()
|
||||||
|
// This is also a scalar multiplication with a four-bit window like in
|
||||||
|
// ScalarMult, but in this case the doublings are precomputed. The value
|
||||||
|
// [windowValue]G added at iteration k would normally get doubled
|
||||||
|
// (totIterations-k)×4 times, but with a larger precomputation we can
|
||||||
|
// instead add [2^((totIterations-k)×4)][windowValue]G and avoid the
|
||||||
|
// doublings between iterations.
|
||||||
|
e, t := >{}, >{}
|
||||||
|
tableIndex := len(tables) - 1
|
||||||
|
e.SetOne()
|
||||||
|
t.SetOne()
|
||||||
|
for _, byte := range scalar {
|
||||||
|
windowValue := byte >> 4
|
||||||
|
tables[tableIndex].Select(t, windowValue)
|
||||||
|
e.Add(e, t)
|
||||||
|
tableIndex--
|
||||||
|
windowValue = byte & 0b1111
|
||||||
|
tables[tableIndex].Select(t, windowValue)
|
||||||
|
e.Add(e, t)
|
||||||
|
tableIndex--
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
// WrappKey generate and wrapp key wtih reciever's uid and system hid
|
// WrappKey generate and wrapp key wtih reciever's uid and system hid
|
||||||
func WrappKey(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte, kLen int) (key []byte, cipher *G1, err error) {
|
func WrappKey(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte, kLen int) (key []byte, cipher *G1, err error) {
|
||||||
q := pub.GenerateUserPublicKey(uid, hid)
|
q := pub.GenerateUserPublicKey(uid, hid)
|
||||||
@ -240,8 +341,7 @@ func WrappKey(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte,
|
|||||||
|
|
||||||
cipher = new(G1).ScalarMult(q, r)
|
cipher = new(G1).ScalarMult(q, r)
|
||||||
|
|
||||||
g := pub.Pair()
|
w := pub.ScalarBaseMult(r)
|
||||||
w := new(GT).ScalarMult(g, r)
|
|
||||||
|
|
||||||
var buffer []byte
|
var buffer []byte
|
||||||
buffer = append(buffer, cipher.Marshal()...)
|
buffer = append(buffer, cipher.Marshal()...)
|
||||||
|
@ -18,6 +18,8 @@ type SignMasterPublicKey struct {
|
|||||||
MasterPublicKey *G2
|
MasterPublicKey *G2
|
||||||
pairOnce sync.Once
|
pairOnce sync.Once
|
||||||
basePoint *GT
|
basePoint *GT
|
||||||
|
tableGenOnce sync.Once
|
||||||
|
table *[32 * 2]gtTable
|
||||||
}
|
}
|
||||||
|
|
||||||
type SignPrivateKey struct {
|
type SignPrivateKey struct {
|
||||||
@ -34,6 +36,8 @@ type EncryptMasterPublicKey struct {
|
|||||||
MasterPublicKey *G1
|
MasterPublicKey *G1
|
||||||
pairOnce sync.Once
|
pairOnce sync.Once
|
||||||
basePoint *GT
|
basePoint *GT
|
||||||
|
tableGenOnce sync.Once
|
||||||
|
table *[32 * 2]gtTable
|
||||||
}
|
}
|
||||||
|
|
||||||
type EncryptPrivateKey struct {
|
type EncryptPrivateKey struct {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user