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:
2025-11-01 19:10:34 +00:00
parent f44b16bae5
commit cf2fed8edf
28 changed files with 5680 additions and 876 deletions

359
hash_test.go Normal file
View File

@@ -0,0 +1,359 @@
package p256k1
import (
"bytes"
"crypto/sha256"
"testing"
)
func TestSHA256Simple(t *testing.T) {
testCases := []struct {
name string
input []byte
expected []byte
}{
{
name: "empty",
input: []byte{},
expected: []byte{
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
},
},
{
name: "abc",
input: []byte("abc"),
expected: []byte{
0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
},
},
{
name: "long_message",
input: []byte("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"),
expected: []byte{
0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var output [32]byte
SHA256Simple(output[:], tc.input)
if !bytes.Equal(output[:], tc.expected) {
t.Errorf("SHA256 mismatch.\nExpected: %x\nGot: %x", tc.expected, output[:])
}
// Compare with Go's crypto/sha256
goHash := sha256.Sum256(tc.input)
if !bytes.Equal(output[:], goHash[:]) {
t.Errorf("SHA256 doesn't match Go's implementation.\nExpected: %x\nGot: %x", goHash[:], output[:])
}
})
}
}
func TestTaggedSHA256(t *testing.T) {
testCases := []struct {
name string
tag []byte
msg []byte
}{
{
name: "BIP340_challenge",
tag: []byte("BIP0340/challenge"),
msg: []byte("test message"),
},
{
name: "BIP340_nonce",
tag: []byte("BIP0340/nonce"),
msg: []byte("another test"),
},
{
name: "custom_tag",
tag: []byte("custom/tag"),
msg: []byte("custom message"),
},
{
name: "empty_message",
tag: []byte("test/tag"),
msg: []byte{},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var output [32]byte
TaggedSHA256(output[:], tc.tag, tc.msg)
// Verify output is not all zeros
allZero := true
for _, b := range output {
if b != 0 {
allZero = false
break
}
}
if allZero {
t.Error("Tagged SHA256 output should not be all zeros")
}
// Test determinism - same inputs should produce same output
var output2 [32]byte
TaggedSHA256(output2[:], tc.tag, tc.msg)
if !bytes.Equal(output[:], output2[:]) {
t.Error("Tagged SHA256 should be deterministic")
}
// Test that different tags produce different outputs (for same message)
if len(tc.tag) > 0 {
differentTag := make([]byte, len(tc.tag))
copy(differentTag, tc.tag)
differentTag[0] ^= 1 // Flip one bit
var outputDifferentTag [32]byte
TaggedSHA256(outputDifferentTag[:], differentTag, tc.msg)
if bytes.Equal(output[:], outputDifferentTag[:]) {
t.Error("Different tags should produce different outputs")
}
}
})
}
}
func TestTaggedSHA256Specification(t *testing.T) {
// Test that tagged SHA256 follows BIP-340 specification:
// tagged_hash(tag, msg) = SHA256(SHA256(tag) || SHA256(tag) || msg)
tag := []byte("BIP0340/challenge")
msg := []byte("test message")
var ourOutput [32]byte
TaggedSHA256(ourOutput[:], tag, msg)
// Compute expected result according to specification
tagHash := sha256.Sum256(tag)
var combined []byte
combined = append(combined, tagHash[:]...)
combined = append(combined, tagHash[:]...)
combined = append(combined, msg...)
expectedOutput := sha256.Sum256(combined)
if !bytes.Equal(ourOutput[:], expectedOutput[:]) {
t.Errorf("Tagged SHA256 doesn't match specification.\nExpected: %x\nGot: %x", expectedOutput[:], ourOutput[:])
}
}
func TestHMACDRBG(t *testing.T) {
// Test HMAC-DRBG functionality - simplified test
seed := []byte("test seed for HMAC-DRBG")
// Test that we can create and use RFC6979 nonce function
var msg32, key32, nonce32 [32]byte
copy(key32[:], seed)
copy(msg32[:], []byte("test message"))
success := rfc6979NonceFunction(nonce32[:], msg32[:], key32[:], nil, nil, 0)
if !success {
t.Error("RFC 6979 nonce generation should succeed")
}
// Verify nonce is not all zeros
allZero := true
for _, b := range nonce32 {
if b != 0 {
allZero = false
break
}
}
if allZero {
t.Error("RFC 6979 nonce should not be all zeros")
}
}
func TestRFC6979NonceFunction(t *testing.T) {
// Test the RFC 6979 nonce function used in ECDSA signing
var msg32, key32, nonce32 [32]byte
// Fill with test data
for i := range msg32 {
msg32[i] = byte(i)
key32[i] = byte(i + 1)
}
// Generate nonce
success := rfc6979NonceFunction(nonce32[:], msg32[:], key32[:], nil, nil, 0)
if !success {
t.Error("RFC 6979 nonce generation should succeed")
}
// Verify nonce is not all zeros
allZero := true
for _, b := range nonce32 {
if b != 0 {
allZero = false
break
}
}
if allZero {
t.Error("RFC 6979 nonce should not be all zeros")
}
// Test determinism - same inputs should produce same nonce
var nonce32_2 [32]byte
success2 := rfc6979NonceFunction(nonce32_2[:], msg32[:], key32[:], nil, nil, 0)
if !success2 {
t.Error("Second RFC 6979 nonce generation should succeed")
}
if !bytes.Equal(nonce32[:], nonce32_2[:]) {
t.Error("RFC 6979 nonce generation should be deterministic")
}
// Test different attempt numbers produce different nonces
var nonce32_attempt1 [32]byte
success = rfc6979NonceFunction(nonce32_attempt1[:], msg32[:], key32[:], nil, nil, 1)
if !success {
t.Error("RFC 6979 nonce generation with attempt=1 should succeed")
}
if bytes.Equal(nonce32[:], nonce32_attempt1[:]) {
t.Error("Different attempt numbers should produce different nonces")
}
}
func TestRFC6979WithExtraData(t *testing.T) {
// Test RFC 6979 with extra entropy
var msg32, key32, nonce32_no_extra, nonce32_with_extra [32]byte
for i := range msg32 {
msg32[i] = byte(i)
key32[i] = byte(i + 1)
}
extraData := []byte("extra entropy for testing")
// Generate nonce without extra data
success := rfc6979NonceFunction(nonce32_no_extra[:], msg32[:], key32[:], nil, nil, 0)
if !success {
t.Error("RFC 6979 nonce generation without extra data should succeed")
}
// Generate nonce with extra data
success = rfc6979NonceFunction(nonce32_with_extra[:], msg32[:], key32[:], nil, extraData, 0)
if !success {
t.Error("RFC 6979 nonce generation with extra data should succeed")
}
// Results should be different
if bytes.Equal(nonce32_no_extra[:], nonce32_with_extra[:]) {
t.Error("Extra data should change the nonce")
}
}
func TestHashEdgeCases(t *testing.T) {
// Test with very large inputs
largeInput := make([]byte, 1000000) // 1MB
for i := range largeInput {
largeInput[i] = byte(i % 256)
}
var output [32]byte
SHA256Simple(output[:], largeInput)
// Should not be all zeros
allZero := true
for _, b := range output {
if b != 0 {
allZero = false
break
}
}
if allZero {
t.Error("SHA256 of large input should not be all zeros")
}
// Test tagged SHA256 with large tag and message
largeTag := make([]byte, 1000)
for i := range largeTag {
largeTag[i] = byte(i % 256)
}
TaggedSHA256(output[:], largeTag, largeInput[:1000]) // Use first 1000 bytes
// Should not be all zeros
allZero = true
for _, b := range output {
if b != 0 {
allZero = false
break
}
}
if allZero {
t.Error("Tagged SHA256 of large inputs should not be all zeros")
}
}
// Benchmark tests
func BenchmarkSHA256Simple(b *testing.B) {
input := []byte("test message for benchmarking SHA-256 performance")
var output [32]byte
b.ResetTimer()
for i := 0; i < b.N; i++ {
SHA256Simple(output[:], input)
}
}
func BenchmarkTaggedSHA256(b *testing.B) {
tag := []byte("BIP0340/challenge")
msg := []byte("test message for benchmarking tagged SHA-256 performance")
var output [32]byte
b.ResetTimer()
for i := 0; i < b.N; i++ {
TaggedSHA256(output[:], tag, msg)
}
}
func BenchmarkHMACDRBGGenerate(b *testing.B) {
// Benchmark RFC6979 nonce generation instead
var msg32, key32, nonce32 [32]byte
for i := range msg32 {
msg32[i] = byte(i)
key32[i] = byte(i + 1)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
rfc6979NonceFunction(nonce32[:], msg32[:], key32[:], nil, nil, 0)
}
}
func BenchmarkRFC6979NonceFunction(b *testing.B) {
var msg32, key32, nonce32 [32]byte
for i := range msg32 {
msg32[i] = byte(i)
key32[i] = byte(i + 1)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
rfc6979NonceFunction(nonce32[:], msg32[:], key32[:], nil, nil, 0)
}
}