package sm9 import ( "encoding/pem" "errors" "io" "math/big" "github.com/emmansun/gmsm/internal/sm9" "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 { privateKey *sm9.SignMasterPrivateKey } // SignMasterPublicKey master public key for sign, generated by KGC type SignMasterPublicKey struct { publicKey *sm9.SignMasterPublicKey } // SignPrivateKey user private key for sign, generated by KGC type SignPrivateKey struct { privateKey *sm9.SignPrivateKey } // EncryptMasterPrivateKey master private key for encryption, generated by KGC type EncryptMasterPrivateKey struct { privateKey *sm9.EncryptMasterPrivateKey } // EncryptMasterPublicKey master private key for encryption, generated by KGC type EncryptMasterPublicKey struct { publicKey *sm9.EncryptMasterPublicKey } // EncryptPrivateKey user private key for encryption, generated by KGC type EncryptPrivateKey struct { privateKey *sm9.EncryptPrivateKey } // GenerateSignMasterKey generates a master public and private key pair for DSA usage. func GenerateSignMasterKey(rand io.Reader) (*SignMasterPrivateKey, error) { priv, err := sm9.GenerateSignMasterKey(rand) if err != nil { return nil, err } return &SignMasterPrivateKey{privateKey: priv}, nil } // Equal compares the receiver SignMasterPrivateKey with another SignMasterPrivateKey // and returns true if they are equal, otherwise it returns false. func (master *SignMasterPrivateKey) Equal(x *SignMasterPrivateKey) bool { return master.privateKey.Equal(x.privateKey) } // Bytes returns the byte representation of the SignMasterPrivateKey. // It converts the private key to a byte slice. func (master *SignMasterPrivateKey) Bytes() []byte { return master.privateKey.Bytes() } // MarshalASN1 marshal sign master private key to asn.1 format data according // SM9 cryptographic algorithm application specification func (master *SignMasterPrivateKey) MarshalASN1() ([]byte, error) { d := new(big.Int).SetBytes(master.privateKey.Bytes()) var b cryptobyte.Builder b.AddASN1BigInt(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 var err error 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, didn'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.privateKey, err = sm9.NewSignMasterPrivateKey(d.Bytes()) if err != nil { return err } return nil } // GenerateUserKey generate an user dsa key. func (master *SignMasterPrivateKey) GenerateUserKey(uid []byte, hid byte) (*SignPrivateKey, error) { priv, err := master.privateKey.GenerateUserKey(uid, hid) if err != nil { return nil, err } return &SignPrivateKey{privateKey: priv}, nil } // Public returns the public key corresponding to priv. func (master *SignMasterPrivateKey) Public() *SignMasterPublicKey { return &SignMasterPublicKey{master.privateKey.Public()} } // Equal compares the receiver SignMasterPublicKey with another SignMasterPublicKey // and returns true if they are equal, otherwise false. func (pub *SignMasterPublicKey) Equal(x *SignMasterPublicKey) bool { return pub.publicKey.Equal(x.publicKey) } // Bytes returns the byte representation of the SignMasterPublicKey. // It calls the Bytes method on the underlying publicKey field. func (pub *SignMasterPublicKey) Bytes() []byte { return pub.publicKey.Bytes() } // 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.publicKey.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.publicKey.MasterPublicKey.MarshalCompressed()) return b.Bytes() } // UnmarshalRaw unmarsal raw bytes data to sign master public key func (pub *SignMasterPublicKey) UnmarshalRaw(bytes []byte) error { if pub.publicKey == nil { pub.publicKey = new(sm9.SignMasterPublicKey) } return pub.publicKey.UnmarshalRaw(bytes) } // 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) } func (priv *SignPrivateKey) Equal(x *SignPrivateKey) bool { return priv.privateKey.Equal(x.privateKey) } func (priv *SignPrivateKey) Bytes() []byte { return priv.privateKey.Bytes() } // MasterPublic returns the master public key corresponding to priv. func (priv *SignPrivateKey) MasterPublic() *SignMasterPublicKey { return &SignMasterPublicKey{priv.privateKey.MasterPublic()} } // SetMasterPublicKey bind the sign master public key to it. func (priv *SignPrivateKey) SetMasterPublicKey(pub *SignMasterPublicKey) { priv.privateKey.SetMasterPublicKey(pub.publicKey) } // 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.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.PrivateKey.MarshalCompressed()) return b.Bytes() } // 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 { if priv.privateKey == nil { priv.privateKey = new(sm9.SignPrivateKey) } return priv.privateKey.UnmarshalRaw(bytes) } // 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) { priv, err := sm9.GenerateEncryptMasterKey(rand) if err != nil { return nil, err } return &EncryptMasterPrivateKey{privateKey: priv}, nil } // Bytes returns the byte representation of the EncryptMasterPrivateKey. // It delegates the call to the Bytes method of the underlying privateKey. func (master *EncryptMasterPrivateKey) Bytes() []byte { return master.privateKey.Bytes() } // Equal compares the receiver EncryptMasterPrivateKey with another EncryptMasterPrivateKey // and returns true if they are equal, otherwise it returns false. func (master *EncryptMasterPrivateKey) Equal(x *EncryptMasterPrivateKey) bool { return master.privateKey.Equal(x.privateKey) } // GenerateUserKey generate an user key for encryption. func (master *EncryptMasterPrivateKey) GenerateUserKey(uid []byte, hid byte) (*EncryptPrivateKey, error) { priv, err := master.privateKey.GenerateUserKey(uid, hid) if err != nil { return nil, err } return &EncryptPrivateKey{privateKey: priv}, nil } // Public returns the public key corresponding to priv. func (master *EncryptMasterPrivateKey) Public() *EncryptMasterPublicKey { return &EncryptMasterPublicKey{publicKey: master.privateKey.Public()} } // MarshalASN1 marshal encrypt master private key to asn.1 format data according // SM9 cryptographic algorithm application specification func (master *EncryptMasterPrivateKey) MarshalASN1() ([]byte, error) { d := new(big.Int).SetBytes(master.privateKey.Bytes()) var b cryptobyte.Builder b.AddASN1BigInt(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") } var err error master.privateKey, err = sm9.NewEncryptMasterPrivateKey(d.Bytes()) if err != nil { return err } return nil } // Equal compares the receiver EncryptMasterPublicKey with another EncryptMasterPublicKey // and returns true if they are equal, otherwise it returns false. func (pub *EncryptMasterPublicKey) Equal(x *EncryptMasterPublicKey) bool { return pub.publicKey.Equal(x.publicKey) } // Bytes returns the byte representation of the EncryptMasterPublicKey. // It delegates the call to the Bytes method of the underlying publicKey. func (pub *EncryptMasterPublicKey) Bytes() []byte { return pub.publicKey.Bytes() } // 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.publicKey.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.publicKey.MasterPublicKey.MarshalCompressed()) return b.Bytes() } // UnmarshalRaw unmarsal raw bytes data to encrypt master public key func (pub *EncryptMasterPublicKey) UnmarshalRaw(bytes []byte) error { if pub.publicKey == nil { pub.publicKey = new(sm9.EncryptMasterPublicKey) } return pub.publicKey.UnmarshalRaw(bytes) } // 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 &EncryptMasterPublicKey{priv.privateKey.MasterPublic()} } // SetMasterPublicKey bind the encrypt master public key to it. func (priv *EncryptPrivateKey) SetMasterPublicKey(pub *EncryptMasterPublicKey) { priv.privateKey.SetMasterPublicKey(pub.publicKey) } // 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.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.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 { if priv.privateKey == nil { priv.privateKey = new(sm9.EncryptPrivateKey) } return priv.privateKey.UnmarshalRaw(bytes) } // 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 } // Equal compares the receiver EncryptPrivateKey with another EncryptPrivateKey x // and returns true if they are equal, otherwise false. func (priv *EncryptPrivateKey) Equal(x *EncryptPrivateKey) bool { return priv.privateKey.Equal(x.privateKey) } // Bytes returns the byte representation of the EncryptPrivateKey. // It delegates the call to the Bytes method of the underlying privateKey. func (priv *EncryptPrivateKey) Bytes() []byte { return priv.privateKey.Bytes() }