github.com/chain5j/chain5j-pkg@v1.0.7/crypto/signature/rft6979.go (about) 1 // Package signature 2 // 3 // @author: xwc1125 4 package signature 5 6 import ( 7 "bytes" 8 "crypto/ecdsa" 9 "crypto/elliptic" 10 "crypto/hmac" 11 "errors" 12 "hash" 13 "math/big" 14 ) 15 16 var ( 17 // Used in RFC6979 implementation when testing the nonce for correctness 18 one = big.NewInt(1) 19 20 // oneInitializer is used to fill a byte slice with byte 0x01. It is provided 21 // here to avoid the need to create it multiple times. 22 oneInitializer = []byte{0x01} 23 ) 24 25 // NewSignature instantiates a new signature given some R,S values. 26 func NewSignature(curve elliptic.Curve, r, s *big.Int) *SignatureECDSA { 27 order := new(big.Int).Set(curve.Params().N) 28 return &SignatureECDSA{ 29 curve: curve, 30 order: order, 31 halfOrder: new(big.Int).Rsh(order, 1), 32 R: r, 33 S: s, 34 } 35 } 36 37 // SignatureECDSA is a type representing an ecdsa signature. 38 type SignatureECDSA struct { 39 curve elliptic.Curve 40 // Curve order and halfOrder, used to tame ECDSA malleability (see BIP-0062) 41 order *big.Int 42 halfOrder *big.Int 43 R *big.Int 44 S *big.Int 45 } 46 47 func (sig *SignatureECDSA) Verify(hash []byte, pubKey *ecdsa.PublicKey) bool { 48 return ecdsa.Verify(pubKey, hash, sig.GetR(), sig.GetS()) 49 } 50 51 // GetR satisfies the chainec PublicKey interface. 52 func (sig *SignatureECDSA) GetR() *big.Int { 53 return sig.R 54 } 55 56 // GetS satisfies the chainec PublicKey interface. 57 func (sig *SignatureECDSA) GetS() *big.Int { 58 return sig.S 59 } 60 61 func getOrder(curve elliptic.Curve) *big.Int { 62 return new(big.Int).Set(curve.Params().N) 63 } 64 65 func getHalforder(curve elliptic.Curve) *big.Int { 66 return new(big.Int).Rsh(getOrder(curve), 1) 67 } 68 69 // SignRFC6979 produces a compact signature of the data in hash with the given 70 // private key on the given koblitz curve. The isCompressed parameter should 71 // be used to detail if the given signature should reference a compressed 72 // public key or not. If successful the bytes of the compact signature will be 73 // returned in the format: 74 // <(byte of 27+public key solution)+4 if compressed >< padded bytes for signature R><padded bytes for signature S> 75 // where the R and S parameters are padde up to the bitlengh of the curve. 76 func SignRFC6979(key *ecdsa.PrivateKey, hash []byte) ([]byte, error) { 77 curve := key.Curve 78 sig, err := signRFC6979(key, hash) 79 if err != nil { 80 return nil, err 81 } 82 result := make([]byte, 0, 2*curve.Params().BitSize) 83 curvelen := (curve.Params().BitSize + 7) / 8 84 85 // Pad R and S to curvelen if needed. 86 bytelen := (sig.R.BitLen() + 7) / 8 87 if bytelen < curvelen { 88 result = append(result, 89 make([]byte, curvelen-bytelen)...) 90 } 91 result = append(result, sig.R.Bytes()...) 92 bytelen = (sig.S.BitLen() + 7) / 8 93 if bytelen < curvelen { 94 result = append(result, 95 make([]byte, curvelen-bytelen)...) 96 } 97 result = append(result, sig.S.Bytes()...) 98 return result, nil 99 } 100 101 // signRFC6979 generates a deterministic ECDSA signature according to RFC 6979 102 // and BIP 62. 103 func signRFC6979(privkey *ecdsa.PrivateKey, hash []byte) (*SignatureECDSA, error) { 104 curve := privkey.Curve 105 N := new(big.Int).Set(curve.Params().N) 106 // 获取唯一的nonce 107 k := NonceRFC6979(curve, privkey.D, hash, nil, nil) 108 109 inv := new(big.Int).ModInverse(k, N) 110 r, _ := curve.ScalarBaseMult(k.Bytes()) 111 r.Mod(r, N) 112 113 if r.Sign() == 0 { 114 return nil, errors.New("calculated R is zero") 115 } 116 117 e := hashToInt(curve, hash) 118 s := new(big.Int).Mul(privkey.D, r) 119 s.Add(s, e) 120 s.Mul(s, inv) 121 s.Mod(s, N) 122 123 if s.Cmp(getHalforder(curve)) == 1 { 124 s.Sub(N, s) 125 } 126 if s.Sign() == 0 { 127 return nil, errors.New("calculated S is zero") 128 } 129 return &SignatureECDSA{ 130 curve: curve, 131 R: r, 132 S: s, 133 }, nil 134 } 135 136 // NonceRFC6979 generates an ECDSA nonce (`k`) deterministically according to 137 // RFC 6979. It takes a 32-byte hash as an input and returns 32-byte nonce to 138 // be used in ECDSA algorithm. 139 func NonceRFC6979(curve elliptic.Curve, privkey *big.Int, hash []byte, extra []byte, version []byte) *big.Int { 140 q := curve.Params().N 141 x := privkey 142 alg := HashFunc(curve.Params().Name) 143 144 qlen := q.BitLen() 145 holen := alg().Size() 146 rolen := (qlen + 7) >> 3 147 bx := append(int2octets(x, rolen), bits2octets(curve, hash, rolen)...) 148 if len(extra) == 32 { 149 bx = append(bx, extra...) 150 } 151 if len(version) == 16 && len(extra) == 32 { 152 bx = append(bx, extra...) 153 } 154 if len(version) == 16 && len(extra) != 32 { 155 bx = append(bx, bytes.Repeat([]byte{0x00}, 32)...) 156 bx = append(bx, version...) 157 } 158 159 // Step B 160 v := bytes.Repeat(oneInitializer, holen) 161 162 // Step C (Go zeroes the all allocated memory) 163 k := make([]byte, holen) 164 165 // Step D 166 k = mac(alg, k, append(append(v, 0x00), bx...)) 167 168 // Step E 169 v = mac(alg, k, v) 170 171 // Step F 172 k = mac(alg, k, append(append(v, 0x01), bx...)) 173 174 // Step G 175 v = mac(alg, k, v) 176 177 // Step H 178 for { 179 // Step H1 180 var t []byte 181 182 // Step H2 183 for len(t)*8 < qlen { 184 v = mac(alg, k, v) 185 t = append(t, v...) 186 } 187 188 // Step H3 189 secret := hashToInt(curve, t) 190 if secret.Cmp(one) >= 0 && secret.Cmp(q) < 0 { 191 return secret 192 } 193 k = mac(alg, k, append(v, 0x00)) 194 v = mac(alg, k, v) 195 } 196 } 197 198 // mac returns an HMAC of the given key and message. 199 func mac(alg func() hash.Hash, k, m []byte) []byte { 200 h := hmac.New(alg, k) 201 h.Write(m) 202 return h.Sum(nil) 203 } 204 205 // https://tools.ietf.org/html/rfc6979#section-2.3.3 206 func int2octets(v *big.Int, rolen int) []byte { 207 out := v.Bytes() 208 209 // left pad with zeros if it's too short 210 if len(out) < rolen { 211 out2 := make([]byte, rolen) 212 copy(out2[rolen-len(out):], out) 213 return out2 214 } 215 216 // drop most significant bytes if it's too long 217 if len(out) > rolen { 218 out2 := make([]byte, rolen) 219 copy(out2, out[len(out)-rolen:]) 220 return out2 221 } 222 223 return out 224 } 225 226 // https://tools.ietf.org/html/rfc6979#section-2.3.4 227 func bits2octets(curve elliptic.Curve, in []byte, rolen int) []byte { 228 z1 := hashToInt(curve, in) 229 z2 := new(big.Int).Sub(z1, curve.Params().N) 230 if z2.Sign() < 0 { 231 return int2octets(z1, rolen) 232 } 233 return int2octets(z2, rolen) 234 } 235 236 // hashToInt converts a hash value to an integer. There is some disagreement 237 // about how this is done. [NSA] suggests that this is done in the obvious 238 // manner, but [SECG] truncates the hash to the bit-length of the curve order 239 // first. We follow [SECG] because that's what OpenSSL does. Additionally, 240 // OpenSSL right shifts excess bits from the number if the hash is too large 241 // and we mirror that too. 242 // This is borrowed from crypto/ecdsa. 243 func hashToInt(curve elliptic.Curve, hash []byte) *big.Int { 244 orderBits := curve.Params().N.BitLen() 245 orderBytes := (orderBits + 7) / 8 246 if len(hash) > orderBytes { 247 hash = hash[:orderBytes] 248 } 249 250 ret := new(big.Int).SetBytes(hash) 251 excess := len(hash)*8 - orderBits 252 if excess > 0 { 253 ret.Rsh(ret, uint(excess)) 254 } 255 return ret 256 } 257 258 // VerifyRFC6979 验证签名 259 func VerifyRFC6979(pubkey *ecdsa.PublicKey, msg, signature []byte) bool { 260 bitlen := (pubkey.Curve.Params().BitSize + 7) / 8 261 if len(signature) != bitlen*2 { 262 return false 263 } 264 265 // 校验码在最后一位 266 sig := &SignatureECDSA{ 267 curve: pubkey.Curve, 268 R: new(big.Int).SetBytes(signature[:bitlen]), 269 S: new(big.Int).SetBytes(signature[bitlen : bitlen*2]), 270 } 271 verify := sig.Verify(msg, pubkey) 272 return verify 273 }