You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
2.2 KiB

  1. // +build !libsecp256k1
  2. package secp256k1
  3. import (
  4. "math/big"
  5. secp256k1 "github.com/btcsuite/btcd/btcec"
  6. "github.com/tendermint/tendermint/crypto"
  7. )
  8. // used to reject malleable signatures
  9. // see:
  10. // - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93
  11. // - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/crypto.go#L39
  12. var secp256k1halfN = new(big.Int).Rsh(secp256k1.S256().N, 1)
  13. // Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg.
  14. // The returned signature will be of the form R || S (in lower-S form).
  15. func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
  16. priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey)
  17. sig, err := priv.Sign(crypto.Sha256(msg))
  18. if err != nil {
  19. return nil, err
  20. }
  21. sigBytes := serializeSig(sig)
  22. return sigBytes, nil
  23. }
  24. // VerifySignature verifies a signature of the form R || S.
  25. // It rejects signatures which are not in lower-S form.
  26. func (pubKey PubKey) VerifySignature(msg []byte, sigStr []byte) bool {
  27. if len(sigStr) != 64 {
  28. return false
  29. }
  30. pub, err := secp256k1.ParsePubKey(pubKey, secp256k1.S256())
  31. if err != nil {
  32. return false
  33. }
  34. // parse the signature:
  35. signature := signatureFromBytes(sigStr)
  36. // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't.
  37. // see: https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93
  38. if signature.S.Cmp(secp256k1halfN) > 0 {
  39. return false
  40. }
  41. return signature.Verify(crypto.Sha256(msg), pub)
  42. }
  43. // Read Signature struct from R || S. Caller needs to ensure
  44. // that len(sigStr) == 64.
  45. func signatureFromBytes(sigStr []byte) *secp256k1.Signature {
  46. return &secp256k1.Signature{
  47. R: new(big.Int).SetBytes(sigStr[:32]),
  48. S: new(big.Int).SetBytes(sigStr[32:64]),
  49. }
  50. }
  51. // Serialize signature to R || S.
  52. // R, S are padded to 32 bytes respectively.
  53. func serializeSig(sig *secp256k1.Signature) []byte {
  54. rBytes := sig.R.Bytes()
  55. sBytes := sig.S.Bytes()
  56. sigBytes := make([]byte, 64)
  57. // 0 pad the byte arrays from the left if they aren't big enough.
  58. copy(sigBytes[32-len(rBytes):32], rBytes)
  59. copy(sigBytes[64-len(sBytes):64], sBytes)
  60. return sigBytes
  61. }