// 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 secp256k1

import (
	
	
	
)

// 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 ( *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  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.
		.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()
	}
}