123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- /*
- Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package sm2
- // reference to ecdsa
- import (
- "crypto"
- "crypto/aes"
- "crypto/cipher"
- "crypto/elliptic"
- "crypto/rand"
- "crypto/sha512"
- "encoding/asn1"
- "errors"
- "io"
- "math/big"
- )
- type combinedMult interface {
- CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int)
- }
- const (
- aesIV = "IV for <SM2> CTR"
- )
- type PublicKey struct {
- elliptic.Curve
- X, Y *big.Int
- }
- type PrivateKey struct {
- PublicKey
- D *big.Int
- }
- type sm2Signature struct {
- R, S *big.Int
- }
- // The SM2's private key contains the public key
- func (priv *PrivateKey) Public() crypto.PublicKey {
- return &priv.PublicKey
- }
- // sign format = 30 + len(z) + 02 + len(r) + r + 02 + len(s) + s, z being what follows its size, ie 02+len(r)+r+02+len(s)+s
- func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
- r, s, err := Sign(priv, msg)
- if err != nil {
- return nil, err
- }
- return asn1.Marshal(sm2Signature{r, s})
- }
- func (pub *PublicKey) Verify(msg []byte, sign []byte) bool {
- var sm2Sign sm2Signature
- _, err := asn1.Unmarshal(sign, &sm2Sign)
- if err != nil {
- return false
- }
- return Verify(pub, msg, sm2Sign.R, sm2Sign.S)
- }
- var one = new(big.Int).SetInt64(1)
- func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) {
- params := c.Params()
- b := make([]byte, params.BitSize/8+8)
- _, err = io.ReadFull(rand, b)
- if err != nil {
- return
- }
- k = new(big.Int).SetBytes(b)
- n := new(big.Int).Sub(params.N, one)
- k.Mod(k, n)
- k.Add(k, one)
- return
- }
- func GenerateKey() (*PrivateKey, error) {
- c := P256Sm2()
- k, err := randFieldElement(c, rand.Reader)
- if err != nil {
- return nil, err
- }
- priv := new(PrivateKey)
- priv.PublicKey.Curve = c
- priv.D = k
- priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
- return priv, nil
- }
- var errZeroParam = errors.New("zero parameter")
- func Sign(priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
- entropylen := (priv.Curve.Params().BitSize + 7) / 16
- if entropylen > 32 {
- entropylen = 32
- }
- entropy := make([]byte, entropylen)
- _, err = io.ReadFull(rand.Reader, entropy)
- if err != nil {
- return
- }
- // Initialize an SHA-512 hash context; digest ...
- md := sha512.New()
- md.Write(priv.D.Bytes()) // the private key,
- md.Write(entropy) // the entropy,
- md.Write(hash) // and the input hash;
- key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512),
- // which is an indifferentiable MAC.
- // Create an AES-CTR instance to use as a CSPRNG.
- block, err := aes.NewCipher(key)
- if err != nil {
- return nil, nil, err
- }
- // Create a CSPRNG that xors a stream of zeros with
- // the output of the AES-CTR instance.
- csprng := cipher.StreamReader{
- R: zeroReader,
- S: cipher.NewCTR(block, []byte(aesIV)),
- }
- // See [NSA] 3.4.1
- c := priv.PublicKey.Curve
- N := c.Params().N
- if N.Sign() == 0 {
- return nil, nil, errZeroParam
- }
- var k *big.Int
- e := new(big.Int).SetBytes(hash)
- for { // 调整算法细节以实现SM2
- for {
- k, err = randFieldElement(c, csprng)
- if err != nil {
- r = nil
- return
- }
- r, _ = priv.Curve.ScalarBaseMult(k.Bytes())
- r.Add(r, e)
- r.Mod(r, N)
- if r.Sign() != 0 {
- break
- }
- if t := new(big.Int).Add(r, k); t.Cmp(N) == 0 {
- break
- }
- }
- rD := new(big.Int).Mul(priv.D, r)
- s = new(big.Int).Sub(k, rD)
- d1 := new(big.Int).Add(priv.D, one)
- d1Inv := new(big.Int).ModInverse(d1, N)
- s.Mul(s, d1Inv)
- s.Mod(s, N)
- if s.Sign() != 0 {
- break
- }
- }
- return
- }
- func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
- c := pub.Curve
- N := c.Params().N
- if r.Sign() <= 0 || s.Sign() <= 0 {
- return false
- }
- if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 {
- return false
- }
- // 调整算法细节以实现SM2
- t := new(big.Int).Add(r, s)
- t.Mod(t, N)
- if N.Sign() == 0 {
- return false
- }
- var x *big.Int
- if opt, ok := c.(combinedMult); ok {
- x, _ = opt.CombinedMult(pub.X, pub.Y, s.Bytes(), t.Bytes())
- } else {
- x1, y1 := c.ScalarBaseMult(s.Bytes())
- x2, y2 := c.ScalarMult(pub.X, pub.Y, t.Bytes())
- x, _ = c.Add(x1, y1, x2, y2)
- }
- e := new(big.Int).SetBytes(hash)
- x.Add(x, e)
- x.Mod(x, N)
- return x.Cmp(r) == 0
- }
- type zr struct {
- io.Reader
- }
- func (z *zr) Read(dst []byte) (n int, err error) {
- for i := range dst {
- dst[i] = 0
- }
- return len(dst), nil
- }
- var zeroReader = &zr{}
|