github.com/chain5j/chain5j-pkg@v1.0.7/crypto/signature/prime256v1/signature.go (about)

     1  package prime256v1
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"crypto/elliptic"
     6  	"crypto/rand"
     7  	"errors"
     8  	"fmt"
     9  	"math/big"
    10  )
    11  
    12  var (
    13  	errNegativeValue          = errors.New("value may be interpreted as negative")
    14  	errExcessivelyPaddedValue = errors.New("value is excessively padded")
    15  )
    16  
    17  func Sign(prv *ecdsa.PrivateKey, hash []byte) ([]byte, error) {
    18  	if prv.Curve == elliptic.P256() {
    19  		return SignCompact((*PrivateKey)(prv), hash, true)
    20  	}
    21  	return ecdsa.SignASN1(rand.Reader, prv, hash)
    22  }
    23  
    24  func Verify(pub *ecdsa.PublicKey, hash []byte, signature []byte) bool {
    25  	if pub.Curve == elliptic.P256() {
    26  		return VerifySignature(pub, hash, signature)
    27  	}
    28  	return ecdsa.VerifyASN1(pub, hash, signature)
    29  }
    30  
    31  // Serialize returns the ECDSA signature in the more strict DER format.  Note
    32  // that the serialized bytes returned do not include the appended hash type
    33  // used in Decred signature scripts.
    34  //
    35  // encoding/asn1 is broken so we hand roll this output:
    36  //
    37  // 0x30 <length> 0x02 <length r> r 0x02 <length s> s
    38  func (sig *Signature) Serialize() []byte {
    39  	// low 'S' malleability breaker
    40  	sigS := sig.S
    41  	if sigS.Cmp(getOrder(sig.curve)) == 1 {
    42  		sigS = new(big.Int).Sub(getOrder(sig.curve), sigS)
    43  	}
    44  	// Ensure the encoded bytes for the r and s values are canonical and
    45  	// thus suitable for DER encoding.
    46  	rb := canonicalizeInt(sig.R)
    47  	sb := canonicalizeInt(sigS)
    48  
    49  	// total length of returned signature is 1 byte for each magic and
    50  	// length (6 total), plus lengths of r and s
    51  	length := 6 + len(rb) + len(sb)
    52  	b := make([]byte, length)
    53  
    54  	b[0] = 0x30
    55  	b[1] = byte(length - 2)
    56  	b[2] = 0x02
    57  	b[3] = byte(len(rb))
    58  	offset := copy(b[4:], rb) + 4
    59  	b[offset] = 0x02
    60  	b[offset+1] = byte(len(sb))
    61  	copy(b[offset+2:], sb)
    62  	return b
    63  }
    64  
    65  // IsEqual compares this Signature instance to the one passed, returning true
    66  // if both Signatures are equivalent. A signature is equivalent to another, if
    67  // they both have the same scalar value for R and S.
    68  func (sig *Signature) IsEqual(otherSig *Signature) bool {
    69  	return sig.R.Cmp(otherSig.R) == 0 &&
    70  		sig.S.Cmp(otherSig.S) == 0
    71  }
    72  
    73  func parseSig(curve elliptic.Curve, sigStr []byte, der bool) (*Signature, error) {
    74  	// Originally this code used encoding/asn1 in order to parse the
    75  	// signature, but a number of problems were found with this approach.
    76  	// Despite the fact that signatures are stored as DER, the difference
    77  	// between go's idea of a bignum (and that they have sign) doesn't agree
    78  	// with the openssl one (where they do not). The above is true as of
    79  	// Go 1.1. In the end it was simpler to rewrite the code to explicitly
    80  	// understand the format which is this:
    81  	// 0x30 <length of whole message> <0x02> <length of R> <R> 0x2
    82  	// <length of S> <S>.
    83  
    84  	signature := &Signature{
    85  		curve: curve,
    86  	}
    87  
    88  	// minimal message is when both numbers are 1 bytes. adding up to:
    89  	// 0x30 + len + 0x02 + 0x01 + <byte> + 0x2 + 0x01 + <byte>
    90  	if len(sigStr) < 8 {
    91  		return nil, errors.New("malformed signature: too short")
    92  	}
    93  	// 0x30
    94  	index := 0
    95  	if sigStr[index] != 0x30 {
    96  		return nil, errors.New("malformed signature: no header magic")
    97  	}
    98  	index++
    99  	// length of remaining message
   100  	siglen := sigStr[index]
   101  	index++
   102  	if int(siglen+2) > len(sigStr) {
   103  		return nil, errors.New("malformed signature: bad length")
   104  	}
   105  	// trim the slice we're working on so we only look at what matters.
   106  	sigStr = sigStr[:siglen+2]
   107  
   108  	// 0x02
   109  	if sigStr[index] != 0x02 {
   110  		return nil,
   111  			errors.New("malformed signature: no 1st int marker")
   112  	}
   113  	index++
   114  
   115  	// Length of signature R.
   116  	rLen := int(sigStr[index])
   117  	// must be positive, must be able to fit in another 0x2, <len> <s>
   118  	// hence the -3. We assume that the length must be at least one byte.
   119  	index++
   120  	if rLen <= 0 || rLen > len(sigStr)-index-3 {
   121  		return nil, errors.New("malformed signature: bogus R length")
   122  	}
   123  
   124  	// Then R itself.
   125  	rBytes := sigStr[index : index+rLen]
   126  	if der {
   127  		switch err := canonicalPadding(rBytes); err {
   128  		case errNegativeValue:
   129  			return nil, errors.New("signature R is negative")
   130  		case errExcessivelyPaddedValue:
   131  			return nil, errors.New("signature R is excessively padded")
   132  		}
   133  	}
   134  	signature.R = new(big.Int).SetBytes(rBytes)
   135  	index += rLen
   136  	// 0x02. length already checked in previous if.
   137  	if sigStr[index] != 0x02 {
   138  		return nil, errors.New("malformed signature: no 2nd int marker")
   139  	}
   140  	index++
   141  
   142  	// Length of signature S.
   143  	sLen := int(sigStr[index])
   144  	index++
   145  	// S should be the rest of the string.
   146  	if sLen <= 0 || sLen > len(sigStr)-index {
   147  		return nil, errors.New("malformed signature: bogus S length")
   148  	}
   149  
   150  	// Then S itself.
   151  	sBytes := sigStr[index : index+sLen]
   152  	if der {
   153  		switch err := canonicalPadding(sBytes); err {
   154  		case errNegativeValue:
   155  			return nil, errors.New("signature S is negative")
   156  		case errExcessivelyPaddedValue:
   157  			return nil, errors.New("signature S is excessively padded")
   158  		}
   159  	}
   160  	signature.S = new(big.Int).SetBytes(sBytes)
   161  	index += sLen
   162  
   163  	// sanity check length parsing
   164  	if index != len(sigStr) {
   165  		return nil, fmt.Errorf("malformed signature: bad final length %v != %v",
   166  			index, len(sigStr))
   167  	}
   168  
   169  	// Verify also checks this, but we can be more sure that we parsed
   170  	// correctly if we verify here too.
   171  	// FWIW the ecdsa spec states that R and S must be | 1, N - 1 |
   172  	// but crypto/ecdsa only checks for Sign != 0. Mirror that.
   173  	if signature.R.Sign() != 1 {
   174  		return nil, errors.New("signature R isn't 1 or more")
   175  	}
   176  	if signature.S.Sign() != 1 {
   177  		return nil, errors.New("signature S isn't 1 or more")
   178  	}
   179  	if signature.R.Cmp(curve.Params().N) >= 0 {
   180  		return nil, errors.New("signature R is >= curve.N")
   181  	}
   182  	if signature.S.Cmp(curve.Params().N) >= 0 {
   183  		return nil, errors.New("signature S is >= curve.N")
   184  	}
   185  
   186  	return signature, nil
   187  }
   188  
   189  // ParseSignature parses a signature in BER format for the curve type `curve'
   190  // into a Signature type, perfoming some basic sanity checks.  If parsing
   191  // according to the more strict DER format is needed, use ParseDERSignature.
   192  func ParseSignature(curve elliptic.Curve, sigStr []byte) (*Signature, error) {
   193  	return parseSig(curve, sigStr, false)
   194  }
   195  
   196  // ParseDERSignature parses a signature in DER format for the curve type
   197  // `curve` into a Signature type.  If parsing according to the less strict
   198  // BER format is needed, use ParseSignature.
   199  func ParseDERSignature(curve elliptic.Curve, sigStr []byte) (*Signature, error) {
   200  	return parseSig(curve, sigStr, true)
   201  }
   202  
   203  // canonicalizeInt returns the bytes for the passed big integer adjusted as
   204  // necessary to ensure that a big-endian encoded integer can't possibly be
   205  // misinterpreted as a negative number.  This can happen when the most
   206  // significant bit is set, so it is padded by a leading zero byte in this case.
   207  // Also, the returned bytes will have at least a single byte when the passed
   208  // value is 0.  This is required for DER encoding.
   209  func canonicalizeInt(val *big.Int) []byte {
   210  	b := val.Bytes()
   211  	if len(b) == 0 {
   212  		b = []byte{0x00}
   213  	}
   214  	if b[0]&0x80 != 0 {
   215  		paddedBytes := make([]byte, len(b)+1)
   216  		copy(paddedBytes[1:], b)
   217  		b = paddedBytes
   218  	}
   219  	return b
   220  }
   221  
   222  // canonicalPadding checks whether a big-endian encoded integer could
   223  // possibly be misinterpreted as a negative number (even though OpenSSL
   224  // treats all numbers as unsigned), or if there is any unnecessary
   225  // leading zero padding.
   226  func canonicalPadding(b []byte) error {
   227  	switch {
   228  	case b[0]&0x80 == 0x80:
   229  		return errNegativeValue
   230  	case len(b) > 1 && b[0] == 0x00 && b[1]&0x80 != 0x80:
   231  		return errExcessivelyPaddedValue
   232  	default:
   233  		return nil
   234  	}
   235  }
   236  
   237  // recoverKeyFromSignature recovers a public key from the signature "sig" on the
   238  // given message hash "msg". Based on the algorithm found in section 5.1.5 of
   239  // SEC 1 Ver 2.0, page 47-48 (53 and 54 in the pdf). This performs the details
   240  // in the inner loop in Step 1. The counter provided is actually the j parameter
   241  // of the loop * 2 - on the first iteration of j we do the R case, else the -R
   242  // case in step 1.6. This counter is used in the Decred compressed signature
   243  // format and thus we match bitcoind's behaviour here.
   244  func recoverKeyFromSignature(sig *Signature, msg []byte, iter int, doChecks bool) (*PublicKey, error) {
   245  	// 1.1 x = (n * i) + r
   246  	curve := sig.curve
   247  	Rx := new(big.Int).Mul(curve.Params().N,
   248  		new(big.Int).SetInt64(int64(iter/2)))
   249  	Rx.Add(Rx, sig.R)
   250  	// 判断有没有超阶
   251  	if Rx.Cmp(curve.Params().P) != -1 {
   252  		return nil, errors.New("calculated Rx is larger than curve P")
   253  	}
   254  
   255  	// convert 02<Rx> to point R. (step 1.2 and 1.3). If we are on an odd
   256  	// iteration then 1.6 will be done with -R, so we calculate the other
   257  	// term when uncompressing the point.
   258  	Ry, err := decompressPoint(sig.curve, Rx, iter%2 == 1)
   259  	if err != nil {
   260  		return nil, err
   261  	}
   262  
   263  	// 1.4 Check n*R is point at infinity
   264  	if doChecks {
   265  		nRx, nRy := curve.ScalarMult(Rx, Ry, curve.Params().N.Bytes())
   266  		if nRx.Sign() != 0 || nRy.Sign() != 0 {
   267  			return nil, errors.New("n*R does not equal the point at infinity")
   268  		}
   269  	}
   270  
   271  	// 1.5 calculate e from message using the same algorithm as ecdsa
   272  	// signature calculation.
   273  	e := hashToInt(sig.curve, msg)
   274  
   275  	// Step 1.6.1:
   276  	// We calculate the two terms sR and eG separately multiplied by the
   277  	// inverse of r (from the signature). We then add them to calculate
   278  	// Q = r^-1(sR-eG)
   279  	invr := new(big.Int).ModInverse(sig.R, curve.Params().N)
   280  	if invr == nil {
   281  		invr = big.NewInt(int64(0))
   282  	}
   283  	// first term.
   284  	invrS := new(big.Int).Mul(invr, sig.S)
   285  	invrS.Mod(invrS, curve.Params().N)
   286  	sRx, sRy := curve.ScalarMult(Rx, Ry, invrS.Bytes())
   287  
   288  	// second term.
   289  	e.Neg(e)
   290  	e.Mod(e, curve.Params().N)
   291  	e.Mul(e, invr)
   292  	e.Mod(e, curve.Params().N)
   293  	minuseGx, minuseGy := curve.ScalarBaseMult(e.Bytes())
   294  
   295  	// step to prevent the jacobian conversion back and forth.
   296  	Qx, Qy := curve.Add(sRx, sRy, minuseGx, minuseGy)
   297  
   298  	return &PublicKey{
   299  		Curve: curve,
   300  		X:     Qx,
   301  		Y:     Qy,
   302  	}, nil
   303  }
   304  
   305  // SignCompact produces a compact signature of the data in hash with the given
   306  // private key on the given koblitz curve. The isCompressed  parameter should
   307  // be used to detail if the given signature should reference a compressed
   308  // public key or not. If successful the bytes of the compact signature will be
   309  // returned in the format:
   310  // <(byte of 27+public key solution)+4 if compressed >< padded bytes for signature R><padded bytes for signature S>
   311  // where the R and S parameters are padde up to the bitlengh of the curve.
   312  func SignCompact(key *PrivateKey, hash []byte, isCompressedKey bool) ([]byte, error) {
   313  	sig, err := key.Sign(hash)
   314  	if err != nil {
   315  		return nil, err
   316  	}
   317  	privkey := key.ToECDSA()
   318  	curve := privkey.Curve
   319  	// bitcoind checks the bit length of R and S here. The ecdsa signature
   320  	// algorithm returns R and S mod N therefore they will be the bitsize of
   321  	// the curve, and thus correctly sized.
   322  	var H = 1
   323  	for i := 0; i < (H+1)*2; i++ {
   324  		// 通过签名恢复公钥
   325  		pk, err := recoverKeyFromSignature(sig, hash, i, true)
   326  		if err == nil && pk.X.Cmp(key.X) == 0 && pk.Y.Cmp(key.Y) == 0 {
   327  			result := make([]byte, 0, 2*curve.Params().BitSize)
   328  			// 将校验码放在第一位
   329  			// result[0] = 27 + byte(i)
   330  			// if isCompressedKey {
   331  			//	result[0] += 4
   332  			// }
   333  			// Not sure this needs rounding but safer to do so.
   334  			curvelen := (curve.Params().BitSize + 7) / 8
   335  
   336  			// Pad R and S to curvelen if needed.
   337  			bytelen := (sig.R.BitLen() + 7) / 8
   338  			if bytelen < curvelen {
   339  				result = append(result,
   340  					make([]byte, curvelen-bytelen)...)
   341  			}
   342  			result = append(result, sig.R.Bytes()...)
   343  
   344  			bytelen = (sig.S.BitLen() + 7) / 8
   345  			if bytelen < curvelen {
   346  				result = append(result,
   347  					make([]byte, curvelen-bytelen)...)
   348  			}
   349  			result = append(result, sig.S.Bytes()...)
   350  
   351  			// 将校验码放在最后
   352  			verifyCode := byte(i) // add back recid to get 65 bytes sig
   353  			// verifyCode := 27 + byte(i)
   354  			// if isCompressedKey {
   355  			//	verifyCode += 4
   356  			// }
   357  			result = append(result, verifyCode)
   358  			return result, nil
   359  		}
   360  	}
   361  
   362  	return nil, errors.New("no valid solution for pubkey found")
   363  }
   364  
   365  // RecoverCompact verifies the compact signature "signature" of "hash" for the
   366  // Koblitz curve in "curve". If the signature matches then the recovered public
   367  // key will be returned as well as a boolen if the original key was compressed
   368  // or not, else an error will be returned.
   369  func RecoverCompact(curve elliptic.Curve, signature, hash []byte) (*PublicKey, bool, error) {
   370  	bitlen := (curve.Params().BitSize + 7) / 8
   371  	if len(signature) != 1+bitlen*2 {
   372  		return nil, false, errors.New("invalid compact signature size")
   373  	}
   374  
   375  	iteration := int((signature[len(signature)-1]) & ^byte(4))
   376  
   377  	// format is <header byte><bitlen R><bitlen S>
   378  	// 校验码在第一位
   379  	// sig := &Signature{
   380  	//	R: new(big.Int).SetBytes(signature[1 : bitlen+1]),
   381  	//	S: new(big.Int).SetBytes(signature[bitlen+1:]),
   382  	// }
   383  	// 校验码在最后一位
   384  	sig := &Signature{
   385  		curve: curve,
   386  		R:     new(big.Int).SetBytes(signature[:bitlen]),
   387  		S:     new(big.Int).SetBytes(signature[bitlen : bitlen*2]),
   388  	}
   389  
   390  	// The iteration used here was encoded
   391  	key, err := recoverKeyFromSignature(sig, hash, iteration, false)
   392  	if err != nil {
   393  		return nil, false, err
   394  	}
   395  
   396  	return key, ((signature[len(signature)-1]) & 4) == 4, nil
   397  }
   398  
   399  // VerifySignature 验证签名
   400  func VerifySignature(pubkey *ecdsa.PublicKey, hash, signature []byte) bool {
   401  	bitlen := (pubkey.Curve.Params().BitSize + 7) / 8
   402  	if len(signature) != bitlen*2 {
   403  		signature = signature[:len(signature)-1]
   404  	}
   405  
   406  	// 校验码在最后一位
   407  	sig := &Signature{
   408  		R: new(big.Int).SetBytes(signature[:bitlen]),
   409  		S: new(big.Int).SetBytes(signature[bitlen : bitlen*2]),
   410  	}
   411  	verify := sig.Verify(hash, pubkey)
   412  	return verify
   413  }
   414  
   415  // RecoverPubkey 返回未压缩的公钥
   416  func RecoverPubkey(curve elliptic.Curve, hash []byte, signature []byte) ([]byte, error) {
   417  	publicKey, _, err := RecoverCompact(curve, signature, hash)
   418  	if err != nil {
   419  		return nil, err
   420  	}
   421  	return publicKey.SerializeUncompressed(), nil
   422  }