Source File
nonce.go
Belonging Package
github.com/decred/dcrd/dcrec/secp256k1/v4
// Copyright (c) 2013-2014 The btcsuite developers// Copyright (c) 2015-2024 The Decred developers// Use of this source code is governed by an ISC// license that can be found in the LICENSE file.package secp256k1import ()// 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.pdfvar (// 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.Hashipad, opad [sha256.BlockSize]byte}// Write adds data to the running hash.func ( *hmacsha256) ( []byte) {.inner.Write()}// initKey initializes the HMAC-SHA256 instance to the provided key.func ( *hmacsha256) ( []byte) {// Hash the key if it is too large.if len() > sha256.BlockSize {.outer.Write()= .outer.Sum(nil)}copy(.ipad[:], )copy(.opad[:], )for := range .ipad {.ipad[] ^= 0x36}for := range .opad {.opad[] ^= 0x5c}.inner.Write(.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 ( *hmacsha256) ( []byte) {.inner.Reset().outer.Reset()copy(.ipad[:], zeroInitializer)copy(.opad[:], zeroInitializer).initKey()}// Resets the HMAC-SHA256 to its initial state using the current key.func ( *hmacsha256) () {.inner.Reset().inner.Write(.ipad[:])}// Sum returns the hash of the written data.func ( *hmacsha256) () []byte {.outer.Reset().outer.Write(.opad[:]).outer.Write(.inner.Sum(nil))return .outer.Sum(nil)}// newHMACSHA256 returns a new HMAC-SHA256 hasher using the provided key.func newHMACSHA256( []byte) *hmacsha256 {:= new(hmacsha256).inner = sha256.New().outer = sha256.New().initKey()return}// 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 ( []byte, []byte, []byte, []byte, 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 (= 32= 32= 32= 16)var [ + + + ]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() > {= [:]}if len() > {= [:]}:= - len() // Zero left padding if needed.+= copy([:], )+= - len() // Zero left padding if needed.+= copy([:], )if len() == {+= copy([:], )if len() == {+= copy([:], )}} else if len() == {// When the version was specified, but not the extra data, leave the// extra data portion all zero.+=+= copy([:], )}:= [:]// 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.:= 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.:= zeroInitializer[:]// 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.:= newHMACSHA256().Write(oneInitializer).Write(singleZero).Write()= .Sum()// Step E.//// V = HMAC_K(V).ResetKey().Write()= .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..Reset().Write().Write(singleOne).Write()= .Sum()// Step G.//// V = HMAC_K(V).ResetKey().Write()= .Sum()// Step H.//// Repeat until the value is nonzero and less than the curve order.var uint32for {// 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..Reset().Write()= .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 ModNScalar:= .SetByteSlice()if ! && !.IsZero() {++if > {return &}}// K = HMAC_K(V || 0x00).Reset().Write().Write(singleZero)= .Sum()// V = HMAC_K(V).ResetKey().Write()= .Sum()}}
![]() |
The pages are generated with Golds v0.8.2. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |