From 67747f8cc57dffb034a586c59183f4d694418317 Mon Sep 17 00:00:00 2001 From: subtly Date: Sun, 2 Nov 2014 04:41:16 +0100 Subject: [PATCH] Placeholder kdf. More cleanup and tests. --- libdevcrypto/Common.cpp | 141 ++++++++++++++------------------------ libdevcrypto/Common.h | 17 +++-- libdevcrypto/CryptoPP.cpp | 80 +++------------------ libdevcrypto/CryptoPP.h | 34 ++++----- libdevcrypto/EC.cpp | 130 ++++++++++++++++++++++++++++++----- libdevcrypto/EC.h | 23 +++++-- libdevcrypto/FileSystem.h | 1 + test/crypto.cpp | 34 ++++----- 8 files changed, 238 insertions(+), 222 deletions(-) diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index c7503a820..e763cc9b2 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -14,51 +14,30 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file CommonEth.cpp +/** @file Common.cpp * @author Gav Wood + * @author Alex Leverington * @date 2014 */ -#include "Common.h" + #include -#include #include "EC.h" #include "SHA3.h" +#include "FileSystem.h" +#include "Common.h" using namespace std; using namespace dev; //#define ETH_ADDRESS_DEBUG 1 -Address dev::toAddress(Secret _private) +Address dev::toAddress(Secret _secret) { - secp256k1_start(); - - byte pubkey[65]; - int pubkeylen = 65; - int ok = secp256k1_ecdsa_seckey_verify(_private.data()); - if (!ok) - return Address(); - ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _private.data(), 0); - if (asserts(pubkeylen == 65)) - return Address(); - if (!ok) - return Address(); - ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65); - if (!ok) - return Address(); - auto ret = right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64))); -#if ETH_ADDRESS_DEBUG - cout << "---- ADDRESS -------------------------------" << endl; - cout << "SEC: " << _private << endl; - cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl; - cout << "ADR: " << ret << endl; -#endif - return ret; + return KeyPair(_secret).address(); } KeyPair KeyPair::create() { - secp256k1_start(); static std::mt19937_64 s_eng(time(0)); std::uniform_int_distribution d(0, 255); @@ -78,25 +57,10 @@ KeyPair KeyPair::create() KeyPair::KeyPair(h256 _sec): m_secret(_sec) { - secp256k1_start(); - int ok = secp256k1_ecdsa_seckey_verify(m_secret.data()); - if (!ok) - return; - - byte pubkey[65]; - int pubkeylen = 65; - ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, m_secret.data(), 0); - if (!ok || pubkeylen != 65) - return; - - ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65); - if (!ok) - return; - - m_secret = m_secret; - memcpy(m_public.data(), &(pubkey[1]), 64); - m_address = right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64))); - + crypto::toPublic(m_secret, m_public); + if (crypto::verifySecret(m_secret, m_public)) + m_address = right160(dev::sha3(m_public.ref())); + #if ETH_ADDRESS_DEBUG cout << "---- ADDRESS -------------------------------" << endl; cout << "SEC: " << m_secret << endl; @@ -129,54 +93,12 @@ bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext) Public dev::recover(Signature _sig, h256 _message) { - secp256k1_start(); - - byte pubkey[65]; - int pubkeylen = 65; - if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _sig.data(), pubkey, &pubkeylen, 0, (int)_sig[64])) - return Public(); - - // right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64))); -#if ETH_CRYPTO_TRACE - h256* sig = (h256 const*)_sig.data(); - cout << "---- RECOVER -------------------------------" << endl; - cout << "MSG: " << _message << endl; - cout << "R S V: " << sig[0] << " " << sig[1] << " " << (int)(_sig[64] - 27) << "+27" << endl; - cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl; -#endif - - Public ret; - memcpy(&ret, &(pubkey[1]), sizeof(Public)); - return ret; -} - -inline h256 kFromMessage(h256 _msg, h256 _priv) -{ - return _msg ^ _priv; + return crypto::recover(_sig, _message.ref()); } Signature dev::sign(Secret _k, h256 _hash) { - int v = 0; - - secp256k1_start(); - - SignatureStruct ret; - h256 nonce = kFromMessage(_hash, _k); - - if (!secp256k1_ecdsa_sign_compact(_hash.data(), 32, ret.r.data(), _k.data(), nonce.data(), &v)) - return Signature(); - -#if ETH_ADDRESS_DEBUG - cout << "---- SIGN -------------------------------" << endl; - cout << "MSG: " << _message << endl; - cout << "SEC: " << _k << endl; - cout << "NON: " << nonce << endl; - cout << "R S V: " << ret.r << " " << ret.s << " " << v << "+27" << endl; -#endif - - ret.v = v; - return *(Signature const*)&ret; + return crypto::sign(_k, _hash); } bool dev::verify(Public _p, Signature _s, h256 _hash) @@ -184,3 +106,40 @@ bool dev::verify(Public _p, Signature _s, h256 _hash) return crypto::verify(_p, _s, bytesConstRef(_hash.data(), 32), true); } +h256 Sec::getNonce(bool _commit) +{ + // todo: atomic efface bit, periodic save, kdf, rr, rng + static h256 seed; + static string seedFile(getDataDir() + "/seed"); + static mutex x; + lock_guard l(x); + { + if (!seed) + { + static Sec sec; + + bytes b = contents(seedFile); + if (b.size() == 32) + memcpy(seed.data(), b.data(), 32); + else + { + std::mt19937_64 s_eng(time(0)); + std::uniform_int_distribution d(0, 255); + for (unsigned i = 0; i < 32; ++i) + seed[i] = (byte)d(s_eng); + } + writeFile(seedFile, bytes()); + } + assert(seed); + h256 prev(seed); + sha3(prev.ref(), seed.ref()); + if (_commit) + writeFile(seedFile, seed.asBytes()); + } + return seed; +} + +Sec::~Sec() +{ + Sec::getNonce(true); +} diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index bd9a4fbd4..e163fb1c4 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -14,8 +14,9 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file CommonEth.h +/** @file Common.h * @author Gav Wood + * @author Alex Leverington * @date 2014 * * Ethereum-specific data structures & algorithms. @@ -63,8 +64,8 @@ void encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher); /// Decrypts cipher using Secret key. bool decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext); -/// Recovers Public key from signed message. -Public recover(Signature _sig, h256 _message); +/// Recovers Public key from signed message hash. +Public recover(Signature _sig, h256 _hash); /// Returns siganture of message hash. Signature sign(Secret _k, h256 _hash); @@ -109,5 +110,13 @@ private: Public m_public; Address m_address; }; + +struct Sec +{ + static h256 getNonce(bool _commit = false); +private: + Sec() {} + ~Sec(); +}; -} +} \ No newline at end of file diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index fa45e6242..1b51d5bd5 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -25,85 +25,21 @@ using namespace dev; using namespace dev::crypto; using namespace CryptoPP; -/// Conversion from bytes to cryptopp point -inline ECP::Point publicToPoint(Public const& _p); -/// Conversion from bytes to cryptopp exponent -inline Integer secretToExponent(Secret const& _s); - -/// Conversion from cryptopp exponent Integer to bytes -inline void exponentToPublic(Integer const& _e, Public& _p); - -void pp::initializeSigner(Secret const& _s, ECDSA::Signer& _signer) -{ - _signer.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1Curve); - _signer.AccessKey().SetPrivateExponent(secretToExponent(_s)); -} - -void pp::initializeVerifier(Public const& _p, ECDSA::Verifier& _verifier) -{ - _verifier.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1Curve); - _verifier.AccessKey().SetPublicElement(publicToPoint(_p)); -} - -void pp::initializeEncryptor(Public const& _p, CryptoPP::ECIES::Encryptor& _encryptor) -{ - _encryptor.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1Curve); - _encryptor.AccessKey().SetPublicElement(publicToPoint(_p)); -} - -void pp::initializeDecryptor(Secret const& _s, CryptoPP::ECIES::Decryptor& _decryptor) -{ - _decryptor.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1Curve); - _decryptor.AccessKey().SetPrivateExponent(secretToExponent(_s)); -} +/// Integer and Point Conversion: void pp::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p) { bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true)); - _k.GetGroupParameters().GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false); - - static_assert(Public::size == 64, "Public key must be 64 bytes."); + secp256k1Params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false); + assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true)); memcpy(_p.data(), &prefixedKey[1], Public::size); } -void pp::exportPrivateKey(CryptoPP::DL_PrivateKey_EC const& _k, Secret& _s) +void pp::exponentToPublic(Integer const& _e, Public& _p) { - _k.GetPrivateExponent().Encode(_s.data(), Secret::size); -} - -/// Integer and Point Conversion: - -inline ECP::Point publicToPoint(Public const& _p) -{ - ECP::Point p; - CryptoPP::DL_PublicKey_EC pub; - pub.AccessGroupParameters().Initialize(pp::secp256k1Curve); - - bytes prefixedKey(pub.GetGroupParameters().GetEncodedElementSize(true)); - prefixedKey[0] = 0x04; - assert(Public::size == prefixedKey.size() - 1); - memcpy(&prefixedKey[1], _p.data(), prefixedKey.size() - 1); - - pub.GetGroupParameters().GetCurve().DecodePoint(p, prefixedKey.data(), prefixedKey.size()); - return std::move(p); -} - -inline Integer secretToExponent(Secret const& _s) -{ - static_assert(Secret::size == 32, "Secret key must be 32 bytes."); - return std::move(Integer(_s.data(), Secret::size)); -} - -inline void exponentToPublic(Integer const& _e, Public& _p) -{ - CryptoPP::DL_PrivateKey_EC k; - k.AccessGroupParameters().Initialize(pp::secp256k1Curve); - k.SetPrivateExponent(_e); - - CryptoPP::DL_PublicKey_EC p; - p.AccessGroupParameters().Initialize(pp::secp256k1Curve); - k.MakePublicKey(p); - pp::exportPublicKey(p, _p); -} + CryptoPP::DL_PublicKey_EC pk; + pk.Initialize(secp256k1Params, secp256k1Params.ExponentiateBase(_e)); + pp::exportPublicKey(pk, _p); +} \ No newline at end of file diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h index e7a5ea94c..756bbb72a 100644 --- a/libdevcrypto/CryptoPP.h +++ b/libdevcrypto/CryptoPP.h @@ -18,7 +18,7 @@ * @author Alex Leverington * @date 2014 * - * CryptoPP headers and helper methods + * CryptoPP headers and primitive helper methods */ #pragma once @@ -45,7 +45,6 @@ #include #include #include -#include #include #pragma warning(pop) #pragma GCC diagnostic pop @@ -55,34 +54,35 @@ namespace dev { namespace crypto { - namespace pp { - + +using namespace CryptoPP; + /// CryptoPP random number pool static CryptoPP::AutoSeededRandomPool PRNG; /// CryptoPP EC Cruve static const CryptoPP::OID secp256k1Curve = CryptoPP::ASN1::secp256k1(); - -/// Initialize signer with Secret -void initializeSigner(Secret const& _s, CryptoPP::ECDSA::Signer& out_signer); -/// Initialize verifier with Public -void initializeVerifier(Public const& _p, CryptoPP::ECDSA::Verifier& _verifier); +static const CryptoPP::DL_GroupParameters_EC secp256k1Params(secp256k1Curve); -/// Initialize cryptopp encryptor with Public -void initializeEncryptor(Public const& _p, CryptoPP::ECIES::Encryptor& out_encryptor); +static ECP::Point publicToPoint(Public const& _p) { Integer x(_p.data(), 32); Integer y(_p.data()+32, 32); return std::move(ECP::Point(x,y)); } -/// Initialize cryptopp decryptor with Secret -void initializeDecryptor(Secret const& _s, CryptoPP::ECIES::Decryptor& out_decryptor); +static Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.data(), Secret::size)); } + +void exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p); -/// Conversion from cryptopp public key to bytes -void exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& out_p); +static void exportPrivateKey(CryptoPP::DL_PrivateKey_EC const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); } -/// Conversion from cryptopp private key to bytes -void exportPrivateKey(CryptoPP::DL_PrivateKey_EC const& _k, Secret& out_s); +void exponentToPublic(Integer const& _e, Public& _p); +template +void initializeDLScheme(Secret const& _s, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, secretToExponent(_s)); } + +template +void initializeDLScheme(Public const& _p, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, publicToPoint(_p)); } + } } } diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index d6c2ad622..e6b4c19c8 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -18,7 +18,7 @@ * @author Alex Leverington * @date 2014 * - * Shared EC classes and functions. + * ECDSA, ECIES */ #pragma warning(push) @@ -32,25 +32,44 @@ #include #pragma warning(pop) #pragma GCC diagnostic pop +#include #include "CryptoPP.h" #include "SHA3.h" +#include "SHA3MAC.h" #include "EC.h" -// CryptoPP and dev conflict so dev and pp namespace are used explicitly +static_assert(dev::Secret::size == 32, "Secret key must be 32 bytes."); +static_assert(dev::Public::size == 64, "Public key must be 64 bytes."); +static_assert(dev::Signature::size == 65, "Signature must be 65 bytes."); + using namespace std; using namespace dev; using namespace dev::crypto; using namespace CryptoPP; +using namespace pp; + +void crypto::toPublic(Secret const& _s, Public& o_public) +{ + exponentToPublic(Integer(_s.data(),sizeof(_s)), o_public); +} -void crypto::encrypt(Public const& _key, bytes& io_cipher) +h256 crypto::kdf(Secret const& _priv, h256 const& _hash) +{ + h256 s; + sha3mac(Sec::getNonce().ref(), _priv.ref(), s.ref()); + assert(s); + return sha3((_hash ^ s).asBytes()); +} + +void crypto::encrypt(Public const& _k, bytes& io_cipher) { ECIES::Encryptor e; - pp::initializeEncryptor(_key, e); + initializeDLScheme(_k, e); size_t plen = io_cipher.size(); bytes c; c.resize(e.CiphertextLength(plen)); // todo: use StringSource with io_cipher as input and output. - e.Encrypt(pp::PRNG, io_cipher.data(), plen, c.data()); + e.Encrypt(PRNG, io_cipher.data(), plen, c.data()); memset(io_cipher.data(), 0, io_cipher.size()); io_cipher = std::move(c); } @@ -58,12 +77,12 @@ void crypto::encrypt(Public const& _key, bytes& io_cipher) void crypto::decrypt(Secret const& _k, bytes& io_text) { CryptoPP::ECIES::Decryptor d; - pp::initializeDecryptor(_k, d); + initializeDLScheme(_k, d); size_t clen = io_text.size(); bytes p; p.resize(d.MaxPlaintextLength(io_text.size())); // todo: use StringSource with io_text as input and output. - DecodingResult r = d.Decrypt(pp::PRNG, io_text.data(), clen, p.data()); + DecodingResult r = d.Decrypt(PRNG, io_text.data(), clen, p.data()); if (!r.isValidCoding) { io_text.clear(); @@ -75,19 +94,51 @@ void crypto::decrypt(Secret const& _k, bytes& io_text) Signature crypto::sign(Secret const& _k, bytesConstRef _message) { - ECDSA::Signer signer; - pp::initializeSigner(_k, signer); + return crypto::sign(_k, sha3(_message)); +} + +Signature crypto::sign(Secret const& _key, h256 const& _hash) +{ + ECDSA::Signer signer; + initializeDLScheme(_key, signer); + + Integer const& q = secp256k1Params.GetGroupOrder(); + Integer e(_hash.asBytes().data(), 32); + + Integer k(kdf(_key, _hash).data(), 32); + k %= secp256k1Params.GetSubgroupOrder()-1; + + ECP::Point rp = secp256k1Params.ExponentiateBase(k); + Integer r = secp256k1Params.ConvertElementToInteger(rp); + int recid = ((r >= q) ? 2 : 0) | (rp.y.IsOdd() ? 1 : 0); + + Integer kInv = k.InverseMod(q); + Integer s = (kInv * (Integer(_key.asBytes().data(), 32)*r + e)) % q; + assert(!!r && !!s); + + if (s > secp256k1Params.GetSubgroupOrder()) + { + s = q - s; + if (recid) + recid ^= 1; + } + + Signature sig; + r.Encode(sig.data(), 32); + s.Encode(sig.data()+32, 32); + sig[64] = recid; + return sig; +} - string sigstr; - StringSource s(_message.toString(), true, new SignerFilter(pp::PRNG, signer, new StringSink(sigstr))); - FixedHash retsig((byte const*)sigstr.data(), Signature::ConstructFromPointer); - return std::move(retsig); +bool crypto::verify(Signature const& _signature, bytesConstRef _message) +{ + return crypto::verify(crypto::recover(_signature, _message), _signature, _message); } -bool crypto::verify(Public _p, Signature _sig, bytesConstRef _message, bool _raw) +bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { static size_t derMaxEncodingLength = 72; - if (_raw) + if (_hashed) { assert(_message.size() == 32); byte encpub[65] = {0x04}; @@ -99,10 +150,53 @@ bool crypto::verify(Public _p, Signature _sig, bytesConstRef _message, bool _raw } ECDSA::Verifier verifier; - pp::initializeVerifier(_p, verifier); - // cryptopp signatures are 64 bytes - static_assert(sizeof(Signature) == 65, "Expected 65-byte signature."); + initializeDLScheme(_p, verifier); return verifier.VerifyMessage(_message.data(), _message.size(), _sig.data(), sizeof(Signature) - 1); } +Public crypto::recover(Signature _signature, bytesConstRef _message) +{ + secp256k1_start(); + + byte pubkey[65]; + int pubkeylen = 65; + if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64])) + return Public(); + +#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 + + Public ret; + memcpy(&ret, &(pubkey[1]), sizeof(Public)); + return ret; +} + +bool crypto::verifySecret(Secret const& _s, Public const& _p) +{ + secp256k1_start(); + int ok = secp256k1_ecdsa_seckey_verify(_s.data()); + if (!ok) + return false; + + byte pubkey[65]; + int pubkeylen = 65; + ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0); + if (!ok || pubkeylen != 65) + return false; + + ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65); + if (!ok) + return false; + + for (int i = 0; i < 32; i++) + if (pubkey[i+1]!=_p[i]) + return false; + + return true; +} diff --git a/libdevcrypto/EC.h b/libdevcrypto/EC.h index d98472a54..2a4155edf 100644 --- a/libdevcrypto/EC.h +++ b/libdevcrypto/EC.h @@ -18,7 +18,7 @@ * @author Alex Leverington * @date 2014 * - * Shared EC classes and functions. + * ECDSA, ECIES */ #pragma once @@ -30,18 +30,33 @@ namespace dev namespace crypto { +void toPublic(Secret const& _s, Public& o_public); +h256 kdf(Secret const& _priv, h256 const& _hash); + /// Encrypts text (in place). void encrypt(Public const& _k, bytes& io_cipher); /// Decrypts text (in place). void decrypt(Secret const& _k, bytes& io_text); -/// Returns siganture of message hash. +/// Returns siganture of message. Signature sign(Secret const& _k, bytesConstRef _message); + +/// Returns compact siganture of message hash. +Signature sign(Secret const& _k, h256 const& _hash); -/// Verify signature -bool verify(Public _p, Signature _sig, bytesConstRef _message, bool _raw = false); +/// Verify compact signature (public key is extracted from message). +bool verify(Signature const& _signature, bytesConstRef _message); + +/// Verify signature. +bool verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed = false); +/// Recovers public key from compact signature. Uses libsecp256k1. +Public recover(Signature _signature, bytesConstRef _message); + +bool verifySecret(Secret const& _s, Public const& _p); + } + } diff --git a/libdevcrypto/FileSystem.h b/libdevcrypto/FileSystem.h index 605545b0d..281e60e24 100644 --- a/libdevcrypto/FileSystem.h +++ b/libdevcrypto/FileSystem.h @@ -24,6 +24,7 @@ #pragma once #include +#include namespace dev { diff --git a/test/crypto.cpp b/test/crypto.cpp index e11659ed0..ab384a038 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1) BOOST_REQUIRE(dev::toAddress(s) == right160(dev::sha3(p.ref()))); Secret previous = s; - for (auto i = 0; i < 30; i++) + for (auto i = 0; i < 2; i++) { ECIES::Decryptor d(pp::PRNG, pp::secp256k1Curve); ECIES::Encryptor e(d.GetKey()); @@ -82,7 +82,13 @@ BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1) Public p; pp::exportPublicKey(e.GetKey(), p); - BOOST_REQUIRE(dev::toAddress(s) == right160(dev::sha3(p.ref()))); + h160 secp256k1Addr = dev::toAddress(s); + h160 cryptoppAddr = right160(dev::sha3(p.ref())); + if (secp256k1Addr != cryptoppAddr) + { + BOOST_REQUIRE(secp256k1Addr == cryptoppAddr); + break; + } } } @@ -94,30 +100,29 @@ BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_ecdsav) Secret secret(sha3("privacy")); // we get ec params from signer + const CryptoPP::DL_GroupParameters_EC params = pp::secp256k1Params; ECDSA::Signer signer; // e := sha3(msg) bytes e(fromHex("0x01")); e.resize(32); - int tests = 15; // Oct 29: successful @ 1500 + int tests = 2; // Oct 29: successful @ 1500 while (sha3(&e, &e), secret = sha3(secret.asBytes()), tests--) { KeyPair key(secret); Public pkey = key.pub(); - pp::initializeSigner(secret, signer); + pp::initializeDLScheme(secret, signer); h256 he(sha3(e)); Integer heInt(he.asBytes().data(), 32); - h256 k(he ^ secret); + h256 k(crypto::kdf(secret, he)); Integer kInt(k.asBytes().data(), 32); - - const DL_GroupParameters ¶ms = signer.GetKey().GetAbstractGroupParameters(); + kInt %= params.GetSubgroupOrder()-1; ECP::Point rp = params.ExponentiateBase(kInt); Integer const& q = params.GetGroupOrder(); Integer r = params.ConvertElementToInteger(rp); int recid = ((r >= q) ? 2 : 0) | (rp.y.IsOdd() ? 1 : 0); - BOOST_REQUIRE(!(r >= q)); Integer kInv = kInt.InverseMod(q); Integer s = (kInv * (Integer(secret.asBytes().data(), 32)*r + heInt)) % q; @@ -164,7 +169,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) KeyPair key(secret); bytes m(fromHex("0x01")); - int tests = 5; + int tests = 2; while (m[0]++, tests--) { h256 hm(sha3(m)); @@ -174,27 +179,26 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) // raw sign w/cryptopp (doesn't pass through cryptopp hash filter) ECDSA::Signer signer; - pp::initializeSigner(key.sec(), signer); + pp::initializeDLScheme(key.sec(), signer); Integer r, s; signer.RawSign(kInt, hInt, r, s); // verify cryptopp raw-signature w/cryptopp ECDSA::Verifier verifier; - pp::initializeVerifier(key.pub(), verifier); + pp::initializeDLScheme(key.pub(), verifier); Signature sigppraw; r.Encode(sigppraw.data(), 32); s.Encode(sigppraw.data()+32, 32); BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppraw.data(), 64)); BOOST_REQUIRE(crypto::verify(key.pub(), sigppraw, bytesConstRef(&m))); BOOST_REQUIRE(dev::verify(key.pub(), sigppraw, hm)); - BOOST_CHECK(dev::recover(sigppraw, hm) == key.pub()); - // sign with sec256lib, verify with cryptopp + // sign with cryptopp, verify, recover w/sec256lib Signature seclibsig(dev::sign(key.sec(), hm)); BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), seclibsig.data(), 64)); BOOST_REQUIRE(crypto::verify(key.pub(), seclibsig, bytesConstRef(&m))); BOOST_REQUIRE(dev::verify(key.pub(), seclibsig, hm)); - BOOST_CHECK(dev::recover(seclibsig, hm) == key.pub()); + BOOST_REQUIRE(dev::recover(seclibsig, hm) == key.pub()); // sign with cryptopp (w/hash filter?), verify with cryptopp bytes sigppb(signer.MaxSignatureLength()); @@ -204,7 +208,6 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppb.data(), ssz)); BOOST_REQUIRE(crypto::verify(key.pub(), sigpp, bytesConstRef(&m))); BOOST_REQUIRE(dev::verify(key.pub(), sigpp, hm)); - BOOST_CHECK(dev::recover(sigpp, hm) == key.pub()); // sign with cryptopp and stringsource hash filter string sigstr; @@ -213,7 +216,6 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), retsig.data(), 64)); BOOST_REQUIRE(crypto::verify(key.pub(), retsig, bytesConstRef(&m))); BOOST_REQUIRE(dev::verify(key.pub(), retsig, hm)); - BOOST_CHECK(dev::recover(retsig, hm) == key.pub()); /// verification w/sec256lib // requires public key and sig in standard format