summaryrefslogtreecommitdiff
path: root/cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/nonce.go
diff options
context:
space:
mode:
Diffstat (limited to 'cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/nonce.go')
-rw-r--r--cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/nonce.go263
1 files changed, 263 insertions, 0 deletions
diff --git a/cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/nonce.go b/cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/nonce.go
new file mode 100644
index 0000000..81b205d
--- /dev/null
+++ b/cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/nonce.go
@@ -0,0 +1,263 @@
+// Copyright (c) 2013-2014 The btcsuite developers
+// Copyright (c) 2015-2020 The Decred developers
+// Use of this source code is governed by an ISC
+// license that can be found in the LICENSE file.
+
+package secp256k1
+
+import (
+ "bytes"
+ "crypto/sha256"
+ "hash"
+)
+
+// References:
+// [GECC]: Guide to Elliptic Curve Cryptography (Hankerson, Menezes, Vanstone)
+//
+// [ISO/IEC 8825-1]: Information technology — ASN.1 encoding rules:
+// Specification of Basic Encoding Rules (BER), Canonical Encoding Rules
+// (CER) and Distinguished Encoding Rules (DER)
+//
+// [SEC1]: Elliptic Curve Cryptography (May 31, 2009, Version 2.0)
+// https://www.secg.org/sec1-v2.pdf
+
+var (
+ // singleZero is used during RFC6979 nonce generation. It is provided
+ // here to avoid the need to create it multiple times.
+ singleZero = []byte{0x00}
+
+ // zeroInitializer is used during RFC6979 nonce generation. It is provided
+ // here to avoid the need to create it multiple times.
+ zeroInitializer = bytes.Repeat([]byte{0x00}, sha256.BlockSize)
+
+ // singleOne is used during RFC6979 nonce generation. It is provided
+ // here to avoid the need to create it multiple times.
+ singleOne = []byte{0x01}
+
+ // oneInitializer is used during RFC6979 nonce generation. It is provided
+ // here to avoid the need to create it multiple times.
+ oneInitializer = bytes.Repeat([]byte{0x01}, sha256.Size)
+)
+
+// hmacsha256 implements a resettable version of HMAC-SHA256.
+type hmacsha256 struct {
+ inner, outer hash.Hash
+ ipad, opad [sha256.BlockSize]byte
+}
+
+// Write adds data to the running hash.
+func (h *hmacsha256) Write(p []byte) {
+ h.inner.Write(p)
+}
+
+// initKey initializes the HMAC-SHA256 instance to the provided key.
+func (h *hmacsha256) initKey(key []byte) {
+ // Hash the key if it is too large.
+ if len(key) > sha256.BlockSize {
+ h.outer.Write(key)
+ key = h.outer.Sum(nil)
+ }
+ copy(h.ipad[:], key)
+ copy(h.opad[:], key)
+ for i := range h.ipad {
+ h.ipad[i] ^= 0x36
+ }
+ for i := range h.opad {
+ h.opad[i] ^= 0x5c
+ }
+ h.inner.Write(h.ipad[:])
+}
+
+// ResetKey resets the HMAC-SHA256 to its initial state and then initializes it
+// with the provided key. It is equivalent to creating a new instance with the
+// provided key without allocating more memory.
+func (h *hmacsha256) ResetKey(key []byte) {
+ h.inner.Reset()
+ h.outer.Reset()
+ copy(h.ipad[:], zeroInitializer)
+ copy(h.opad[:], zeroInitializer)
+ h.initKey(key)
+}
+
+// Resets the HMAC-SHA256 to its initial state using the current key.
+func (h *hmacsha256) Reset() {
+ h.inner.Reset()
+ h.inner.Write(h.ipad[:])
+}
+
+// Sum returns the hash of the written data.
+func (h *hmacsha256) Sum() []byte {
+ h.outer.Reset()
+ h.outer.Write(h.opad[:])
+ h.outer.Write(h.inner.Sum(nil))
+ return h.outer.Sum(nil)
+}
+
+// newHMACSHA256 returns a new HMAC-SHA256 hasher using the provided key.
+func newHMACSHA256(key []byte) *hmacsha256 {
+ h := new(hmacsha256)
+ h.inner = sha256.New()
+ h.outer = sha256.New()
+ h.initKey(key)
+ return h
+}
+
+// NonceRFC6979 generates a nonce deterministically according to RFC 6979 using
+// HMAC-SHA256 for the hashing function. It takes a 32-byte hash as an input
+// and returns a 32-byte nonce to be used for deterministic signing. The extra
+// and version arguments are optional, but allow additional data to be added to
+// the input of the HMAC. When provided, the extra data must be 32-bytes and
+// version must be 16 bytes or they will be ignored.
+//
+// Finally, the extraIterations parameter provides a method to produce a stream
+// of deterministic nonces to ensure the signing code is able to produce a nonce
+// that results in a valid signature in the extremely unlikely event the
+// original nonce produced results in an invalid signature (e.g. R == 0).
+// Signing code should start with 0 and increment it if necessary.
+func NonceRFC6979(privKey []byte, hash []byte, extra []byte, version []byte, extraIterations uint32) *ModNScalar {
+ // Input to HMAC is the 32-byte private key and the 32-byte hash. In
+ // addition, it may include the optional 32-byte extra data and 16-byte
+ // version. Create a fixed-size array to avoid extra allocs and slice it
+ // properly.
+ const (
+ privKeyLen = 32
+ hashLen = 32
+ extraLen = 32
+ versionLen = 16
+ )
+ var keyBuf [privKeyLen + hashLen + extraLen + versionLen]byte
+
+ // Truncate rightmost bytes of private key and hash if they are too long and
+ // leave left padding of zeros when they're too short.
+ if len(privKey) > privKeyLen {
+ privKey = privKey[:privKeyLen]
+ }
+ if len(hash) > hashLen {
+ hash = hash[:hashLen]
+ }
+ offset := privKeyLen - len(privKey) // Zero left padding if needed.
+ offset += copy(keyBuf[offset:], privKey)
+ offset += hashLen - len(hash) // Zero left padding if needed.
+ offset += copy(keyBuf[offset:], hash)
+ if len(extra) == extraLen {
+ offset += copy(keyBuf[offset:], extra)
+ if len(version) == versionLen {
+ offset += copy(keyBuf[offset:], version)
+ }
+ } else if len(version) == versionLen {
+ // When the version was specified, but not the extra data, leave the
+ // extra data portion all zero.
+ offset += privKeyLen
+ offset += copy(keyBuf[offset:], version)
+ }
+ key := keyBuf[:offset]
+
+ // Step B.
+ //
+ // V = 0x01 0x01 0x01 ... 0x01 such that the length of V, in bits, is
+ // equal to 8*ceil(hashLen/8).
+ //
+ // Note that since the hash length is a multiple of 8 for the chosen hash
+ // function in this optimized implementation, the result is just the hash
+ // length, so avoid the extra calculations. Also, since it isn't modified,
+ // start with a global value.
+ v := oneInitializer
+
+ // Step C (Go zeroes all allocated memory).
+ //
+ // K = 0x00 0x00 0x00 ... 0x00 such that the length of K, in bits, is
+ // equal to 8*ceil(hashLen/8).
+ //
+ // As above, since the hash length is a multiple of 8 for the chosen hash
+ // function in this optimized implementation, the result is just the hash
+ // length, so avoid the extra calculations.
+ k := zeroInitializer[:hashLen]
+
+ // Step D.
+ //
+ // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1))
+ //
+ // Note that key is the "int2octets(x) || bits2octets(h1)" portion along
+ // with potential additional data as described by section 3.6 of the RFC.
+ hasher := newHMACSHA256(k)
+ hasher.Write(oneInitializer)
+ hasher.Write(singleZero[:])
+ hasher.Write(key)
+ k = hasher.Sum()
+
+ // Step E.
+ //
+ // V = HMAC_K(V)
+ hasher.ResetKey(k)
+ hasher.Write(v)
+ v = hasher.Sum()
+
+ // Step F.
+ //
+ // K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1))
+ //
+ // Note that key is the "int2octets(x) || bits2octets(h1)" portion along
+ // with potential additional data as described by section 3.6 of the RFC.
+ hasher.Reset()
+ hasher.Write(v)
+ hasher.Write(singleOne[:])
+ hasher.Write(key[:])
+ k = hasher.Sum()
+
+ // Step G.
+ //
+ // V = HMAC_K(V)
+ hasher.ResetKey(k)
+ hasher.Write(v)
+ v = hasher.Sum()
+
+ // Step H.
+ //
+ // Repeat until the value is nonzero and less than the curve order.
+ var generated uint32
+ for {
+ // Step H1 and H2.
+ //
+ // Set T to the empty sequence. The length of T (in bits) is denoted
+ // tlen; thus, at that point, tlen = 0.
+ //
+ // While tlen < qlen, do the following:
+ // V = HMAC_K(V)
+ // T = T || V
+ //
+ // Note that because the hash function output is the same length as the
+ // private key in this optimized implementation, there is no need to
+ // loop or create an intermediate T.
+ hasher.Reset()
+ hasher.Write(v)
+ v = hasher.Sum()
+
+ // Step H3.
+ //
+ // k = bits2int(T)
+ // If k is within the range [1,q-1], return it.
+ //
+ // Otherwise, compute:
+ // K = HMAC_K(V || 0x00)
+ // V = HMAC_K(V)
+ var secret ModNScalar
+ overflow := secret.SetByteSlice(v)
+ if !overflow && !secret.IsZero() {
+ generated++
+ if generated > extraIterations {
+ return &secret
+ }
+ }
+
+ // K = HMAC_K(V || 0x00)
+ hasher.Reset()
+ hasher.Write(v)
+ hasher.Write(singleZero[:])
+ k = hasher.Sum()
+
+ // V = HMAC_K(V)
+ hasher.ResetKey(k)
+ hasher.Write(v)
+ v = hasher.Sum()
+ }
+}