Files
p256k1/eckey.go
mleku 3966183137 Add benchmark results and performance analysis for ECDSA and ECDH operations
This commit introduces two new files: `BENCHMARK_RESULTS.md` and `benchmark_results.txt`, which document the performance metrics of various cryptographic operations, including ECDSA signing, verification, and ECDH key exchange. The results provide insights into operation times, memory allocations, and comparisons with C implementations. Additionally, new test files for ECDSA and ECDH functionalities have been added, ensuring comprehensive coverage and validation of the implemented algorithms. This enhances the overall robustness and performance understanding of the secp256k1 implementation.
2025-11-01 20:17:24 +00:00

221 lines
4.6 KiB
Go

package p256k1
import (
"crypto/rand"
"errors"
)
// ECSeckeyVerify verifies that a 32-byte array is a valid secret key
func ECSeckeyVerify(seckey []byte) bool {
if len(seckey) != 32 {
return false
}
var scalar Scalar
return scalar.setB32Seckey(seckey)
}
// ECSeckeyNegate negates a secret key in place
func ECSeckeyNegate(seckey []byte) bool {
if len(seckey) != 32 {
return false
}
var scalar Scalar
if !scalar.setB32Seckey(seckey) {
return false
}
scalar.negate(&scalar)
scalar.getB32(seckey)
return true
}
// ECSeckeyGenerate generates a new random secret key
func ECSeckeyGenerate() ([]byte, error) {
seckey := make([]byte, 32)
for {
if _, err := rand.Read(seckey); err != nil {
return nil, err
}
if ECSeckeyVerify(seckey) {
return seckey, nil
}
}
}
// ECKeyPairGenerate generates a new key pair (private key and public key)
func ECKeyPairGenerate() (seckey []byte, pubkey *PublicKey, err error) {
seckey, err = ECSeckeyGenerate()
if err != nil {
return nil, nil, err
}
pubkey = &PublicKey{}
if err := ECPubkeyCreate(pubkey, seckey); err != nil {
return nil, nil, err
}
return seckey, pubkey, nil
}
// ECSeckeyTweakAdd adds a tweak to a secret key: seckey = seckey + tweak mod n
func ECSeckeyTweakAdd(seckey []byte, tweak []byte) error {
if len(seckey) != 32 {
return errors.New("secret key must be 32 bytes")
}
if len(tweak) != 32 {
return errors.New("tweak must be 32 bytes")
}
var sec, tw Scalar
if !sec.setB32Seckey(seckey) {
return errors.New("invalid secret key")
}
if !tw.setB32Seckey(tweak) {
return errors.New("invalid tweak")
}
// Add tweak
sec.add(&sec, &tw)
// Check if result is valid
if sec.isZero() {
return errors.New("resulting secret key is zero")
}
// Get result
sec.getB32(seckey)
return nil
}
// ECSeckeyTweakMul multiplies a secret key by a tweak: seckey = seckey * tweak mod n
func ECSeckeyTweakMul(seckey []byte, tweak []byte) error {
if len(seckey) != 32 {
return errors.New("secret key must be 32 bytes")
}
if len(tweak) != 32 {
return errors.New("tweak must be 32 bytes")
}
var sec, tw Scalar
if !sec.setB32Seckey(seckey) {
return errors.New("invalid secret key")
}
if !tw.setB32Seckey(tweak) {
return errors.New("invalid tweak")
}
// Multiply by tweak
sec.mul(&sec, &tw)
// Check if result is valid
if sec.isZero() {
return errors.New("resulting secret key is zero")
}
// Get result
sec.getB32(seckey)
return nil
}
// ECPubkeyTweakAdd adds a tweak to a public key: pubkey = pubkey + tweak*G
func ECPubkeyTweakAdd(pubkey *PublicKey, tweak []byte) error {
if len(tweak) != 32 {
return errors.New("tweak must be 32 bytes")
}
var tw Scalar
if !tw.setB32Seckey(tweak) {
return errors.New("invalid tweak")
}
// Load public key
var pubkeyPoint GroupElementAffine
pubkeyPoint.fromBytes(pubkey.data[:])
if pubkeyPoint.isInfinity() {
return errors.New("invalid public key")
}
// Compute tweak*G
var tweakG GroupElementJacobian
EcmultGen(&tweakG, &tw)
// Add to public key
var pubkeyJac GroupElementJacobian
pubkeyJac.setGE(&pubkeyPoint)
// result = pubkey + tweak*G
var result GroupElementJacobian
result.addVar(&pubkeyJac, &tweakG)
// Check if result is infinity
if result.isInfinity() {
return errors.New("resulting public key is infinity")
}
// Convert back to affine and store
var resultAff GroupElementAffine
resultAff.setGEJ(&result)
resultAff.toBytes(pubkey.data[:])
return nil
}
// ECPubkeyTweakMul multiplies a public key by a tweak: pubkey = pubkey * tweak
func ECPubkeyTweakMul(pubkey *PublicKey, tweak []byte) error {
if len(tweak) != 32 {
return errors.New("tweak must be 32 bytes")
}
var tw Scalar
if !tw.setB32Seckey(tweak) {
return errors.New("invalid tweak")
}
// Load public key
var pubkeyPoint GroupElementAffine
pubkeyPoint.fromBytes(pubkey.data[:])
if pubkeyPoint.isInfinity() {
return errors.New("invalid public key")
}
// Multiply by tweak using binary method
var pubkeyJac GroupElementJacobian
pubkeyJac.setGE(&pubkeyPoint)
var result GroupElementJacobian
result.setInfinity()
var base GroupElementJacobian
base = pubkeyJac
// Simple binary method
for i := 0; i < 256; i++ {
if i > 0 {
result.double(&result)
}
bit := tw.getBits(uint(255-i), 1)
if bit != 0 {
if result.isInfinity() {
result = base
} else {
result.addVar(&result, &base)
}
}
}
// Check if result is infinity
if result.isInfinity() {
return errors.New("resulting public key is infinity")
}
// Convert back to affine and store
var resultAff GroupElementAffine
resultAff.setGEJ(&result)
resultAff.toBytes(pubkey.data[:])
return nil
}