From 59d88742c2dadbc7aec669a33e49a7d1a8191dc7 Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 26 Jun 2015 06:46:49 -0400 Subject: [PATCH] Prep for supporting both cryptopp and secp256k1. Link (old) secp256k1 library to devcrypto. Rename cryptopp Secp256k1 to Secp256k1PP. Update toPublic to use secp256k1 library and add test. --- CMakeLists.txt | 5 +++- alethzero/DappLoader.cpp | 2 +- libdevcrypto/CMakeLists.txt | 4 +++ libdevcrypto/Common.cpp | 49 +++++++++++++++++++++++++----------- libdevcrypto/Common.h | 2 ++ libdevcrypto/CryptoPP.cpp | 30 +++++++++++----------- libdevcrypto/CryptoPP.h | 8 +++--- libdevcrypto/ECDHE.cpp | 2 +- mix/FileIo.cpp | 2 +- test/libdevcrypto/crypto.cpp | 14 ++++++++++- test/libp2p/rlpx.cpp | 2 +- 11 files changed, 80 insertions(+), 40 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e3b6a53c..d7e598678 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -397,7 +397,10 @@ if (JSCONSOLE) add_subdirectory(ethconsole) endif () -add_subdirectory(secp256k1) +if (NOT WIN32) + add_subdirectory(secp256k1) +endif () + add_subdirectory(libscrypt) add_subdirectory(libdevcrypto) diff --git a/alethzero/DappLoader.cpp b/alethzero/DappLoader.cpp index 5ef784e3a..a91531f89 100644 --- a/alethzero/DappLoader.cpp +++ b/alethzero/DappLoader.cpp @@ -129,7 +129,7 @@ void DappLoader::downloadComplete(QNetworkReply* _reply) h256 expected = m_uriHashes[requestUrl]; bytes package(reinterpret_cast(data.constData()), reinterpret_cast(data.constData() + data.size())); - Secp256k1 dec; + Secp256k1PP dec; dec.decrypt(expected, package); h256 got = sha3(package); if (got != expected) diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index d30aa7bc1..4244d95ca 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -24,6 +24,10 @@ target_link_libraries(${EXECUTABLE} ${DB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} scrypt) target_link_libraries(${EXECUTABLE} devcore) +if (NOT WIN32) + add_definitions(-DETH_HAVE_SECP256K1) + target_link_libraries(${EXECUTABLE} secp256k1) +endif () install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index af61a1dd5..de1eb645a 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -29,6 +29,9 @@ #include #include #include +#if ETH_HAVE_SECP256K1 +#include +#endif #include "AES.h" #include "CryptoPP.h" #include "Exceptions.h" @@ -36,7 +39,17 @@ using namespace std; using namespace dev; using namespace dev::crypto; -static Secp256k1 s_secp256k1; +#ifdef ETH_HAVE_SECP256K1 +struct Secp256k1Context +{ + Secp256k1Context() { secp256k1_start(); } + ~Secp256k1Context() { secp256k1_stop(); } +}; +static Secp256k1Context s_secp256k1; +void dev::crypto::secp256k1Init() { (void)s_secp256k1; } +#endif + +static Secp256k1PP s_secp256k1pp; bool dev::SignatureStruct::isValid() const noexcept { @@ -53,34 +66,42 @@ Address dev::ZeroAddress = Address(); Public dev::toPublic(Secret const& _secret) { +#ifdef ETH_HAVE_SECP256K1 + bytes o(65); + int pubkeylen; + if (!secp256k1_ecdsa_pubkey_create(o.data(), &pubkeylen, _secret.data(), false)) + return Public(); + return FixedHash<64>(o.data()+1, Public::ConstructFromPointer); +#else Public p; - s_secp256k1.toPublic(_secret, p); + s_secp256k1pp.toPublic(_secret, p); return p; +#endif } Address dev::toAddress(Public const& _public) { - return s_secp256k1.toAddress(_public); + return right160(sha3(_public.ref())); } Address dev::toAddress(Secret const& _secret) { Public p; - s_secp256k1.toPublic(_secret, p); - return s_secp256k1.toAddress(p); + s_secp256k1pp.toPublic(_secret, p); + return toAddress(p); } void dev::encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher) { bytes io = _plain.toBytes(); - s_secp256k1.encrypt(_k, io); + s_secp256k1pp.encrypt(_k, io); o_cipher = std::move(io); } bool dev::decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext) { bytes io = _cipher.toBytes(); - s_secp256k1.decrypt(_k, io); + s_secp256k1pp.decrypt(_k, io); if (io.empty()) return false; o_plaintext = std::move(io); @@ -90,14 +111,14 @@ bool dev::decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext) void dev::encryptECIES(Public const& _k, bytesConstRef _plain, bytes& o_cipher) { bytes io = _plain.toBytes(); - s_secp256k1.encryptECIES(_k, io); + s_secp256k1pp.encryptECIES(_k, io); o_cipher = std::move(io); } bool dev::decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext) { bytes io = _cipher.toBytes(); - if (!s_secp256k1.decryptECIES(_k, io)) + if (!s_secp256k1pp.decryptECIES(_k, io)) return false; o_plaintext = std::move(io); return true; @@ -163,17 +184,17 @@ bytes dev::decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _ci Public dev::recover(Signature const& _sig, h256 const& _message) { - return s_secp256k1.recover(_sig, _message.ref()); + return s_secp256k1pp.recover(_sig, _message.ref()); } Signature dev::sign(Secret const& _k, h256 const& _hash) { - return s_secp256k1.sign(_k, _hash); + return s_secp256k1pp.sign(_k, _hash); } bool dev::verify(Public const& _p, Signature const& _s, h256 const& _hash) { - return s_secp256k1.verify(_p, _s, _hash.ref(), true); + return s_secp256k1pp.verify(_p, _s, _hash.ref(), true); } bytes dev::pbkdf2(string const& _pass, bytes const& _salt, unsigned _iterations, unsigned _dkLen) @@ -232,8 +253,8 @@ KeyPair KeyPair::create() KeyPair::KeyPair(h256 _sec): m_secret(_sec) { - if (s_secp256k1.verifySecret(m_secret, m_public)) - m_address = s_secp256k1.toAddress(m_public); + if (s_secp256k1pp.verifySecret(m_secret, m_public)) + m_address = toAddress(m_public); } KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password) diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index b3d2649b8..7bb46c3ea 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -177,6 +177,8 @@ namespace crypto { struct InvalidState: public dev::Exception {}; +void secp256k1Init(); + /// Key derivation h256 kdf(Secret const& _priv, h256 const& _hash); diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index 40eae10f1..270367de5 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -33,7 +33,7 @@ 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."); -bytes Secp256k1::eciesKDF(Secret _z, bytes _s1, unsigned kdByteLen) +bytes Secp256k1PP::eciesKDF(Secret _z, bytes _s1, unsigned kdByteLen) { // interop w/go ecies implementation @@ -64,7 +64,7 @@ bytes Secp256k1::eciesKDF(Secret _z, bytes _s1, unsigned kdByteLen) return k; } -void Secp256k1::encryptECIES(Public const& _k, bytes& io_cipher) +void Secp256k1PP::encryptECIES(Public const& _k, bytes& io_cipher) { // interop w/go ecies implementation auto r = KeyPair::create(); @@ -98,7 +98,7 @@ void Secp256k1::encryptECIES(Public const& _k, bytes& io_cipher) io_cipher.swap(msg); } -bool Secp256k1::decryptECIES(Secret const& _k, bytes& io_text) +bool Secp256k1PP::decryptECIES(Secret const& _k, bytes& io_text) { // interop w/go ecies implementation @@ -145,7 +145,7 @@ bool Secp256k1::decryptECIES(Secret const& _k, bytes& io_text) return true; } -void Secp256k1::encrypt(Public const& _k, bytes& io_cipher) +void Secp256k1PP::encrypt(Public const& _k, bytes& io_cipher) { ECIES::Encryptor e; initializeDLScheme(_k, e); @@ -163,7 +163,7 @@ void Secp256k1::encrypt(Public const& _k, bytes& io_cipher) io_cipher = std::move(ciphertext); } -void Secp256k1::decrypt(Secret const& _k, bytes& io_text) +void Secp256k1PP::decrypt(Secret const& _k, bytes& io_text) { CryptoPP::ECIES::Decryptor d; initializeDLScheme(_k, d); @@ -194,12 +194,12 @@ void Secp256k1::decrypt(Secret const& _k, bytes& io_text) io_text = std::move(plain); } -Signature Secp256k1::sign(Secret const& _k, bytesConstRef _message) +Signature Secp256k1PP::sign(Secret const& _k, bytesConstRef _message) { return sign(_k, sha3(_message)); } -Signature Secp256k1::sign(Secret const& _key, h256 const& _hash) +Signature Secp256k1PP::sign(Secret const& _key, h256 const& _hash) { // assumption made by signing alogrithm asserts(m_q == m_qs); @@ -240,18 +240,18 @@ Signature Secp256k1::sign(Secret const& _key, h256 const& _hash) return sig; } -bool Secp256k1::verify(Signature const& _signature, bytesConstRef _message) +bool Secp256k1PP::verify(Signature const& _signature, bytesConstRef _message) { return !!recover(_signature, _message); } -bool Secp256k1::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) +bool Secp256k1PP::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { // todo: verify w/o recovery (if faster) - return (bool)_p == _hashed ? (bool)recover(_sig, _message) : (bool)recover(_sig, sha3(_message).ref()); + return _p == (_hashed ? recover(_sig, _message) : recover(_sig, sha3(_message).ref())); } -Public Secp256k1::recover(Signature _signature, bytesConstRef _message) +Public Secp256k1PP::recover(Signature _signature, bytesConstRef _message) { Public recovered; @@ -293,7 +293,7 @@ Public Secp256k1::recover(Signature _signature, bytesConstRef _message) return recovered; } -bool Secp256k1::verifySecret(Secret const& _s, Public& _p) +bool Secp256k1PP::verifySecret(Secret const& _s, Public& _p) { DL_PrivateKey_EC k; k.Initialize(m_params, secretToExponent(_s)); @@ -309,7 +309,7 @@ bool Secp256k1::verifySecret(Secret const& _s, Public& _p) return true; } -void Secp256k1::agree(Secret const& _s, Public const& _r, h256& o_s) +void Secp256k1PP::agree(Secret const& _s, Public const& _r, h256& o_s) { // TODO: mutex ASN1::secp256k1() singleton // Creating Domain is non-const for m_oid and m_oid is not thread-safe @@ -320,7 +320,7 @@ void Secp256k1::agree(Secret const& _s, Public const& _r, h256& o_s) d.Agree(o_s.data(), _s.data(), remote); } -void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& o_p) +void Secp256k1PP::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& o_p) { bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true)); @@ -333,7 +333,7 @@ void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC const& memcpy(o_p.data(), &prefixedKey[1], Public::size); } -void Secp256k1::exponentToPublic(Integer const& _e, Public& o_p) +void Secp256k1PP::exponentToPublic(Integer const& _e, Public& o_p) { CryptoPP::DL_PublicKey_EC pk; diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h index 377da8754..6a0453330 100644 --- a/libdevcrypto/CryptoPP.h +++ b/libdevcrypto/CryptoPP.h @@ -67,13 +67,11 @@ inline Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s. * CryptoPP secp256k1 algorithms. * @todo Collect ECIES methods into class. */ -class Secp256k1 +class Secp256k1PP { public: - Secp256k1(): m_oid(ASN1::secp256k1()), m_params(m_oid), m_curve(m_params.GetCurve()), m_q(m_params.GetGroupOrder()), m_qs(m_params.GetSubgroupOrder()) {} - - Address toAddress(Public const& _p) { return right160(sha3(_p.ref())); } - + Secp256k1PP(): m_oid(ASN1::secp256k1()), m_params(m_oid), m_curve(m_params.GetCurve()), m_q(m_params.GetGroupOrder()), m_qs(m_params.GetSubgroupOrder()) {} + void toPublic(Secret const& _s, Public& o_public) { exponentToPublic(Integer(_s.data(), sizeof(_s)), o_public); } /// Encrypts text (replace input). (ECIES w/XOR-SHA1) diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp index a5aaf3984..f9e55f676 100644 --- a/libdevcrypto/ECDHE.cpp +++ b/libdevcrypto/ECDHE.cpp @@ -27,7 +27,7 @@ using namespace std; using namespace dev; using namespace dev::crypto; -static Secp256k1 s_secp256k1; +static Secp256k1PP s_secp256k1; void dev::crypto::ecdh::agree(Secret const& _s, Public const& _r, h256& o_s) { diff --git a/mix/FileIo.cpp b/mix/FileIo.cpp index cf8300677..96a1ff446 100644 --- a/mix/FileIo.cpp +++ b/mix/FileIo.cpp @@ -180,7 +180,7 @@ QStringList FileIo::makePackage(QString const& _deploymentFolder) dev::h256 dappHash = dev::sha3(dapp); //encrypt KeyPair key(dappHash); - Secp256k1 enc; + Secp256k1PP enc; enc.encrypt(key.pub(), dapp); QUrl url(_deploymentFolder + "package.dapp"); diff --git a/test/libdevcrypto/crypto.cpp b/test/libdevcrypto/crypto.cpp index 1a0537ccd..776c0a88e 100644 --- a/test/libdevcrypto/crypto.cpp +++ b/test/libdevcrypto/crypto.cpp @@ -43,7 +43,7 @@ BOOST_GLOBAL_FIXTURE( MoveNonceToTempDir ) BOOST_AUTO_TEST_SUITE(devcrypto) -static Secp256k1 s_secp256k1; +static Secp256k1PP s_secp256k1; static CryptoPP::AutoSeededRandomPool s_rng; static CryptoPP::OID s_curveOID(CryptoPP::ASN1::secp256k1()); static CryptoPP::DL_GroupParameters_EC s_params(s_curveOID); @@ -64,6 +64,16 @@ BOOST_AUTO_TEST_CASE(emptySHA3Types) BOOST_REQUIRE_EQUAL(emptyListSHA3, EmptyListSHA3); } +BOOST_AUTO_TEST_CASE(secp256k1lib) +{ + secp256k1Init(); + KeyPair k = KeyPair::create(); + BOOST_REQUIRE(!!k.sec()); + BOOST_REQUIRE(!!k.pub()); + Public test = toPublic(k.sec()); + BOOST_REQUIRE(k.pub() == test); +} + BOOST_AUTO_TEST_CASE(cryptopp_patch) { KeyPair k = KeyPair::create(); @@ -156,6 +166,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_secp256k1libport) BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) { +#ifdef CRYPTOPPNOTBROKEN secp256k1_start(); // cryptopp integer encoding @@ -237,6 +248,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) BOOST_CHECK(cssz <= 72); BOOST_REQUIRE(1 == secp256k1_ecdsa_verify(hm.data(), sizeof(hm), dersig, cssz, encpub, 65)); } +#endif } BOOST_AUTO_TEST_CASE(sha3_norestart) diff --git a/test/libp2p/rlpx.cpp b/test/libp2p/rlpx.cpp index 620ddd952..6d5e59733 100644 --- a/test/libp2p/rlpx.cpp +++ b/test/libp2p/rlpx.cpp @@ -39,7 +39,7 @@ using namespace CryptoPP; BOOST_AUTO_TEST_SUITE(rlpx) -static Secp256k1 s_secp256k1; +static Secp256k1PP s_secp256k1; static CryptoPP::AutoSeededRandomPool s_rng; static CryptoPP::OID s_curveOID(CryptoPP::ASN1::secp256k1()); static CryptoPP::DL_GroupParameters_EC s_params(s_curveOID);