aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/crypto.go13
-rw-r--r--crypto/crypto_test.go2
-rw-r--r--crypto/ecies/ecies.go12
-rw-r--r--crypto/ecies/ecies_test.go30
-rw-r--r--crypto/secp256k1/README.md25
-rw-r--r--crypto/secp256k1/secp256.go21
6 files changed, 60 insertions, 43 deletions
diff --git a/crypto/crypto.go b/crypto/crypto.go
index 8685d62d3..c944fd553 100644
--- a/crypto/crypto.go
+++ b/crypto/crypto.go
@@ -171,12 +171,21 @@ func GenerateKey() (*ecdsa.PrivateKey, error) {
return ecdsa.GenerateKey(S256(), rand.Reader)
}
-func ValidateSignatureValues(v byte, r, s *big.Int) bool {
+func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool {
if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 {
return false
}
vint := uint32(v)
- if r.Cmp(secp256k1n) < 0 && s.Cmp(secp256k1n) < 0 && (vint == 27 || vint == 28) {
+ // reject upper range of s values (ECDSA malleability)
+ // see discussion in secp256k1/libsecp256k1/include/secp256k1.h
+ if homestead && s.Cmp(secp256k1.HalfN) > 0 {
+ return false
+ }
+ // Frontier: allow s to be in full N range
+ if s.Cmp(secp256k1.N) >= 0 {
+ return false
+ }
+ if r.Cmp(secp256k1.N) < 0 && (vint == 27 || vint == 28) {
return true
} else {
return false
diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go
index fdd9c1ee8..a366313df 100644
--- a/crypto/crypto_test.go
+++ b/crypto/crypto_test.go
@@ -174,7 +174,7 @@ func TestLoadECDSAFile(t *testing.T) {
func TestValidateSignatureValues(t *testing.T) {
check := func(expected bool, v byte, r, s *big.Int) {
- if ValidateSignatureValues(v, r, s) != expected {
+ if ValidateSignatureValues(v, r, s, false) != expected {
t.Errorf("mismatch for v: %d r: %d s: %d want: %v", v, r, s, expected)
}
}
diff --git a/crypto/ecies/ecies.go b/crypto/ecies/ecies.go
index a3b520dd5..3443a1c1a 100644
--- a/crypto/ecies/ecies.go
+++ b/crypto/ecies/ecies.go
@@ -191,11 +191,9 @@ func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) {
// messageTag computes the MAC of a message (called the tag) as per
// SEC 1, 3.5.
func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte {
- if shared == nil {
- shared = make([]byte, 0)
- }
mac := hmac.New(hash, km)
mac.Write(msg)
+ mac.Write(shared)
tag := mac.Sum(nil)
return tag
}
@@ -242,9 +240,11 @@ func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte,
return
}
-// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. If
-// the shared information parameters aren't being used, they should be
-// nil.
+// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1.
+//
+// s1 and s2 contain shared information that is not part of the resulting
+// ciphertext. s1 is fed into key derivation, s2 is fed into the MAC. If the
+// shared information parameters aren't being used, they should be nil.
func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) {
params := pub.Params
if params == nil {
diff --git a/crypto/ecies/ecies_test.go b/crypto/ecies/ecies_test.go
index 1c391f938..5d46c32ce 100644
--- a/crypto/ecies/ecies_test.go
+++ b/crypto/ecies/ecies_test.go
@@ -353,6 +353,36 @@ func TestEncryptDecrypt(t *testing.T) {
}
}
+func TestDecryptShared2(t *testing.T) {
+ prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ message := []byte("Hello, world.")
+ shared2 := []byte("shared data 2")
+ ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, shared2)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Check that decrypting with correct shared data works.
+ pt, err := prv.Decrypt(rand.Reader, ct, nil, shared2)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(pt, message) {
+ t.Fatal("ecies: plaintext doesn't match message")
+ }
+
+ // Decrypting without shared data or incorrect shared data fails.
+ if _, err = prv.Decrypt(rand.Reader, ct, nil, nil); err == nil {
+ t.Fatal("ecies: decrypting without shared data didn't fail")
+ }
+ if _, err = prv.Decrypt(rand.Reader, ct, nil, []byte("garbage")); err == nil {
+ t.Fatal("ecies: decrypting with incorrect shared data didn't fail")
+ }
+}
+
// TestMarshalEncryption validates the encode/decode produces a valid
// ECIES encryption key.
func TestMarshalEncryption(t *testing.T) {
diff --git a/crypto/secp256k1/README.md b/crypto/secp256k1/README.md
deleted file mode 100644
index 5a86147d4..000000000
--- a/crypto/secp256k1/README.md
+++ /dev/null
@@ -1,25 +0,0 @@
-secp256k1-go
-=======
-
-golang secp256k1 library
-
-Implements cryptographic operations for the secp256k1 ECDSA curve used by Bitcoin.
-
-Installing
-===
-
-GMP library headers are required to build. On Debian-based systems, the package is called `libgmp-dev`.
-
-```
-sudo apt-get install libgmp-dev
-```
-
-Now compiles with cgo!
-
-Test
-===
-
-To run tests do
-```
-go tests
-``` \ No newline at end of file
diff --git a/crypto/secp256k1/secp256.go b/crypto/secp256k1/secp256.go
index 41a5608a5..83f2a5f26 100644
--- a/crypto/secp256k1/secp256.go
+++ b/crypto/secp256k1/secp256.go
@@ -20,14 +20,8 @@ package secp256k1
/*
#cgo CFLAGS: -I./libsecp256k1
-#cgo darwin CFLAGS: -I/usr/local/include
-#cgo freebsd CFLAGS: -I/usr/local/include
-#cgo linux,arm CFLAGS: -I/usr/local/arm/include
-#cgo LDFLAGS: -lgmp
-#cgo darwin LDFLAGS: -L/usr/local/lib
-#cgo freebsd LDFLAGS: -L/usr/local/lib
-#cgo linux,arm LDFLAGS: -L/usr/local/arm/lib
-#define USE_NUM_GMP
+#cgo CFLAGS: -I./libsecp256k1/src/
+#define USE_NUM_NONE
#define USE_FIELD_10X26
#define USE_FIELD_INV_BUILTIN
#define USE_SCALAR_8X32
@@ -44,6 +38,7 @@ import "C"
import (
"errors"
+ "math/big"
"unsafe"
"github.com/ethereum/go-ethereum/crypto/randentropy"
@@ -60,9 +55,17 @@ import (
*/
// holds ptr to secp256k1_context_struct (see secp256k1/include/secp256k1.h)
-var context *C.secp256k1_context
+var (
+ context *C.secp256k1_context
+ N *big.Int
+ HalfN *big.Int
+)
func init() {
+ N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
+ // N / 2 == 57896044618658097711785492504343953926418782139537452191302581570759080747168
+ HalfN, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", 16)
+
// around 20 ms on a modern CPU.
context = C.secp256k1_context_create(3) // SECP256K1_START_SIGN | SECP256K1_START_VERIFY
C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil)