From 98646cfac0ac5c13b3b399dc3a21c0d5916adcf4 Mon Sep 17 00:00:00 2001 From: Sun Yimin Date: Mon, 28 Nov 2022 10:32:17 +0800 Subject: [PATCH] sm9: deprecated sign/verify non-asn1 methods --- sm2/sm2.go | 6 ++- sm9/sm9.go | 122 ++++++++++++++++++++++++++++++----------------------- 2 files changed, 73 insertions(+), 55 deletions(-) diff --git a/sm2/sm2.go b/sm2/sm2.go index adf45a8..1e9d4e4 100644 --- a/sm2/sm2.go +++ b/sm2/sm2.go @@ -505,8 +505,10 @@ func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte, opts crypto.SignerO func signSM2EC(c *sm2Curve, priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error) { e := bigmod.NewNat() hashToNat(c, e, hash) - var k, r, s, dp1Inv, oneNat *bigmod.Nat - var R *_sm2ec.SM2P256Point + var ( + k, r, s, dp1Inv, oneNat *bigmod.Nat + R *_sm2ec.SM2P256Point + ) oneNat, err = bigmod.NewNat().SetBytes(one.Bytes(), c.N) if err != nil { diff --git a/sm9/sm9.go b/sm9/sm9.go index dc00564..dc9391e 100644 --- a/sm9/sm9.go +++ b/sm9/sm9.go @@ -115,21 +115,38 @@ func randomScalar(rand io.Reader) (k *bigmod.Nat, err error) { // 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. +// Please use SignASN1 instead. func Sign(rand io.Reader, priv *SignPrivateKey, hash []byte) (h *big.Int, s *bn256.G1, err error) { + sig, err := SignASN1(rand, priv, hash) + if err != nil { + return nil, nil, err + } + return parseSignature(sig) +} + +// Sign signs digest with user's DSA key, reading randomness from rand. The opts argument +// is not currently used but, in keeping with the crypto.Signer interface. +// The result is SM9Signature ASN.1 format. +func (priv *SignPrivateKey) Sign(rand io.Reader, hash []byte, opts crypto.SignerOpts) ([]byte, error) { + return SignASN1(rand, priv, hash) +} + +// SignASN1 signs a hash (which should be the result of hashing a larger message) +// using the private key, priv. It returns the ASN.1 encoded signature of type SM9Signature. +func SignASN1(rand io.Reader, priv *SignPrivateKey, hash []byte) ([]byte, error) { var ( - r *bigmod.Nat - w *bn256.GT hNat *bigmod.Nat + s *bn256.G1 ) for { - r, err = randomScalar(rand) + r, err := randomScalar(rand) if err != nil { - return + return nil, err } - w, err = priv.SignMasterPublicKey.ScalarBaseMult(r.Bytes(orderNat)) + w, err := priv.SignMasterPublicKey.ScalarBaseMult(r.Bytes(orderNat)) if err != nil { - return + return nil, err } var buffer []byte @@ -140,26 +157,30 @@ func Sign(rand io.Reader, priv *SignPrivateKey, hash []byte) (h *big.Int, s *bn2 r.Sub(hNat, orderNat) if r.IsZero() == 0 { - h = new(big.Int).SetBytes(hNat.Bytes(orderNat)) s, err = new(bn256.G1).ScalarMult(priv.PrivateKey, r.Bytes(orderNat)) + if err != nil { + return nil, err + } break } } - return + + return encodeSignature(hNat.Bytes(orderNat), s) } -// Sign signs digest with user's DSA key, reading randomness from rand. The opts argument -// is not currently used but, in keeping with the crypto.Signer interface. -// The result is SM9Signature ASN.1 format. -func (priv *SignPrivateKey) Sign(rand io.Reader, hash []byte, opts crypto.SignerOpts) ([]byte, error) { - h, s, err := Sign(rand, priv, hash) - if err != nil { - return nil, err - } - +// Verify verifies the signature in h, s of hash using the master dsa public key and user id, uid and hid. +// Its return value records whether the signature is valid. Please use VerifyASN1 instead. +func Verify(pub *SignMasterPublicKey, uid []byte, hid byte, hash []byte, h *big.Int, s *bn256.G1) bool { hBytes := make([]byte, orderNat.Size()) h.FillBytes(hBytes) + sig, err := encodeSignature(hBytes, s) + if err != nil { + return false + } + return VerifyASN1(pub, uid, hid, hash, sig) +} +func encodeSignature(hBytes []byte, s *bn256.G1) ([]byte, error) { var b cryptobyte.Builder b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { b.AddASN1OctetString(hBytes) @@ -168,15 +189,39 @@ func (priv *SignPrivateKey) Sign(rand io.Reader, hash []byte, opts crypto.Signer return b.Bytes() } -// SignASN1 signs a hash (which should be the result of hashing a larger message) -// using the private key, priv. It returns the ASN.1 encoded signature of type SM9Signature. -func SignASN1(rand io.Reader, priv *SignPrivateKey, hash []byte) ([]byte, error) { - return priv.Sign(rand, hash, nil) +func parseSignature(sig []byte) (*big.Int, *bn256.G1, error) { + var ( + hBytes []byte + sBytes []byte + inner cryptobyte.String + ) + input := cryptobyte.String(sig) + if !input.ReadASN1(&inner, asn1.SEQUENCE) || + !input.Empty() || + !inner.ReadASN1Bytes(&hBytes, asn1.OCTET_STRING) || + !inner.ReadASN1BitStringAsBytes(&sBytes) || + !inner.Empty() { + return nil, nil, errors.New("invalid ASN.1") + } + h := new(big.Int).SetBytes(hBytes) + if sBytes[0] != 4 { + return nil, nil, errors.New("sm9: invalid point format") + } + s := new(bn256.G1) + _, err := s.Unmarshal(sBytes[1:]) + if err != nil { + return nil, nil, err + } + return h, s, nil } -// Verify verifies the signature in h, s of hash using the master dsa public key and user id, uid and hid. -// Its return value records whether the signature is valid. -func Verify(pub *SignMasterPublicKey, uid []byte, hid byte, hash []byte, h *big.Int, s *bn256.G1) bool { +// VerifyASN1 verifies the ASN.1 encoded signature of type SM9Signature, sig, of hash using the +// public key, pub. Its return value records whether the signature is valid. +func VerifyASN1(pub *SignMasterPublicKey, uid []byte, hid byte, hash, sig []byte) bool { + h, s, err := parseSignature(sig) + if err != nil { + return false + } if h.Sign() <= 0 || h.Cmp(bn256.Order) >= 0 { return false } @@ -208,35 +253,6 @@ func Verify(pub *SignMasterPublicKey, uid []byte, hid byte, hash []byte, h *big. return h2.Equal(hNat) == 1 } -// VerifyASN1 verifies the ASN.1 encoded signature of type SM9Signature, sig, of hash using the -// public key, pub. Its return value records whether the signature is valid. -func VerifyASN1(pub *SignMasterPublicKey, uid []byte, hid byte, hash, sig []byte) bool { - var ( - hBytes []byte - sBytes []byte - inner cryptobyte.String - ) - input := cryptobyte.String(sig) - if !input.ReadASN1(&inner, asn1.SEQUENCE) || - !input.Empty() || - !inner.ReadASN1Bytes(&hBytes, asn1.OCTET_STRING) || - !inner.ReadASN1BitStringAsBytes(&sBytes) || - !inner.Empty() { - return false - } - h := new(big.Int).SetBytes(hBytes) - if sBytes[0] != 4 { - return false - } - s := new(bn256.G1) - _, err := s.Unmarshal(sBytes[1:]) - if err != nil { - return false - } - - return Verify(pub, uid, hid, hash, h, s) -} - // Verify verifies the ASN.1 encoded signature, sig, of hash using the // public key, pub. Its return value records whether the signature is valid. func (pub *SignMasterPublicKey) Verify(uid []byte, hid byte, hash, sig []byte) bool {