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 }