From ad5b5a4895f39180f329f2532e2484430c1ac480 Mon Sep 17 00:00:00 2001
From: Gustav Simonsson <gustav.simonsson@gmail.com>
Date: Tue, 9 Jun 2015 15:41:15 +0200
Subject: Pad precompiled EC recover input and add validations

---
 core/vm/contracts.go | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

(limited to 'core')

diff --git a/core/vm/contracts.go b/core/vm/contracts.go
index 742017dd2..b5cb9ccd2 100644
--- a/core/vm/contracts.go
+++ b/core/vm/contracts.go
@@ -67,21 +67,27 @@ func ripemd160Func(in []byte) []byte {
 const ecRecoverInputLength = 128
 
 func ecrecoverFunc(in []byte) []byte {
-	// "in" is (hash, v, r, s), each 32 bytes
-	// but for ecrecover we want (r, s, v)
 	if len(in) < ecRecoverInputLength {
-		return nil
+		in = common.RightPadBytes(in, 128)
 	}
+	// "in" is (hash, v, r, s), each 32 bytes
+	// but for ecrecover we want (r, s, v)
 
+	r := common.BytesToBig(in[64:96])
+	s := common.BytesToBig(in[96:128])
 	// Treat V as a 256bit integer
-	v := new(big.Int).Sub(common.Bytes2Big(in[32:64]), big.NewInt(27))
-	// Ethereum requires V to be either 0 or 1 => (27 || 28)
-	if !(v.Cmp(Zero) == 0 || v.Cmp(One) == 0) {
+	vbig := common.Bytes2Big(in[32:64])
+	v := byte(vbig.Uint64())
+
+	if !crypto.ValidateSignatureValues(v, r, s) {
+		glog.V(logger.Error).Infof("EC RECOVER FAIL: v, r or s value invalid")
 		return nil
 	}
 
-	// v needs to be moved to the end
-	rsv := append(in[64:128], byte(v.Uint64()))
+	// v needs to be at the end and normalized for libsecp256k1
+	vbignormal := new(big.Int).Sub(vbig, big.NewInt(27))
+	vnormal := byte(vbignormal.Uint64())
+	rsv := append(in[64:128], vnormal)
 	pubKey, err := crypto.Ecrecover(in[:32], rsv)
 	// make sure the public key is a valid one
 	if err != nil {
-- 
cgit v1.2.3


From 6e3b58e491c822cc6e4aa822c31c6dee034e3df9 Mon Sep 17 00:00:00 2001
From: Gustav Simonsson <gustav.simonsson@gmail.com>
Date: Tue, 9 Jun 2015 16:03:05 +0200
Subject: Remove unneeded if check on EC recover padding

---
 core/vm/contracts.go | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

(limited to 'core')

diff --git a/core/vm/contracts.go b/core/vm/contracts.go
index b5cb9ccd2..90e356b1d 100644
--- a/core/vm/contracts.go
+++ b/core/vm/contracts.go
@@ -67,9 +67,7 @@ func ripemd160Func(in []byte) []byte {
 const ecRecoverInputLength = 128
 
 func ecrecoverFunc(in []byte) []byte {
-	if len(in) < ecRecoverInputLength {
-		in = common.RightPadBytes(in, 128)
-	}
+	in = common.RightPadBytes(in, 128)
 	// "in" is (hash, v, r, s), each 32 bytes
 	// but for ecrecover we want (r, s, v)
 
-- 
cgit v1.2.3