eckey.go raw

   1  package p256k1
   2  
   3  import (
   4  	"crypto/rand"
   5  	"errors"
   6  )
   7  
   8  // ECSeckeyVerify verifies that a 32-byte array is a valid secret key
   9  func ECSeckeyVerify(seckey []byte) bool {
  10  	if len(seckey) != 32 {
  11  		return false
  12  	}
  13  	
  14  	var scalar Scalar
  15  	return scalar.setB32Seckey(seckey)
  16  }
  17  
  18  // ECSeckeyNegate negates a secret key in place
  19  func ECSeckeyNegate(seckey []byte) bool {
  20  	if len(seckey) != 32 {
  21  		return false
  22  	}
  23  	
  24  	var scalar Scalar
  25  	if !scalar.setB32Seckey(seckey) {
  26  		return false
  27  	}
  28  	
  29  	scalar.negate(&scalar)
  30  	scalar.getB32(seckey)
  31  	return true
  32  }
  33  
  34  // ECSeckeyGenerate generates a new random secret key
  35  func ECSeckeyGenerate() ([]byte, error) {
  36  	seckey := make([]byte, 32)
  37  	for {
  38  		if _, err := rand.Read(seckey); err != nil {
  39  			return nil, err
  40  		}
  41  		
  42  		if ECSeckeyVerify(seckey) {
  43  			return seckey, nil
  44  		}
  45  	}
  46  }
  47  
  48  // ECKeyPairGenerate generates a new key pair (private key and public key)
  49  func ECKeyPairGenerate() (seckey []byte, pubkey *PublicKey, err error) {
  50  	seckey, err = ECSeckeyGenerate()
  51  	if err != nil {
  52  		return nil, nil, err
  53  	}
  54  	
  55  	pubkey = &PublicKey{}
  56  	if err := ECPubkeyCreate(pubkey, seckey); err != nil {
  57  		return nil, nil, err
  58  	}
  59  	
  60  	return seckey, pubkey, nil
  61  }
  62  
  63  // ECSeckeyTweakAdd adds a tweak to a secret key: seckey = seckey + tweak mod n
  64  func ECSeckeyTweakAdd(seckey []byte, tweak []byte) error {
  65  	if len(seckey) != 32 {
  66  		return errors.New("secret key must be 32 bytes")
  67  	}
  68  	if len(tweak) != 32 {
  69  		return errors.New("tweak must be 32 bytes")
  70  	}
  71  	
  72  	var sec, tw Scalar
  73  	if !sec.setB32Seckey(seckey) {
  74  		return errors.New("invalid secret key")
  75  	}
  76  	if !tw.setB32Seckey(tweak) {
  77  		return errors.New("invalid tweak")
  78  	}
  79  	
  80  	// Add tweak
  81  	sec.add(&sec, &tw)
  82  	
  83  	// Check if result is valid
  84  	if sec.isZero() {
  85  		return errors.New("resulting secret key is zero")
  86  	}
  87  	
  88  	// Get result
  89  	sec.getB32(seckey)
  90  	return nil
  91  }
  92  
  93  // ECSeckeyTweakMul multiplies a secret key by a tweak: seckey = seckey * tweak mod n
  94  func ECSeckeyTweakMul(seckey []byte, tweak []byte) error {
  95  	if len(seckey) != 32 {
  96  		return errors.New("secret key must be 32 bytes")
  97  	}
  98  	if len(tweak) != 32 {
  99  		return errors.New("tweak must be 32 bytes")
 100  	}
 101  	
 102  	var sec, tw Scalar
 103  	if !sec.setB32Seckey(seckey) {
 104  		return errors.New("invalid secret key")
 105  	}
 106  	if !tw.setB32Seckey(tweak) {
 107  		return errors.New("invalid tweak")
 108  	}
 109  	
 110  	// Multiply by tweak
 111  	sec.mul(&sec, &tw)
 112  	
 113  	// Check if result is valid
 114  	if sec.isZero() {
 115  		return errors.New("resulting secret key is zero")
 116  	}
 117  	
 118  	// Get result
 119  	sec.getB32(seckey)
 120  	return nil
 121  }
 122  
 123  // ECPubkeyTweakAdd adds a tweak to a public key: pubkey = pubkey + tweak*G
 124  func ECPubkeyTweakAdd(pubkey *PublicKey, tweak []byte) error {
 125  	if len(tweak) != 32 {
 126  		return errors.New("tweak must be 32 bytes")
 127  	}
 128  	
 129  	var tw Scalar
 130  	if !tw.setB32Seckey(tweak) {
 131  		return errors.New("invalid tweak")
 132  	}
 133  	
 134  	// Load public key
 135  	var pubkeyPoint GroupElementAffine
 136  	pubkeyPoint.fromBytes(pubkey.data[:])
 137  	if pubkeyPoint.isInfinity() {
 138  		return errors.New("invalid public key")
 139  	}
 140  	
 141  	// Compute tweak*G
 142  	var tweakG GroupElementJacobian
 143  	EcmultGen(&tweakG, &tw)
 144  	
 145  	// Add to public key
 146  	var pubkeyJac GroupElementJacobian
 147  	pubkeyJac.setGE(&pubkeyPoint)
 148  	
 149  	// result = pubkey + tweak*G
 150  	var result GroupElementJacobian
 151  	result.addVar(&pubkeyJac, &tweakG)
 152  	
 153  	// Check if result is infinity
 154  	if result.isInfinity() {
 155  		return errors.New("resulting public key is infinity")
 156  	}
 157  	
 158  	// Convert back to affine and store
 159  	var resultAff GroupElementAffine
 160  	resultAff.setGEJ(&result)
 161  	resultAff.toBytes(pubkey.data[:])
 162  	
 163  	return nil
 164  }
 165  
 166  // ECPubkeyTweakMul multiplies a public key by a tweak: pubkey = pubkey * tweak
 167  func ECPubkeyTweakMul(pubkey *PublicKey, tweak []byte) error {
 168  	if len(tweak) != 32 {
 169  		return errors.New("tweak must be 32 bytes")
 170  	}
 171  	
 172  	var tw Scalar
 173  	if !tw.setB32Seckey(tweak) {
 174  		return errors.New("invalid tweak")
 175  	}
 176  	
 177  	// Load public key
 178  	var pubkeyPoint GroupElementAffine
 179  	pubkeyPoint.fromBytes(pubkey.data[:])
 180  	if pubkeyPoint.isInfinity() {
 181  		return errors.New("invalid public key")
 182  	}
 183  	
 184  	// Multiply by tweak using binary method
 185  	var pubkeyJac GroupElementJacobian
 186  	pubkeyJac.setGE(&pubkeyPoint)
 187  	
 188  	var result GroupElementJacobian
 189  	result.setInfinity()
 190  	var base GroupElementJacobian
 191  	base = pubkeyJac
 192  	
 193  	// Simple binary method
 194  	for i := 0; i < 256; i++ {
 195  		if i > 0 {
 196  			result.double(&result)
 197  		}
 198  		bit := tw.getBits(uint(255-i), 1)
 199  		if bit != 0 {
 200  			if result.isInfinity() {
 201  				result = base
 202  			} else {
 203  				result.addVar(&result, &base)
 204  			}
 205  		}
 206  	}
 207  	
 208  	// Check if result is infinity
 209  	if result.isInfinity() {
 210  		return errors.New("resulting public key is infinity")
 211  	}
 212  	
 213  	// Convert back to affine and store
 214  	var resultAff GroupElementAffine
 215  	resultAff.setGEJ(&result)
 216  	resultAff.toBytes(pubkey.data[:])
 217  	
 218  	return nil
 219  }
 220  
 221