@ -172,3 +172,67 @@ func (pubKey PubKey) Equals(other crypto.PubKey) bool {
func ( pubKey PubKey ) Type ( ) string {
return KeyType
}
// used to reject malleable signatures
// see:
// - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93
// - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/crypto.go#L39
var secp256k1halfN = new ( big . Int ) . Rsh ( secp256k1 . S256 ( ) . N , 1 )
// Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg.
// The returned signature will be of the form R || S (in lower-S form).
func ( privKey PrivKey ) Sign ( msg [ ] byte ) ( [ ] byte , error ) {
priv , _ := secp256k1 . PrivKeyFromBytes ( secp256k1 . S256 ( ) , privKey )
sig , err := priv . Sign ( crypto . Sha256 ( msg ) )
if err != nil {
return nil , err
}
sigBytes := serializeSig ( sig )
return sigBytes , nil
}
// VerifySignature verifies a signature of the form R || S.
// It rejects signatures which are not in lower-S form.
func ( pubKey PubKey ) VerifySignature ( msg [ ] byte , sigStr [ ] byte ) bool {
if len ( sigStr ) != 64 {
return false
}
pub , err := secp256k1 . ParsePubKey ( pubKey , secp256k1 . S256 ( ) )
if err != nil {
return false
}
// parse the signature:
signature := signatureFromBytes ( sigStr )
// Reject malleable signatures. libsecp256k1 does this check but btcec doesn't.
// see: https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93
if signature . S . Cmp ( secp256k1halfN ) > 0 {
return false
}
return signature . Verify ( crypto . Sha256 ( msg ) , pub )
}
// Read Signature struct from R || S. Caller needs to ensure
// that len(sigStr) == 64.
func signatureFromBytes ( sigStr [ ] byte ) * secp256k1 . Signature {
return & secp256k1 . Signature {
R : new ( big . Int ) . SetBytes ( sigStr [ : 32 ] ) ,
S : new ( big . Int ) . SetBytes ( sigStr [ 32 : 64 ] ) ,
}
}
// Serialize signature to R || S.
// R, S are padded to 32 bytes respectively.
func serializeSig ( sig * secp256k1 . Signature ) [ ] byte {
rBytes := sig . R . Bytes ( )
sBytes := sig . S . Bytes ( )
sigBytes := make ( [ ] byte , 64 )
// 0 pad the byte arrays from the left if they aren't big enough.
copy ( sigBytes [ 32 - len ( rBytes ) : 32 ] , rBytes )
copy ( sigBytes [ 64 - len ( sBytes ) : 64 ] , sBytes )
return sigBytes
}