From 98f3011aabcfb53399c17265705a908c17f9fbaf Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 12 Nov 2014 02:01:27 +0100 Subject: [PATCH] cryptopp recover public key --- libdevcrypto/EC.cpp | 39 ++++++++++++++++++++++++--------------- test/crypto.cpp | 8 ++++---- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index af6d0e65e..a509a5b41 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -153,24 +153,33 @@ bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _mess Public crypto::recover(Signature _signature, bytesConstRef _message) { - secp256k1_start(); + Integer heInt(_message.data(), 32); - int pubkeylen = 65; - byte pubkey[pubkeylen]; - if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64])) - return Public(); + // a different curve would require additional check for v (aka, recid) + Integer r(_signature.data(), 32); + Integer s(_signature.data()+32, 32); + unsigned recid = _signature[64]; -#if ETH_CRYPTO_TRACE - h256* sig = (h256 const*)_signature.data(); - cout << "---- RECOVER -------------------------------" << endl; - cout << "MSG: " << _message << endl; - cout << "R S V: " << sig[0] << " " << sig[1] << " " << (int)(_signature[64] - 27) << "+27" << endl; - cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl; -#endif + byte encodedpoint[33]; + encodedpoint[0] = recid|2; + memcpy(&encodedpoint[1], _signature.data(), 32); + + ECP::Element x; + secp256k1Params.GetCurve().DecodePoint(x, encodedpoint, 33); + + if (!secp256k1Params.GetCurve().VerifyPoint(x)) + BOOST_THROW_EXCEPTION(InvalidState()); - Public ret; - memcpy(&ret, &(pubkey[1]), sizeof(Public)); - return ret; + Integer rn = r.InverseMod(secp256k1Params.GetGroupOrder()); + Integer u1 = secp256k1Params.GetGroupOrder() - (rn.Times(heInt)).Modulo(secp256k1Params.GetGroupOrder()); + Integer u2 = (rn.Times(s)).Modulo(secp256k1Params.GetGroupOrder()); + + ECP::Point p = secp256k1Params.GetCurve().CascadeMultiply(u2, x, u1, secp256k1Params.GetSubgroupGenerator()); + byte recoveredbytes[65]; + secp256k1Params.GetCurve().EncodePoint(recoveredbytes, p, false); + Public recovered; + memcpy(recovered.data(), &recoveredbytes[1], 64); + return recovered; } bool crypto::verifySecret(Secret const& _s, Public const& _p) diff --git a/test/crypto.cpp b/test/crypto.cpp index a84c1fbb5..4e752fd1a 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -172,19 +172,19 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) Integer nB(fromHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2").data(), 32); BOOST_REQUIRE(nHex == nB); - bytes sbytes(fromHex("0x01")); + bytes sbytes(fromHex("0xFFFF")); Secret secret(sha3(sbytes)); // 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2 KeyPair key(secret); - bytes m(fromHex("0x01")); - int tests = 2; + bytes m(fromHex("0xFF")); + int tests = 3; while (m[0]++, tests--) { h256 hm(sha3(m)); Integer hInt(hm.asBytes().data(), 32); h256 k(hm ^ key.sec()); Integer kInt(k.asBytes().data(), 32); - + // raw sign w/cryptopp (doesn't pass through cryptopp hash filter) ECDSA::Signer signer; pp::initializeDLScheme(key.sec(), signer);