Remove deprecated files and update README to reflect current implementation status and features. This commit deletes unused context, ecmult, and test files, streamlining the codebase. The README has been revised to include architectural details, performance benchmarks, and security considerations for the secp256k1 implementation.
This commit is contained in:
278
hash.go
Normal file
278
hash.go
Normal file
@@ -0,0 +1,278 @@
|
||||
package p256k1
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"hash"
|
||||
)
|
||||
|
||||
// SHA256 represents a SHA-256 hash context
|
||||
type SHA256 struct {
|
||||
hasher hash.Hash
|
||||
}
|
||||
|
||||
// NewSHA256 creates a new SHA-256 hash context
|
||||
func NewSHA256() *SHA256 {
|
||||
return &SHA256{
|
||||
hasher: sha256.New(),
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize initializes the SHA-256 context
|
||||
func (h *SHA256) Initialize() {
|
||||
h.hasher.Reset()
|
||||
}
|
||||
|
||||
// InitializeTagged initializes the SHA-256 context for tagged hashing (BIP-340)
|
||||
func (h *SHA256) InitializeTagged(tag []byte) {
|
||||
// Compute SHA256(tag)
|
||||
tagHash := sha256.Sum256(tag)
|
||||
|
||||
// Initialize with SHA256(tag) || SHA256(tag)
|
||||
h.hasher.Reset()
|
||||
h.hasher.Write(tagHash[:])
|
||||
h.hasher.Write(tagHash[:])
|
||||
}
|
||||
|
||||
// Write adds data to the hash
|
||||
func (h *SHA256) Write(data []byte) {
|
||||
h.hasher.Write(data)
|
||||
}
|
||||
|
||||
// Finalize completes the hash and returns the result
|
||||
func (h *SHA256) Finalize(output []byte) {
|
||||
if len(output) != 32 {
|
||||
panic("SHA-256 output must be 32 bytes")
|
||||
}
|
||||
|
||||
result := h.hasher.Sum(nil)
|
||||
copy(output, result[:])
|
||||
}
|
||||
|
||||
// Clear clears the hash context
|
||||
func (h *SHA256) Clear() {
|
||||
h.hasher.Reset()
|
||||
}
|
||||
|
||||
// TaggedSHA256 computes a tagged hash as defined in BIP-340
|
||||
func TaggedSHA256(output []byte, tag []byte, msg []byte) {
|
||||
if len(output) != 32 {
|
||||
panic("output must be 32 bytes")
|
||||
}
|
||||
|
||||
// Compute SHA256(tag)
|
||||
tagHash := sha256.Sum256(tag)
|
||||
|
||||
// Compute SHA256(SHA256(tag) || SHA256(tag) || msg)
|
||||
hasher := sha256.New()
|
||||
hasher.Write(tagHash[:])
|
||||
hasher.Write(tagHash[:])
|
||||
hasher.Write(msg)
|
||||
|
||||
result := hasher.Sum(nil)
|
||||
copy(output, result)
|
||||
}
|
||||
|
||||
// SHA256Simple computes a simple SHA-256 hash
|
||||
func SHA256Simple(output []byte, input []byte) {
|
||||
if len(output) != 32 {
|
||||
panic("output must be 32 bytes")
|
||||
}
|
||||
|
||||
result := sha256.Sum256(input)
|
||||
copy(output, result[:])
|
||||
}
|
||||
|
||||
// HMACSHA256 represents an HMAC-SHA256 context for RFC 6979
|
||||
type HMACSHA256 struct {
|
||||
k [32]byte // HMAC key
|
||||
v [32]byte // HMAC value
|
||||
init bool
|
||||
}
|
||||
|
||||
// NewHMACSHA256 creates a new HMAC-SHA256 context
|
||||
func NewHMACSHA256() *HMACSHA256 {
|
||||
return &HMACSHA256{}
|
||||
}
|
||||
|
||||
// Initialize initializes the HMAC context with key data
|
||||
func (h *HMACSHA256) Initialize(key []byte) {
|
||||
// Initialize V = 0x01 0x01 0x01 ... 0x01
|
||||
for i := range h.v {
|
||||
h.v[i] = 0x01
|
||||
}
|
||||
|
||||
// Initialize K = 0x00 0x00 0x00 ... 0x00
|
||||
for i := range h.k {
|
||||
h.k[i] = 0x00
|
||||
}
|
||||
|
||||
// K = HMAC_K(V || 0x00 || key)
|
||||
h.updateK(0x00, key)
|
||||
|
||||
// V = HMAC_K(V)
|
||||
h.updateV()
|
||||
|
||||
// K = HMAC_K(V || 0x01 || key)
|
||||
h.updateK(0x01, key)
|
||||
|
||||
// V = HMAC_K(V)
|
||||
h.updateV()
|
||||
|
||||
h.init = true
|
||||
}
|
||||
|
||||
// updateK updates the K value using HMAC
|
||||
func (h *HMACSHA256) updateK(sep byte, data []byte) {
|
||||
// Create HMAC with current K
|
||||
mac := NewHMACWithKey(h.k[:])
|
||||
mac.Write(h.v[:])
|
||||
mac.Write([]byte{sep})
|
||||
if data != nil {
|
||||
mac.Write(data)
|
||||
}
|
||||
mac.Finalize(h.k[:])
|
||||
}
|
||||
|
||||
// updateV updates the V value using HMAC
|
||||
func (h *HMACSHA256) updateV() {
|
||||
mac := NewHMACWithKey(h.k[:])
|
||||
mac.Write(h.v[:])
|
||||
mac.Finalize(h.v[:])
|
||||
}
|
||||
|
||||
// Generate generates pseudorandom bytes
|
||||
func (h *HMACSHA256) Generate(output []byte) {
|
||||
if !h.init {
|
||||
panic("HMAC not initialized")
|
||||
}
|
||||
|
||||
outputLen := len(output)
|
||||
generated := 0
|
||||
|
||||
for generated < outputLen {
|
||||
// V = HMAC_K(V)
|
||||
h.updateV()
|
||||
|
||||
// Copy V to output
|
||||
toCopy := 32
|
||||
if generated+toCopy > outputLen {
|
||||
toCopy = outputLen - generated
|
||||
}
|
||||
copy(output[generated:generated+toCopy], h.v[:toCopy])
|
||||
generated += toCopy
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize finalizes the HMAC context
|
||||
func (h *HMACSHA256) Finalize() {
|
||||
// Clear sensitive data
|
||||
for i := range h.k {
|
||||
h.k[i] = 0
|
||||
}
|
||||
for i := range h.v {
|
||||
h.v[i] = 0
|
||||
}
|
||||
h.init = false
|
||||
}
|
||||
|
||||
// Clear clears the HMAC context
|
||||
func (h *HMACSHA256) Clear() {
|
||||
h.Finalize()
|
||||
}
|
||||
|
||||
// HMAC represents an HMAC context
|
||||
type HMAC struct {
|
||||
inner *SHA256
|
||||
outer *SHA256
|
||||
keyLen int
|
||||
}
|
||||
|
||||
// NewHMACWithKey creates a new HMAC context with the given key
|
||||
func NewHMACWithKey(key []byte) *HMAC {
|
||||
h := &HMAC{
|
||||
inner: NewSHA256(),
|
||||
outer: NewSHA256(),
|
||||
keyLen: len(key),
|
||||
}
|
||||
|
||||
// Prepare key
|
||||
var k [64]byte
|
||||
if len(key) > 64 {
|
||||
// Hash long keys
|
||||
hasher := sha256.New()
|
||||
hasher.Write(key)
|
||||
result := hasher.Sum(nil)
|
||||
copy(k[:], result)
|
||||
} else {
|
||||
copy(k[:], key)
|
||||
}
|
||||
|
||||
// Create inner and outer keys
|
||||
var ikey, okey [64]byte
|
||||
for i := 0; i < 64; i++ {
|
||||
ikey[i] = k[i] ^ 0x36
|
||||
okey[i] = k[i] ^ 0x5c
|
||||
}
|
||||
|
||||
// Initialize inner hash with inner key
|
||||
h.inner.Initialize()
|
||||
h.inner.Write(ikey[:])
|
||||
|
||||
// Initialize outer hash with outer key
|
||||
h.outer.Initialize()
|
||||
h.outer.Write(okey[:])
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
// Write adds data to the HMAC
|
||||
func (h *HMAC) Write(data []byte) {
|
||||
h.inner.Write(data)
|
||||
}
|
||||
|
||||
// Finalize completes the HMAC and returns the result
|
||||
func (h *HMAC) Finalize(output []byte) {
|
||||
if len(output) != 32 {
|
||||
panic("HMAC output must be 32 bytes")
|
||||
}
|
||||
|
||||
// Get inner hash result
|
||||
var innerResult [32]byte
|
||||
h.inner.Finalize(innerResult[:])
|
||||
|
||||
// Complete outer hash
|
||||
h.outer.Write(innerResult[:])
|
||||
h.outer.Finalize(output)
|
||||
}
|
||||
|
||||
// RFC6979HMACSHA256 implements RFC 6979 deterministic nonce generation
|
||||
type RFC6979HMACSHA256 struct {
|
||||
hmac *HMACSHA256
|
||||
}
|
||||
|
||||
// NewRFC6979HMACSHA256 creates a new RFC 6979 HMAC context
|
||||
func NewRFC6979HMACSHA256() *RFC6979HMACSHA256 {
|
||||
return &RFC6979HMACSHA256{
|
||||
hmac: NewHMACSHA256(),
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize initializes the RFC 6979 context
|
||||
func (r *RFC6979HMACSHA256) Initialize(key []byte) {
|
||||
r.hmac.Initialize(key)
|
||||
}
|
||||
|
||||
// Generate generates deterministic nonce bytes
|
||||
func (r *RFC6979HMACSHA256) Generate(output []byte) {
|
||||
r.hmac.Generate(output)
|
||||
}
|
||||
|
||||
// Finalize finalizes the RFC 6979 context
|
||||
func (r *RFC6979HMACSHA256) Finalize() {
|
||||
r.hmac.Finalize()
|
||||
}
|
||||
|
||||
// Clear clears the RFC 6979 context
|
||||
func (r *RFC6979HMACSHA256) Clear() {
|
||||
r.hmac.Clear()
|
||||
}
|
||||
Reference in New Issue
Block a user