package sm9 import ( "encoding/pem" "errors" "io" "math/big" "sync" "github.com/emmansun/gmsm/internal/bigmod" "github.com/emmansun/gmsm/sm9/bn256" "golang.org/x/crypto/cryptobyte" cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" ) // SignMasterPrivateKey master private key for sign, generated by KGC type SignMasterPrivateKey struct { *SignMasterPublicKey // master public key D *big.Int // master private key } // SignMasterPublicKey master public key for sign, generated by KGC type SignMasterPublicKey struct { MasterPublicKey *bn256.G2 // master public key pairOnce sync.Once basePoint *bn256.GT // the result of Pair(Gen1, pub.MasterPublicKey) tableGenOnce sync.Once table *[32 * 2]bn256.GTFieldTable // precomputed basePoint^n } // SignPrivateKey user private key for sign, generated by KGC type SignPrivateKey struct { PrivateKey *bn256.G1 // user private key *SignMasterPublicKey // master public key } // EncryptMasterPrivateKey master private key for encryption, generated by KGC type EncryptMasterPrivateKey struct { *EncryptMasterPublicKey // master public key D *big.Int // master private key } // EncryptMasterPublicKey master private key for encryption, generated by KGC type EncryptMasterPublicKey struct { MasterPublicKey *bn256.G1 // public key pairOnce sync.Once basePoint *bn256.GT // the result of Pair(pub.MasterPublicKey, Gen2) tableGenOnce sync.Once table *[32 * 2]bn256.GTFieldTable // precomputed basePoint^n } // EncryptPrivateKey user private key for encryption, generated by KGC type EncryptPrivateKey struct { PrivateKey *bn256.G2 // user private key *EncryptMasterPublicKey // master public key } // GenerateSignMasterKey generates a master public and private key pair for DSA usage. func GenerateSignMasterKey(rand io.Reader) (*SignMasterPrivateKey, error) { k, err := randomScalar(rand) if err != nil { return nil, err } kBytes := k.Bytes(orderNat) p, err := new(bn256.G2).ScalarBaseMult(kBytes) if err != nil { return nil, err } priv := new(SignMasterPrivateKey) priv.D = new(big.Int).SetBytes(kBytes) priv.SignMasterPublicKey = new(SignMasterPublicKey) priv.MasterPublicKey = p return priv, nil } // MarshalASN1 marshal sign master private key to asn.1 format data according // SM9 cryptographic algorithm application specification func (master *SignMasterPrivateKey) MarshalASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BigInt(master.D) return b.Bytes() } // UnmarshalASN1 unmarsal der data to sign master private key func (master *SignMasterPrivateKey) UnmarshalASN1(der []byte) error { input := cryptobyte.String(der) d := &big.Int{} var inner cryptobyte.String var pubBytes []byte if der[0] == 0x30 { if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) || !input.Empty() || !inner.ReadASN1Integer(d) { return errors.New("sm9: invalid sign master private key asn1 data") } // Just parse it, did't validate it if !inner.Empty() && (!inner.ReadASN1BitStringAsBytes(&pubBytes) || !inner.Empty()) { return errors.New("sm9: invalid sign master public key asn1 data") } } else if !input.ReadASN1Integer(d) || !input.Empty() { return errors.New("sm9: invalid sign master private key asn1 data") } master.D = d master.SignMasterPublicKey = new(SignMasterPublicKey) p, err := new(bn256.G2).ScalarBaseMult(bn256.NormalizeScalar(d.Bytes())) if err != nil { return err } master.MasterPublicKey = p return nil } // GenerateUserKey generate an user dsa key. func (master *SignMasterPrivateKey) GenerateUserKey(uid []byte, hid byte) (*SignPrivateKey, error) { var id []byte id = append(id, uid...) id = append(id, hid) t1Nat := hashH1(id) d, err := bigmod.NewNat().SetBytes(master.D.Bytes(), orderNat) if err != nil { return nil, err } t1Nat.Add(d, orderNat) if t1Nat.IsZero() == 1 { return nil, errors.New("sm9: need to re-generate sign master private key") } t1Nat = bigmod.NewNat().Exp(t1Nat, orderMinus2, orderNat) t1Nat.Mul(d, orderNat) priv := new(SignPrivateKey) priv.SignMasterPublicKey = master.SignMasterPublicKey g1, err := new(bn256.G1).ScalarBaseMult(t1Nat.Bytes(orderNat)) if err != nil { return nil, err } priv.PrivateKey = g1 return priv, nil } // Public returns the public key corresponding to priv. func (master *SignMasterPrivateKey) Public() *SignMasterPublicKey { return master.SignMasterPublicKey } // pair generate the basepoint once func (pub *SignMasterPublicKey) pair() *bn256.GT { pub.pairOnce.Do(func() { pub.basePoint = bn256.Pair(bn256.Gen1, pub.MasterPublicKey) }) return pub.basePoint } func (pub *SignMasterPublicKey) generatorTable() *[32 * 2]bn256.GTFieldTable { pub.tableGenOnce.Do(func() { pub.table = bn256.GenerateGTFieldTable(pub.pair()) }) return pub.table } // ScalarBaseMult compute basepoint^r with precomputed table // The base point = pair(Gen1, ) func (pub *SignMasterPublicKey) ScalarBaseMult(scalar []byte) (*bn256.GT, error) { tables := pub.generatorTable() return bn256.ScalarBaseMultGT(tables, scalar) } // GenerateUserPublicKey generate user sign public key func (pub *SignMasterPublicKey) GenerateUserPublicKey(uid []byte, hid byte) *bn256.G2 { var buffer []byte buffer = append(buffer, uid...) buffer = append(buffer, hid) h1 := hashH1(buffer) p, err := new(bn256.G2).ScalarBaseMult(h1.Bytes(orderNat)) if err != nil { panic(err) } p.Add(p, pub.MasterPublicKey) return p } // MarshalASN1 marshal sign master public key to asn.1 format data according // SM9 cryptographic algorithm application specification func (pub *SignMasterPublicKey) MarshalASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BitString(pub.MasterPublicKey.MarshalUncompressed()) return b.Bytes() } // MarshalCompressedASN1 marshal sign master public key to asn.1 format data according // SM9 cryptographic algorithm application specification, the curve point is in compressed form. func (pub *SignMasterPublicKey) MarshalCompressedASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BitString(pub.MasterPublicKey.MarshalCompressed()) return b.Bytes() } func unmarshalG2(bytes []byte) (*bn256.G2, error) { g2 := new(bn256.G2) switch bytes[0] { case 4: _, err := g2.Unmarshal(bytes[1:]) if err != nil { return nil, err } case 2, 3: _, err := g2.UnmarshalCompressed(bytes) if err != nil { return nil, err } default: return nil, errors.New("sm9: invalid point identity byte") } return g2, nil } // UnmarshalRaw unmarsal raw bytes data to sign master public key func (pub *SignMasterPublicKey) UnmarshalRaw(bytes []byte) error { g2, err := unmarshalG2(bytes) if err != nil { return err } pub.MasterPublicKey = g2 return nil } // UnmarshalASN1 unmarsal der data to sign master public key func (pub *SignMasterPublicKey) UnmarshalASN1(der []byte) error { var bytes []byte var inner cryptobyte.String input := cryptobyte.String(der) if der[0] == 0x30 { if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) || !input.Empty() || !inner.ReadASN1BitStringAsBytes(&bytes) || !inner.Empty() { return errors.New("sm9: invalid sign master public key asn1 data") } } else if !input.ReadASN1BitStringAsBytes(&bytes) || !input.Empty() { return errors.New("sm9: invalid sign master public key asn1 data") } return pub.UnmarshalRaw(bytes) } // ParseFromPEM just for GMSSL, there are no Algorithm pkix.AlgorithmIdentifier func (pub *SignMasterPublicKey) ParseFromPEM(data []byte) error { block, _ := pem.Decode([]byte(data)) if block == nil { return errors.New("sm9: failed to parse PEM block") } return pub.UnmarshalASN1(block.Bytes) } // MasterPublic returns the master public key corresponding to priv. func (priv *SignPrivateKey) MasterPublic() *SignMasterPublicKey { return priv.SignMasterPublicKey } // SetMasterPublicKey bind the sign master public key to it. func (priv *SignPrivateKey) SetMasterPublicKey(pub *SignMasterPublicKey) { if priv.SignMasterPublicKey == nil || priv.SignMasterPublicKey.MasterPublicKey == nil { priv.SignMasterPublicKey = pub } } // MarshalASN1 marshal sign user private key to asn.1 format data according // SM9 cryptographic algorithm application specification func (priv *SignPrivateKey) MarshalASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BitString(priv.PrivateKey.MarshalUncompressed()) return b.Bytes() } // MarshalCompressedASN1 marshal sign user private key to asn.1 format data according // SM9 cryptographic algorithm application specification, the curve point is in compressed form. func (priv *SignPrivateKey) MarshalCompressedASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BitString(priv.PrivateKey.MarshalCompressed()) return b.Bytes() } func unmarshalG1(bytes []byte) (*bn256.G1, error) { g := new(bn256.G1) switch bytes[0] { case 4: _, err := g.Unmarshal(bytes[1:]) if err != nil { return nil, err } case 2, 3: _, err := g.UnmarshalCompressed(bytes) if err != nil { return nil, err } default: return nil, errors.New("sm9: invalid point identity byte") } return g, nil } // UnmarshalRaw unmarsal raw bytes data to sign user private key // Note, priv's SignMasterPublicKey should be handled separately. func (priv *SignPrivateKey) UnmarshalRaw(bytes []byte) error { g, err := unmarshalG1(bytes) if err != nil { return err } priv.PrivateKey = g return nil } // UnmarshalASN1 unmarsal der data to sign user private key // Note, priv's SignMasterPublicKey should be handled separately. func (priv *SignPrivateKey) UnmarshalASN1(der []byte) error { var bytes []byte var pubBytes []byte var inner cryptobyte.String input := cryptobyte.String(der) if der[0] == 0x30 { if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) || !input.Empty() || !inner.ReadASN1BitStringAsBytes(&bytes) { return errors.New("sm9: invalid sign user private key asn1 data") } if !inner.Empty() && (!inner.ReadASN1BitStringAsBytes(&pubBytes) || !inner.Empty()) { return errors.New("sm9: invalid sign master public key asn1 data") } } else if !input.ReadASN1BitStringAsBytes(&bytes) || !input.Empty() { return errors.New("sm9: invalid sign user private key asn1 data") } err := priv.UnmarshalRaw(bytes) if err != nil { return err } if len(pubBytes) > 0 { masterPK := new(SignMasterPublicKey) err = masterPK.UnmarshalRaw(pubBytes) if err != nil { return err } priv.SetMasterPublicKey(masterPK) } return nil } // GenerateEncryptMasterKey generates a master public and private key pair for encryption usage. func GenerateEncryptMasterKey(rand io.Reader) (*EncryptMasterPrivateKey, error) { k, err := randomScalar(rand) if err != nil { return nil, err } kBytes := k.Bytes(orderNat) priv := new(EncryptMasterPrivateKey) priv.D = new(big.Int).SetBytes(kBytes) priv.EncryptMasterPublicKey = new(EncryptMasterPublicKey) p, err := new(bn256.G1).ScalarBaseMult(kBytes) if err != nil { panic(err) } priv.MasterPublicKey = p return priv, nil } // GenerateUserKey generate an user key for encryption. func (master *EncryptMasterPrivateKey) GenerateUserKey(uid []byte, hid byte) (*EncryptPrivateKey, error) { var id []byte id = append(id, uid...) id = append(id, hid) t1Nat := hashH1(id) d, err := bigmod.NewNat().SetBytes(master.D.Bytes(), orderNat) if err != nil { return nil, err } t1Nat.Add(d, orderNat) if t1Nat.IsZero() == 1 { return nil, errors.New("sm9: need to re-generate encrypt master private key") } t1Nat = bigmod.NewNat().Exp(t1Nat, orderMinus2, orderNat) t1Nat.Mul(d, orderNat) priv := new(EncryptPrivateKey) priv.EncryptMasterPublicKey = master.EncryptMasterPublicKey p, err := new(bn256.G2).ScalarBaseMult(t1Nat.Bytes(orderNat)) if err != nil { panic(err) } priv.PrivateKey = p return priv, nil } // Public returns the public key corresponding to priv. func (master *EncryptMasterPrivateKey) Public() *EncryptMasterPublicKey { return master.EncryptMasterPublicKey } // MarshalASN1 marshal encrypt master private key to asn.1 format data according // SM9 cryptographic algorithm application specification func (master *EncryptMasterPrivateKey) MarshalASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BigInt(master.D) return b.Bytes() } // UnmarshalASN1 unmarsal der data to encrypt master private key func (master *EncryptMasterPrivateKey) UnmarshalASN1(der []byte) error { input := cryptobyte.String(der) d := &big.Int{} var inner cryptobyte.String var pubBytes []byte if der[0] == 0x30 { if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) || !input.Empty() || !inner.ReadASN1Integer(d) { return errors.New("sm9: invalid encrypt master private key asn1 data") } // Just parse it, did't validate it if !inner.Empty() && (!inner.ReadASN1BitStringAsBytes(&pubBytes) || !inner.Empty()) { return errors.New("sm9: invalid encrypt master public key asn1 data") } } else if !input.ReadASN1Integer(d) || !input.Empty() { return errors.New("sm9: invalid encrypt master private key asn1 data") } master.D = d master.EncryptMasterPublicKey = new(EncryptMasterPublicKey) p, err := new(bn256.G1).ScalarBaseMult(bn256.NormalizeScalar(d.Bytes())) if err != nil { return err } master.MasterPublicKey = p return nil } // pair generate the basepoint once func (pub *EncryptMasterPublicKey) pair() *bn256.GT { pub.pairOnce.Do(func() { pub.basePoint = bn256.Pair(pub.MasterPublicKey, bn256.Gen2) }) return pub.basePoint } func (pub *EncryptMasterPublicKey) generatorTable() *[32 * 2]bn256.GTFieldTable { pub.tableGenOnce.Do(func() { pub.table = bn256.GenerateGTFieldTable(pub.pair()) }) return pub.table } // ScalarBaseMult compute basepoint^r with precomputed table. // The base point = pair(, Gen2) func (pub *EncryptMasterPublicKey) ScalarBaseMult(scalar []byte) (*bn256.GT, error) { tables := pub.generatorTable() return bn256.ScalarBaseMultGT(tables, scalar) } // GenerateUserPublicKey generate user encrypt public key func (pub *EncryptMasterPublicKey) GenerateUserPublicKey(uid []byte, hid byte) *bn256.G1 { var buffer []byte buffer = append(buffer, uid...) buffer = append(buffer, hid) h1 := hashH1(buffer) p, err := new(bn256.G1).ScalarBaseMult(h1.Bytes(orderNat)) if err != nil { panic(err) } p.Add(p, pub.MasterPublicKey) return p } // MarshalASN1 marshal encrypt master public key to asn.1 format data according // SM9 cryptographic algorithm application specification func (pub *EncryptMasterPublicKey) MarshalASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BitString(pub.MasterPublicKey.MarshalUncompressed()) return b.Bytes() } // MarshalCompressedASN1 marshal encrypt master public key to asn.1 format data according // SM9 cryptographic algorithm application specification, the curve point is in compressed form. func (pub *EncryptMasterPublicKey) MarshalCompressedASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BitString(pub.MasterPublicKey.MarshalCompressed()) return b.Bytes() } // UnmarshalRaw unmarsal raw bytes data to encrypt master public key func (pub *EncryptMasterPublicKey) UnmarshalRaw(bytes []byte) error { g, err := unmarshalG1(bytes) if err != nil { return err } pub.MasterPublicKey = g return nil } // ParseFromPEM just for GMSSL, there are no Algorithm pkix.AlgorithmIdentifier func (pub *EncryptMasterPublicKey) ParseFromPEM(data []byte) error { block, _ := pem.Decode([]byte(data)) if block == nil { return errors.New("sm9: failed to parse PEM block") } return pub.UnmarshalASN1(block.Bytes) } // UnmarshalASN1 unmarsal der data to encrypt master public key func (pub *EncryptMasterPublicKey) UnmarshalASN1(der []byte) error { var bytes []byte var inner cryptobyte.String input := cryptobyte.String(der) if der[0] == 0x30 { if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) || !input.Empty() || !inner.ReadASN1BitStringAsBytes(&bytes) || !inner.Empty() { return errors.New("sm9: invalid encrypt master public key asn1 data") } } else if !input.ReadASN1BitStringAsBytes(&bytes) || !input.Empty() { return errors.New("sm9: invalid encrypt master public key asn1 data") } return pub.UnmarshalRaw(bytes) } // MasterPublic returns the master public key corresponding to priv. func (priv *EncryptPrivateKey) MasterPublic() *EncryptMasterPublicKey { return priv.EncryptMasterPublicKey } // SetMasterPublicKey bind the encrypt master public key to it. func (priv *EncryptPrivateKey) SetMasterPublicKey(pub *EncryptMasterPublicKey) { if priv.EncryptMasterPublicKey == nil || priv.EncryptMasterPublicKey.MasterPublicKey == nil { priv.EncryptMasterPublicKey = pub } } // MarshalASN1 marshal encrypt user private key to asn.1 format data according // SM9 cryptographic algorithm application specification func (priv *EncryptPrivateKey) MarshalASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BitString(priv.PrivateKey.MarshalUncompressed()) return b.Bytes() } // MarshalCompressedASN1 marshal encrypt user private key to asn.1 format data according // SM9 cryptographic algorithm application specification, the curve point is in compressed form. func (priv *EncryptPrivateKey) MarshalCompressedASN1() ([]byte, error) { var b cryptobyte.Builder b.AddASN1BitString(priv.PrivateKey.MarshalCompressed()) return b.Bytes() } // UnmarshalRaw unmarsal raw bytes data to encrypt user private key // Note, priv's EncryptMasterPublicKey should be handled separately. func (priv *EncryptPrivateKey) UnmarshalRaw(bytes []byte) error { g, err := unmarshalG2(bytes) if err != nil { return err } priv.PrivateKey = g return nil } // UnmarshalASN1 unmarsal der data to encrypt user private key // Note, priv's EncryptMasterPublicKey should be handled separately. func (priv *EncryptPrivateKey) UnmarshalASN1(der []byte) error { var bytes []byte var pubBytes []byte var inner cryptobyte.String input := cryptobyte.String(der) if der[0] == 0x30 { if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) || !input.Empty() || !inner.ReadASN1BitStringAsBytes(&bytes) { return errors.New("sm9: invalid encrypt user private key asn1 data") } if !inner.Empty() && (!inner.ReadASN1BitStringAsBytes(&pubBytes) || !inner.Empty()) { return errors.New("sm9: invalid encrypt master public key asn1 data") } } else if !input.ReadASN1BitStringAsBytes(&bytes) || !input.Empty() { return errors.New("sm9: invalid encrypt user private key asn1 data") } err := priv.UnmarshalRaw(bytes) if err != nil { return err } if len(pubBytes) > 0 { masterPK := new(EncryptMasterPublicKey) err = masterPK.UnmarshalRaw(pubBytes) if err != nil { return err } priv.SetMasterPublicKey(masterPK) } return nil }