From d35482a3585811f837029e3f0e1754d848b2e79a Mon Sep 17 00:00:00 2001 From: Sun Yimin Date: Mon, 24 Oct 2022 11:00:13 +0800 Subject: [PATCH] pkcs8 sm9 master sign/encrypt private key support --- sm9/sm9_key.go | 34 +++++++++++++--- smx509/pkcs8.go | 93 ++++++++++++++++++++++++++++++++++++++++++-- smx509/pkcs8_test.go | 46 ++++++++++++++++++++++ 3 files changed, 165 insertions(+), 8 deletions(-) diff --git a/sm9/sm9_key.go b/sm9/sm9_key.go index d017593..ab3e741 100644 --- a/sm9/sm9_key.go +++ b/sm9/sm9_key.go @@ -81,8 +81,20 @@ func (master *SignMasterPrivateKey) MarshalASN1() ([]byte, error) { func (master *SignMasterPrivateKey) UnmarshalASN1(der []byte) error { input := cryptobyte.String(der) d := &big.Int{} - if !input.ReadASN1Integer(d) || !input.Empty() { - return errors.New("sm9: invalid sign master key asn1 data") + 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.MasterPublicKey = new(bn256.G2).ScalarBaseMult(d) @@ -366,12 +378,24 @@ func (master *EncryptMasterPrivateKey) MarshalASN1() ([]byte, error) { return b.Bytes() } -// UnmarshalASN1 unmarsal der data to encrpt master private key +// UnmarshalASN1 unmarsal der data to encrypt master private key func (master *EncryptMasterPrivateKey) UnmarshalASN1(der []byte) error { input := cryptobyte.String(der) d := &big.Int{} - if !input.ReadASN1Integer(d) || !input.Empty() { - return errors.New("sm9: invalid encrpt master key asn1 data") + 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 key asn1 data") } master.D = d master.MasterPublicKey = new(bn256.G1).ScalarBaseMult(d) diff --git a/smx509/pkcs8.go b/smx509/pkcs8.go index 2dfec00..2c5b1e7 100644 --- a/smx509/pkcs8.go +++ b/smx509/pkcs8.go @@ -86,9 +86,32 @@ func parseSM9PrivateKey(privKey pkcs8) (key interface{}, err error) { key = sm9EncKey return default: + bytes := privKey.Algo.Parameters.FullBytes + detailOID := new(asn1.ObjectIdentifier) + _, err = asn1.Unmarshal(bytes, detailOID) + if err != nil { + return + } + switch { + case oidSM9Sign.Equal(*detailOID): + sm9SignMasterKey := new(sm9.SignMasterPrivateKey) + err = sm9SignMasterKey.UnmarshalASN1(privKey.PrivateKey) + if err != nil { + return + } + key = sm9SignMasterKey + return + case oidSM9Enc.Equal(*detailOID): + sm9EncMasterKey := new(sm9.EncryptMasterPrivateKey) + err = sm9EncMasterKey.UnmarshalASN1(privKey.PrivateKey) + if err != nil { + return + } + key = sm9EncMasterKey + return + } return nil, errors.New("not support yet") } - } // MarshalPKCS8PrivateKey converts a private key to PKCS #8, ASN.1 DER form. @@ -106,9 +129,9 @@ func MarshalPKCS8PrivateKey(key interface{}) ([]byte, error) { case *sm9.EncryptPrivateKey: return marshalPKCS8SM9EncPrivateKey(k) case *sm9.SignMasterPrivateKey: - return nil, errors.New("not implemented") + return marshalPKCS8SM9SignMasterPrivateKey(k) case *sm9.EncryptMasterPrivateKey: - return nil, errors.New("not implemented") + return marshalPKCS8SM9EncMasterPrivateKey(k) } return x509.MarshalPKCS8PrivateKey(key) } @@ -167,6 +190,70 @@ func marshalPKCS8SM9EncPrivateKey(k *sm9.EncryptPrivateKey) ([]byte, error) { return asn1.Marshal(privKey) } +func marshalPKCS8SM9SignMasterPrivateKey(k *sm9.SignMasterPrivateKey) ([]byte, error) { + var privKey pkcs8 + oidBytes, err := asn1.Marshal(oidSM9Sign) + if err != nil { + return nil, errors.New("x509: failed to marshal SM9 OID: " + err.Error()) + } + + privKey.Algo = pkix.AlgorithmIdentifier{ + Algorithm: oidSM9, + Parameters: asn1.RawValue{ + FullBytes: oidBytes, + }, + } + + key := sm9PrivateKey{} + privans1, err := k.MarshalASN1() + if err != nil { + return nil, err + } + pubasn1, err := k.Public().MarshalASN1() + if err != nil { + return nil, err + } + key.PrivateKey.FullBytes = privans1 + key.PublicKey.FullBytes = pubasn1 + + if privKey.PrivateKey, err = asn1.Marshal(key); err != nil { + return nil, errors.New("x509: failed to marshal sm9 sign master private key while building PKCS#8: " + err.Error()) + } + return asn1.Marshal(privKey) +} + +func marshalPKCS8SM9EncMasterPrivateKey(k *sm9.EncryptMasterPrivateKey) ([]byte, error) { + var privKey pkcs8 + oidBytes, err := asn1.Marshal(oidSM9Enc) + if err != nil { + return nil, errors.New("x509: failed to marshal SM9 OID: " + err.Error()) + } + + privKey.Algo = pkix.AlgorithmIdentifier{ + Algorithm: oidSM9, + Parameters: asn1.RawValue{ + FullBytes: oidBytes, + }, + } + + key := sm9PrivateKey{} + privans1, err := k.MarshalASN1() + if err != nil { + return nil, err + } + pubasn1, err := k.Public().MarshalASN1() + if err != nil { + return nil, err + } + key.PrivateKey.FullBytes = privans1 + key.PublicKey.FullBytes = pubasn1 + + if privKey.PrivateKey, err = asn1.Marshal(key); err != nil { + return nil, errors.New("x509: failed to marshal sm9 encrypt master private key while building PKCS#8: " + err.Error()) + } + return asn1.Marshal(privKey) +} + func marshalPKCS8ECPrivateKey(k *ecdsa.PrivateKey) ([]byte, error) { var privKey pkcs8 oid, ok := oidFromNamedCurve(k.Curve) diff --git a/smx509/pkcs8_test.go b/smx509/pkcs8_test.go index dfacbc4..e297a6c 100644 --- a/smx509/pkcs8_test.go +++ b/smx509/pkcs8_test.go @@ -210,3 +210,49 @@ func TestMarshalPKCS8SM9EncPrivateKey(t *testing.T) { t.Fatalf("not same key") } } + +func TestMarshalPKCS8SM9SignMasterPrivateKey(t *testing.T) { + masterKey, err := sm9.GenerateSignMasterKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + res, err := MarshalPKCS8PrivateKey(masterKey) + if err != nil { + t.Fatal(err) + } + masterKey1, err := ParsePKCS8PrivateKey(res) + if err != nil { + t.Fatal(err) + } + masterKey2, ok := masterKey1.(*sm9.SignMasterPrivateKey) + if !ok { + t.Fatalf("not expected key") + } + masterKey2.MasterPublicKey.Marshal() + if !(masterKey.D.Cmp(masterKey2.D) == 0 && masterKey.MasterPublicKey.Equal(masterKey2.MasterPublicKey)) { + t.Fatalf("not same key") + } +} + +func TestMarshalPKCS8SM9EncMasterPrivateKey(t *testing.T) { + masterKey, err := sm9.GenerateEncryptMasterKey(rand.Reader) + if err != nil { + t.Fatal(err) + } + res, err := MarshalPKCS8PrivateKey(masterKey) + if err != nil { + t.Fatal(err) + } + masterKey1, err := ParsePKCS8PrivateKey(res) + if err != nil { + t.Fatal(err) + } + masterKey2, ok := masterKey1.(*sm9.EncryptMasterPrivateKey) + if !ok { + t.Fatalf("not expected key") + } + masterKey2.MasterPublicKey.Marshal() + if !(masterKey.D.Cmp(masterKey2.D) == 0 && masterKey.MasterPublicKey.Equal(masterKey2.MasterPublicKey)) { + t.Fatalf("not same key") + } +}