From e2f32c3632e51b58ec5f7811a9730982bac82738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Nov 2014 17:58:37 +0100 Subject: [PATCH 01/27] Fix compilation with Visual Studio --- libdevcrypto/EC.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index af6d0e65e..7bc17ab99 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -134,7 +134,7 @@ bool crypto::verify(Signature const& _signature, bytesConstRef _message) bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { - static size_t derMaxEncodingLength = 72; + static const size_t derMaxEncodingLength = 72; if (_hashed) { assert(_message.size() == 32); @@ -155,8 +155,9 @@ Public crypto::recover(Signature _signature, bytesConstRef _message) { secp256k1_start(); - int pubkeylen = 65; - byte pubkey[pubkeylen]; + static const int c_pubkeylen = 65; + auto pubkeylen = c_pubkeylen; + byte pubkey[c_pubkeylen]; if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64])) return Public(); @@ -180,8 +181,9 @@ bool crypto::verifySecret(Secret const& _s, Public const& _p) if (!ok) return false; - int pubkeylen = 65; - byte pubkey[pubkeylen]; + static const int c_pubkeylen = 65; + auto pubkeylen = c_pubkeylen; + byte pubkey[c_pubkeylen]; ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0); if (!ok || pubkeylen != 65) return false; From de0c84c7df6ad668f0969d35475fe4608e99f072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Nov 2014 18:29:49 +0100 Subject: [PATCH 02/27] Replace auto with int --- libdevcrypto/EC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index 7bc17ab99..17304668b 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -182,7 +182,7 @@ bool crypto::verifySecret(Secret const& _s, Public const& _p) return false; static const int c_pubkeylen = 65; - auto pubkeylen = c_pubkeylen; + int pubkeylen = c_pubkeylen; byte pubkey[c_pubkeylen]; ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0); if (!ok || pubkeylen != 65) From 30bb7c21607d4b9c11a47a94fcdd53d3ecd87a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Nov 2014 18:30:42 +0100 Subject: [PATCH 03/27] Replace auto with int --- libdevcrypto/EC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index 17304668b..237acebc5 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -156,7 +156,7 @@ Public crypto::recover(Signature _signature, bytesConstRef _message) secp256k1_start(); static const int c_pubkeylen = 65; - auto pubkeylen = c_pubkeylen; + int pubkeylen = c_pubkeylen; byte pubkey[c_pubkeylen]; if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64])) return Public(); From c5927833ac583d39bc32975c2e6b4a6a502a3ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 7 Nov 2014 11:37:34 +0100 Subject: [PATCH 04/27] static const variable name fix --- libdevcrypto/EC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index 237acebc5..a54c0132d 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -134,7 +134,7 @@ bool crypto::verify(Signature const& _signature, bytesConstRef _message) bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { - static const size_t derMaxEncodingLength = 72; + static const size_t c_derMaxEncodingLength = 72; if (_hashed) { assert(_message.size() == 32); From 554681992d3cafe39421b81f5e4022c467ac5dee Mon Sep 17 00:00:00 2001 From: subtly Date: Tue, 11 Nov 2014 03:36:07 +0100 Subject: [PATCH 05/27] aes, ecdh, ecdhe --- libdevcrypto/AES.cpp | 23 +++++++++ libdevcrypto/AES.h | 78 +++++++++++++++++++++++++++++ libdevcrypto/CryptoPP.cpp | 10 +++- libdevcrypto/CryptoPP.h | 4 +- libdevcrypto/ECDHE.cpp | 79 +++++++++++++++++++++++++++++ libdevcrypto/ECDHE.h | 102 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 294 insertions(+), 2 deletions(-) create mode 100644 libdevcrypto/AES.cpp create mode 100644 libdevcrypto/AES.h create mode 100644 libdevcrypto/ECDHE.cpp create mode 100644 libdevcrypto/ECDHE.h diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp new file mode 100644 index 000000000..109ba9646 --- /dev/null +++ b/libdevcrypto/AES.cpp @@ -0,0 +1,23 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . + */ +/** @file AES.cpp + * @author Alex Leverington + * @date 2014 + */ + +#include "AES.h" + diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h new file mode 100644 index 000000000..95525685b --- /dev/null +++ b/libdevcrypto/AES.h @@ -0,0 +1,78 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . + */ +/** @file AES.h + * @author Alex Leverington + * @date 2014 + * + * AES + */ + +#pragma once + +#include "Common.h" + +namespace dev +{ +namespace crypto +{ +namespace aes +{ + +using Secret128 = FixedHash<16>; +enum StreamType { Encrypt, Decrypt }; + +/** + * @brief Encrypted stream + */ +class Stream +{ +public: + Stream(StreamType _t, Secret128 _encS, bool _zero = true): m_type(_t), m_zeroInput(_zero), m_encSecret(_encS) {}; + + virtual void update(bytesRef io_bytes) {}; + + /// Move ciphertext to _bytes. + virtual size_t streamOut(bytes& o_bytes) {}; + +private: + StreamType m_type; + bool m_zeroInput; + Secret128 m_encSecret; + bytes m_text; +}; + +/** + * @brief Encrypted stream with inband SHA3 mac at specific interval. + */ +class AuthenticatedStream: public Stream +{ +public: + AuthenticatedStream(StreamType _t, Secret128 _encS, Secret128 _macS, unsigned _interval, bool _zero = true): Stream(_t, _encS, _zero), m_macSecret(_macS) { m_macInterval = _interval; } + + AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval, bool _zero = true): Stream(_t, Secret128(_s), _zero), m_macSecret(FixedHash<16>(_s[0]+16)) { m_macInterval = _interval; } + + /// Adjust mac interval. Next mac will be xored with value. + void adjustInterval(unsigned _interval) { m_macInterval = _interval; }; + +private: + std::atomic m_macInterval; + Secret128 m_macSecret; +}; + +} +} +} \ No newline at end of file diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index 1b51d5bd5..87859ef9c 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -31,6 +31,7 @@ using namespace CryptoPP; void pp::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p) { bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true)); + secp256k1Params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false); assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true)); @@ -42,4 +43,11 @@ void pp::exponentToPublic(Integer const& _e, Public& _p) CryptoPP::DL_PublicKey_EC pk; pk.Initialize(secp256k1Params, secp256k1Params.ExponentiateBase(_e)); pp::exportPublicKey(pk, _p); -} \ No newline at end of file +} + +void pp::ecdhAgree(Secret _s, Public _r, h256& o_s) +{ + ECDH::Domain d(secp256k1Curve); + assert(d.AgreedValueLength() == sizeof(o_s)); + d.Agree(o_s.data(), _s.data(), _r.data()); +} diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h index dc5d6a610..daf26bc3f 100644 --- a/libdevcrypto/CryptoPP.h +++ b/libdevcrypto/CryptoPP.h @@ -76,7 +76,9 @@ void exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& static void exportPrivateKey(CryptoPP::DL_PrivateKey_EC const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); } void exponentToPublic(Integer const& _e, Public& _p); - + +void ecdhAgree(Secret _s, Public _r, h256& o_s); + template void initializeDLScheme(Secret const& _s, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, secretToExponent(_s)); } diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp new file mode 100644 index 000000000..d785f467e --- /dev/null +++ b/libdevcrypto/ECDHE.cpp @@ -0,0 +1,79 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . + */ +/** @file ECDHE.cpp + * @author Alex Leverington + * @date 2014 + */ + +#include "SHA3.h" +#include "SHA3MAC.h" +#include "CryptoPP.h" +#include "ECDHE.h" + +using namespace std; +using namespace dev; +using namespace dev::crypto; +using namespace dev::crypto::pp; + +void ECDHE::agree(Public _remote) +{ + m_remoteEphemeral = _remote; + ecdhAgree(m_ephemeral.sec(), m_remoteEphemeral, m_sharedSecret); +} + +void ECDHEKeyExchange::exchange(bytes& o_exchange) +{ + if (!m_sharedSecret) + // didn't agree on public remote + BOOST_THROW_EXCEPTION(InvalidState()); + + Public encpk = m_known.first|m_remoteEphemeral; + bytes exchange(encpk.asBytes()); + + // This is the public key which we would like the remote to use, + // which maybe different than previously-known public key. + // Here we would pick an appropriate alias or generate a new one, + // but for now, we use static alias passed to constructor. + // + Public p; + pp::exponentToPublic(pp::secretToExponent(m_alias.m_secret), p); + exchange.resize(exchange.size() + sizeof(p)); + memcpy(exchange.data() - sizeof(p), p.data(), sizeof(p)); + + // protocol parameters; should be fixed size + bytes v(asBytes("\x80")); + exchange.resize(exchange.size() + v.size()); + memcpy(exchange.data() - v.size(), v.data(), v.size()); + + h256 auth; + sha3mac(m_alias.m_secret.ref(), m_sharedSecret.ref(), auth.ref()); + Signature sig = crypto::sign(m_alias.m_secret, auth); + exchange.resize(exchange.size() + sizeof(sig)); + memcpy(exchange.data() - sizeof(sig), sig.data(), sizeof(sig)); + + aes::AuthenticatedStream aes(aes::Encrypt, m_sharedSecret, 0); + h256 prefix(sha3((h256)(m_known.second|m_remoteEphemeral))); + aes.update(prefix.ref()); + + encrypt(encpk, exchange); + aes.update(&exchange); + + aes.streamOut(o_exchange); +} + + + diff --git a/libdevcrypto/ECDHE.h b/libdevcrypto/ECDHE.h new file mode 100644 index 000000000..11a5afa5c --- /dev/null +++ b/libdevcrypto/ECDHE.h @@ -0,0 +1,102 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . + */ +/** @file ECDHE.h + * @author Alex Leverington + * @date 2014 + * + * Elliptic curve Diffie-Hellman ephemeral key exchange + */ + +#pragma once + +#include "AES.h" +#include "EC.h" + +namespace dev +{ +namespace crypto +{ + +typedef std::pair AliasSession; + +class Alias +{ + friend class ECDHEKeyExchange; // todo: remove +public: + Alias(Secret _s): m_secret(_s) {}; + + AliasSession session(Address _a) { return m_sessions.count(_a) ? AliasSession() : m_sessions.find(_a)->second; } + +private: + std::map m_sessions; + Secret m_secret; +}; + +/** + * @brief Derive DH shared secret from EC keypairs. + */ +class ECDHE +{ +public: + /// Constructor (pass public key for ingress exchange). + ECDHE(): m_ephemeral(KeyPair::create()) {}; + + /// Public key sent to remote. + Public pubkey() { return m_ephemeral.pub(); } + + /// Provide public key for dh agreement to generated shared secret. + void agree(Public _remoteEphemeral); + +protected: + KeyPair m_ephemeral; ///< Ephemeral keypair; generated. + Public m_remoteEphemeral; ///< Public key of remote; parameter. + Secret m_sharedSecret; ///< Derived secret; derived by agree. +}; + +/** + * @brief Secure exchange of static keys. + * Key exchange is encrypted with public key of remote and then encrypted by block cipher. For a blind remote the ecdhe public key is used to encrypt exchange, and for a known remote the known public key is used. The block cipher key is derived from ecdhe shared secret. + * + * Usage: Agree -> Exchange -> Authenticate + */ +class ECDHEKeyExchange: public ECDHE +{ +public: + /// Exchange with unknown remote (pass public key for ingress exchange) + ECDHEKeyExchange(Alias& _k): m_alias(_k) {}; + + /// Exchange with known remote + ECDHEKeyExchange(Alias& _k, AliasSession _known): m_alias(_k), m_known(_known) {}; + + /// @returns encrypted payload of key exchange + void exchange(bytes& o_exchange); + + /// Decrypt payload, check mac, check trust, decrypt exchange, authenticate exchange, verify version, verify signature, and if no failure occurs, update or creats trust and derive session-shared-secret. + bool authenticate(bytes _exchangeIn); + +private: + Alias m_alias; + AliasSession m_known; + Secret m_sharedAliasSecret; + + FixedHash<16> m_sharedC; + FixedHash<16> m_sharedM; +}; + +} +} + From 489fb2b430a24eb6b7e2617db3bb7b8646481ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 11 Nov 2014 18:00:49 +0100 Subject: [PATCH 06/27] static const variable name fix --- libdevcrypto/EC.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index a54c0132d..a3438ede1 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -134,15 +134,15 @@ bool crypto::verify(Signature const& _signature, bytesConstRef _message) bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { - static const size_t c_derMaxEncodingLength = 72; if (_hashed) { assert(_message.size() == 32); byte encpub[65] = {0x04}; memcpy(&encpub[1], _p.data(), 64); - byte dersig[derMaxEncodingLength]; - size_t cssz = DSAConvertSignatureFormat(dersig, derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363); - assert(cssz <= derMaxEncodingLength); + static const size_t c_derMaxEncodingLength = 72; + byte dersig[c_derMaxEncodingLength]; + size_t cssz = DSAConvertSignatureFormat(dersig, c_derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363); + assert(cssz <= c_derMaxEncodingLength); return (1 == secp256k1_ecdsa_verify(_message.data(), _message.size(), dersig, cssz, encpub, 65)); } From 0f86ce7545b101e66cbb9089d0dddc137951467b Mon Sep 17 00:00:00 2001 From: subtly Date: Tue, 11 Nov 2014 18:31:23 +0100 Subject: [PATCH 07/27] ecdh, ecdhe, initial aes classes --- libdevcore/Common.h | 1 + libdevcore/FixedHash.h | 1 + libdevcrypto/AES.cpp | 28 ++++++++ libdevcrypto/AES.h | 22 +++--- libdevcrypto/All.h | 1 - libdevcrypto/CryptoPP.cpp | 6 +- libdevcrypto/CryptoPP.h | 8 ++- libdevcrypto/ECDHE.cpp | 19 +++-- libdevcrypto/ECDHE.h | 12 ++-- libethcore/CryptoHeaders.h | 36 ---------- test/TestHelperCrypto.h | 51 ------------- test/crypto.cpp | 143 +++++++++++++++++++++++-------------- 12 files changed, 164 insertions(+), 164 deletions(-) delete mode 100644 libethcore/CryptoHeaders.h delete mode 100644 test/TestHelperCrypto.h diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 87cc069b3..198119f24 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -59,6 +59,7 @@ using bytesConstRef = vector_ref; // Numeric types. using bigint = boost::multiprecision::number>; +using u128 = boost::multiprecision::number>; using u256 = boost::multiprecision::number>; using s256 = boost::multiprecision::number>; using u160 = boost::multiprecision::number>; diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 2353a100c..0e387ab8a 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -240,6 +240,7 @@ using h520 = FixedHash<65>; using h512 = FixedHash<64>; using h256 = FixedHash<32>; using h160 = FixedHash<20>; +using h128 = FixedHash<16>; using h512s = std::vector; using h256s = std::vector; using h160s = std::vector; diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp index 109ba9646..fc0cf15c4 100644 --- a/libdevcrypto/AES.cpp +++ b/libdevcrypto/AES.cpp @@ -19,5 +19,33 @@ * @date 2014 */ +#include "CryptoPP.h" #include "AES.h" +using namespace std; +using namespace dev::crypto::aes; +using namespace dev::crypto::pp; +using namespace CryptoPP; + +Stream::Stream(StreamType _t, h128 _ckey): + m_cSecret(_ckey) +{ + (void)_t; // encrypt and decrypt are same operation w/ctr mode + cryptor = new Aes128Ctr(_ckey); +} + +Stream::~Stream() +{ + delete cryptor; +} + +void Stream::update(bytesRef io_bytes) +{ + +} + +size_t Stream::streamOut(bytes& o_bytes) +{ + +} + diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h index 95525685b..753dcd14b 100644 --- a/libdevcrypto/AES.h +++ b/libdevcrypto/AES.h @@ -29,10 +29,10 @@ namespace dev { namespace crypto { +namespace pp { struct Aes128Ctr; } namespace aes { -using Secret128 = FixedHash<16>; enum StreamType { Encrypt, Decrypt }; /** @@ -41,18 +41,20 @@ enum StreamType { Encrypt, Decrypt }; class Stream { public: - Stream(StreamType _t, Secret128 _encS, bool _zero = true): m_type(_t), m_zeroInput(_zero), m_encSecret(_encS) {}; + // streamtype maybe irrelevant w/ctr + Stream(StreamType _t, h128 _ckey); + ~Stream(); - virtual void update(bytesRef io_bytes) {}; + virtual void update(bytesRef io_bytes); /// Move ciphertext to _bytes. - virtual size_t streamOut(bytes& o_bytes) {}; + virtual size_t streamOut(bytes& o_bytes); private: - StreamType m_type; - bool m_zeroInput; - Secret128 m_encSecret; + h128 m_cSecret; bytes m_text; + + pp::Aes128Ctr* cryptor; }; /** @@ -61,16 +63,16 @@ private: class AuthenticatedStream: public Stream { public: - AuthenticatedStream(StreamType _t, Secret128 _encS, Secret128 _macS, unsigned _interval, bool _zero = true): Stream(_t, _encS, _zero), m_macSecret(_macS) { m_macInterval = _interval; } + AuthenticatedStream(StreamType _t, h128 _ckey, h128 _mackey, unsigned _interval): Stream(_t, _ckey), m_macSecret(_mackey) { m_macInterval = _interval; } - AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval, bool _zero = true): Stream(_t, Secret128(_s), _zero), m_macSecret(FixedHash<16>(_s[0]+16)) { m_macInterval = _interval; } + AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval): Stream(_t, h128(_s)), m_macSecret(FixedHash<16>(_s[0]+16)) { m_macInterval = _interval; } /// Adjust mac interval. Next mac will be xored with value. void adjustInterval(unsigned _interval) { m_macInterval = _interval; }; private: std::atomic m_macInterval; - Secret128 m_macSecret; + h128 m_macSecret; }; } diff --git a/libdevcrypto/All.h b/libdevcrypto/All.h index db6d7c615..8018db4fb 100644 --- a/libdevcrypto/All.h +++ b/libdevcrypto/All.h @@ -1,7 +1,6 @@ #pragma once #include "Common.h" -#include "CryptoPP.h" #include "EC.h" #include "FileSystem.h" #include "MemoryDB.h" diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index 87859ef9c..0694699ae 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -45,9 +45,11 @@ void pp::exponentToPublic(Integer const& _e, Public& _p) pp::exportPublicKey(pk, _p); } -void pp::ecdhAgree(Secret _s, Public _r, h256& o_s) +void pp::ecdhAgree(Secret const& _s, Public const& _r, h256& o_s) { ECDH::Domain d(secp256k1Curve); assert(d.AgreedValueLength() == sizeof(o_s)); - d.Agree(o_s.data(), _s.data(), _r.data()); + byte remote[65] = {0x04}; + memcpy(&remote[1], _r.data(), 64); + assert(d.Agree(o_s.data(), _s.data(), remote)); } diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h index daf26bc3f..1ae4bee74 100644 --- a/libdevcrypto/CryptoPP.h +++ b/libdevcrypto/CryptoPP.h @@ -77,13 +77,19 @@ static void exportPrivateKey(CryptoPP::DL_PrivateKey_EC const& _k void exponentToPublic(Integer const& _e, Public& _p); -void ecdhAgree(Secret _s, Public _r, h256& o_s); +void ecdhAgree(Secret const& _s, Public const& _r, h256& o_s); 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)); } + +struct Aes128Ctr +{ + Aes128Ctr(h128 _k) { mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); } + CTR_Mode::Encryption mode; +}; } } diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp index d785f467e..6b3979874 100644 --- a/libdevcrypto/ECDHE.cpp +++ b/libdevcrypto/ECDHE.cpp @@ -29,15 +29,24 @@ using namespace dev; using namespace dev::crypto; using namespace dev::crypto::pp; -void ECDHE::agree(Public _remote) +void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret) { + if (m_remoteEphemeral) + // agreement can only occur once + BOOST_THROW_EXCEPTION(InvalidState()); + m_remoteEphemeral = _remote; - ecdhAgree(m_ephemeral.sec(), m_remoteEphemeral, m_sharedSecret); + ecdhAgree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret); +} + +void ECDHEKeyExchange::agree(Public const& _remoteEphemeral) +{ + ecdhAgree(m_ephemeral.sec(), _remoteEphemeral, m_ephemeralSecret); } void ECDHEKeyExchange::exchange(bytes& o_exchange) { - if (!m_sharedSecret) + if (!m_ephemeralSecret) // didn't agree on public remote BOOST_THROW_EXCEPTION(InvalidState()); @@ -60,12 +69,12 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange) memcpy(exchange.data() - v.size(), v.data(), v.size()); h256 auth; - sha3mac(m_alias.m_secret.ref(), m_sharedSecret.ref(), auth.ref()); + sha3mac(m_alias.m_secret.ref(), m_ephemeralSecret.ref(), auth.ref()); Signature sig = crypto::sign(m_alias.m_secret, auth); exchange.resize(exchange.size() + sizeof(sig)); memcpy(exchange.data() - sizeof(sig), sig.data(), sizeof(sig)); - aes::AuthenticatedStream aes(aes::Encrypt, m_sharedSecret, 0); + aes::AuthenticatedStream aes(aes::Encrypt, m_ephemeralSecret, 0); h256 prefix(sha3((h256)(m_known.second|m_remoteEphemeral))); aes.update(prefix.ref()); diff --git a/libdevcrypto/ECDHE.h b/libdevcrypto/ECDHE.h index 11a5afa5c..88e5ba764 100644 --- a/libdevcrypto/ECDHE.h +++ b/libdevcrypto/ECDHE.h @@ -48,6 +48,7 @@ private: /** * @brief Derive DH shared secret from EC keypairs. + * As ephemeral keys are single-use, agreement is limited to a single occurence. */ class ECDHE { @@ -58,13 +59,12 @@ public: /// Public key sent to remote. Public pubkey() { return m_ephemeral.pub(); } - /// Provide public key for dh agreement to generated shared secret. - void agree(Public _remoteEphemeral); + /// Input public key for dh agreement, output generated shared secret. + void agree(Public const& _remoteEphemeral, Secret& o_sharedSecret); protected: KeyPair m_ephemeral; ///< Ephemeral keypair; generated. Public m_remoteEphemeral; ///< Public key of remote; parameter. - Secret m_sharedSecret; ///< Derived secret; derived by agree. }; /** @@ -73,7 +73,7 @@ protected: * * Usage: Agree -> Exchange -> Authenticate */ -class ECDHEKeyExchange: public ECDHE +class ECDHEKeyExchange: private ECDHE { public: /// Exchange with unknown remote (pass public key for ingress exchange) @@ -82,6 +82,9 @@ public: /// Exchange with known remote ECDHEKeyExchange(Alias& _k, AliasSession _known): m_alias(_k), m_known(_known) {}; + /// Provide public key for dh agreement to generate shared secret. + void agree(Public const& _remoteEphemeral); + /// @returns encrypted payload of key exchange void exchange(bytes& o_exchange); @@ -89,6 +92,7 @@ public: bool authenticate(bytes _exchangeIn); private: + Secret m_ephemeralSecret; Alias m_alias; AliasSession m_known; Secret m_sharedAliasSecret; diff --git a/libethcore/CryptoHeaders.h b/libethcore/CryptoHeaders.h deleted file mode 100644 index 4ff63f1d7..000000000 --- a/libethcore/CryptoHeaders.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . -*/ -/** @file CryptoHeaders.h - * @author Tim Hughes - * @date 2014 - */ -#pragma once - -// need to leave this one disabled -#pragma GCC diagnostic ignored "-Wunused-function" - -#pragma warning(push) -#pragma warning(disable:4100 4244) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#include -#include -#include -#include -#pragma warning(pop) -#pragma GCC diagnostic pop diff --git a/test/TestHelperCrypto.h b/test/TestHelperCrypto.h deleted file mode 100644 index 01e97c21f..000000000 --- a/test/TestHelperCrypto.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . - */ -/** @file TestHelperCrypto.h - * @author Alex Leverington - * @date 2014 - */ - -#pragma once - -#include - -using namespace std; -using namespace CryptoPP; - -void SavePrivateKey(const PrivateKey& key, const string& file = "ecies.private.key") -{ - FileSink sink(file.c_str()); - key.Save(sink); -} - -void SavePublicKey(const PublicKey& key, const string& file = "ecies.public.key") -{ - FileSink sink(file.c_str()); - key.Save(sink); -} - -void LoadPrivateKey(PrivateKey& key, const string& file = "ecies.private.key") -{ - FileSource source(file.c_str(), true); - key.Load(source); -} - -void LoadPublicKey(PublicKey& key, const string& file = "ecies.public.key") -{ - FileSource source(file.c_str(), true); - key.Load(source); -} diff --git a/test/crypto.cpp b/test/crypto.cpp index 06e55658a..a84c1fbb5 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -27,9 +27,10 @@ #include #include #include -#include #include -#include "TestHelperCrypto.h" +#include +#include +#include using namespace std; using namespace dev; @@ -40,7 +41,7 @@ BOOST_AUTO_TEST_SUITE(devcrypto) BOOST_AUTO_TEST_CASE(common_encrypt_decrypt) { - string message("Now is the time for all good persons to come to the aide of humanity."); + string message("Now is the time for all good persons to come to the aid of humanity."); bytes m = asBytes(message); bytesConstRef bcr(&m); @@ -267,7 +268,7 @@ BOOST_AUTO_TEST_CASE(ecies_eckeypair) { KeyPair k = KeyPair::create(); - string message("Now is the time for all good persons to come to the aide of humanity."); + string message("Now is the time for all good persons to come to the aid of humanity."); string original = message; bytes b = asBytes(message); @@ -278,61 +279,87 @@ BOOST_AUTO_TEST_CASE(ecies_eckeypair) BOOST_REQUIRE(b == asBytes(original)); } -BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) +BOOST_AUTO_TEST_CASE(ecdh) { - // New connections require new ECDH keypairs - // Every new connection requires a new EC keypair - // Every new trust requires a new EC keypair - // All connections should share seed for PRF (or PRNG) for nonces + cnote << "Testing ecdh..."; + + ECDH::Domain dhLocal(pp::secp256k1Curve); + SecByteBlock privLocal(dhLocal.PrivateKeyLength()); + SecByteBlock pubLocal(dhLocal.PublicKeyLength()); + dhLocal.GenerateKeyPair(pp::PRNG, privLocal, pubLocal); + + ECDH::Domain dhRemote(pp::secp256k1Curve); + SecByteBlock privRemote(dhRemote.PrivateKeyLength()); + SecByteBlock pubRemote(dhRemote.PublicKeyLength()); + dhRemote.GenerateKeyPair(pp::PRNG, privRemote, pubRemote); + assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength()); + // local: send public to remote; remote: send public to local + + // Local + SecByteBlock sharedLocal(dhLocal.AgreedValueLength()); + assert(dhLocal.Agree(sharedLocal, privLocal, pubRemote)); + + // Remote + SecByteBlock sharedRemote(dhRemote.AgreedValueLength()); + assert(dhRemote.Agree(sharedRemote, privRemote, pubLocal)); + + // Test + Integer ssLocal, ssRemote; + ssLocal.Decode(sharedLocal.BytePtr(), sharedLocal.SizeInBytes()); + ssRemote.Decode(sharedRemote.BytePtr(), sharedRemote.SizeInBytes()); + + assert(ssLocal != 0); + assert(ssLocal == ssRemote); + + + // Now use our keys + KeyPair a = KeyPair::create(); + byte puba[65] = {0x04}; + memcpy(&puba[1], a.pub().data(), 64); + + KeyPair b = KeyPair::create(); + byte pubb[65] = {0x04}; + memcpy(&pubb[1], b.pub().data(), 64); + + ECDH::Domain dhA(pp::secp256k1Curve); + Secret shared; + BOOST_REQUIRE(dhA.Agree(shared.data(), a.sec().data(), pubb)); + BOOST_REQUIRE(shared); } -BOOST_AUTO_TEST_CASE(cryptopp_ecies_message) +BOOST_AUTO_TEST_CASE(ecdhe) { - cnote << "Testing cryptopp_ecies_message..."; - - string const message("Now is the time for all good persons to come to the aide of humanity."); - - ECIES::Decryptor localDecryptor(pp::PRNG, pp::secp256k1Curve); - SavePrivateKey(localDecryptor.GetPrivateKey()); + cnote << "Testing ecdhe..."; - ECIES::Encryptor localEncryptor(localDecryptor); - SavePublicKey(localEncryptor.GetPublicKey()); - - ECIES::Decryptor futureDecryptor; - LoadPrivateKey(futureDecryptor.AccessPrivateKey()); - futureDecryptor.GetPrivateKey().ThrowIfInvalid(pp::PRNG, 3); + ECDHE a, b; + BOOST_CHECK_NE(a.pubkey(), b.pubkey()); - ECIES::Encryptor futureEncryptor; - LoadPublicKey(futureEncryptor.AccessPublicKey()); - futureEncryptor.GetPublicKey().ThrowIfInvalid(pp::PRNG, 3); - - // encrypt/decrypt with local - string cipherLocal; - StringSource ss1 (message, true, new PK_EncryptorFilter(pp::PRNG, localEncryptor, new StringSink(cipherLocal) ) ); - string plainLocal; - StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG, localDecryptor, new StringSink(plainLocal) ) ); - - // encrypt/decrypt with future - string cipherFuture; - StringSource ss3 (message, true, new PK_EncryptorFilter(pp::PRNG, futureEncryptor, new StringSink(cipherFuture) ) ); - string plainFuture; - StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG, futureDecryptor, new StringSink(plainFuture) ) ); + ECDHE local; + ECDHE remote; - // decrypt local w/future - string plainFutureFromLocal; - StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG, futureDecryptor, new StringSink(plainFutureFromLocal) ) ); + // local tx pubkey -> remote + Secret sremote; + remote.agree(local.pubkey(), sremote); - // decrypt future w/local - string plainLocalFromFuture; - StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG, localDecryptor, new StringSink(plainLocalFromFuture) ) ); + // remote tx pbukey -> local + Secret slocal; + local.agree(remote.pubkey(), slocal); + + BOOST_REQUIRE(sremote); + BOOST_REQUIRE(slocal); + BOOST_REQUIRE_EQUAL(sremote, slocal); +} + +BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) +{ + // New connections require new ECDH keypairs + // Every new connection requires a new EC keypair + // Every new trust requires a new EC keypair + // All connections should share seed for PRF (or PRNG) for nonces - BOOST_REQUIRE(plainLocal == message); - BOOST_REQUIRE(plainFuture == plainLocal); - BOOST_REQUIRE(plainFutureFromLocal == plainLocal); - BOOST_REQUIRE(plainLocalFromFuture == plainLocal); } BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) @@ -346,21 +373,29 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) rng.GenerateBlock(key, key.size()); // cryptopp uses IV as nonce/counter which is same as using nonce w/0 ctr - byte ctr[AES::BLOCKSIZE]; - rng.GenerateBlock(ctr, sizeof(ctr)); + FixedHash ctr; + rng.GenerateBlock(ctr.data(), sizeof(ctr)); + + // used for decrypt + FixedHash ctrcopy(ctr); - string text = "Now is the time for all good persons to come to the aide of humanity."; - // c++11 ftw + string text = "Now is the time for all good persons to come to the aid of humanity."; unsigned char const* in = (unsigned char*)&text[0]; unsigned char* out = (unsigned char*)&text[0]; string original = text; + string doublespeak = text + text; string cipherCopy; try { CTR_Mode::Encryption e; - e.SetKeyWithIV(key, key.size(), ctr); + e.SetKeyWithIV(key, key.size(), ctr.data()); + + // 68 % 255 should be difference of counter e.ProcessData(out, in, text.size()); + + (u128)ctr += (u128)(text.size() % 16); + BOOST_REQUIRE(text != original); cipherCopy = text; } @@ -372,7 +407,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) try { CTR_Mode< AES >::Decryption d; - d.SetKeyWithIV(key, key.size(), ctr); + d.SetKeyWithIV(key, key.size(), ctrcopy.data()); d.ProcessData(out, in, text.size()); BOOST_REQUIRE(text == original); } @@ -390,7 +425,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) out = (unsigned char*)&cipherCopy[0]; CTR_Mode::Encryption e; - e.SetKeyWithIV(key, key.size(), ctr); + e.SetKeyWithIV(key, key.size(), ctrcopy.data()); e.ProcessData(out, in, text.size()); // yep, ctr mode. From 98f3011aabcfb53399c17265705a908c17f9fbaf Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 12 Nov 2014 02:01:27 +0100 Subject: [PATCH 08/27] 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); From fab63ce0a086f0e261a3c0abda69bb19a6e4eb1c Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 13 Nov 2014 02:00:19 +0100 Subject: [PATCH 09/27] refactor and thread-safe cryptopp. for now, remove secp256klib calls. ecdh and tests. move sha3mac into sha3. --- libdevcrypto/AES.cpp | 17 +++- libdevcrypto/AES.h | 5 +- libdevcrypto/All.h | 7 +- libdevcrypto/Common.cpp | 103 +++++++++++-------- libdevcrypto/Common.h | 11 +- libdevcrypto/CryptoPP.cpp | 192 ++++++++++++++++++++++++++++++++--- libdevcrypto/CryptoPP.h | 90 ++++++++++++----- libdevcrypto/EC.cpp | 208 -------------------------------------- libdevcrypto/EC.h | 62 ------------ libdevcrypto/ECDHE.cpp | 31 ++++-- libdevcrypto/ECDHE.h | 4 +- libdevcrypto/SHA3.cpp | 10 ++ libdevcrypto/SHA3.h | 3 + libdevcrypto/SHA3MAC.cpp | 40 -------- libdevcrypto/SHA3MAC.h | 38 ------- libethcore/CommonEth.cpp | 27 ----- libethereum/State.cpp | 4 - test/crypto.cpp | 143 +++++++++----------------- 18 files changed, 414 insertions(+), 581 deletions(-) delete mode 100644 libdevcrypto/EC.cpp delete mode 100644 libdevcrypto/EC.h delete mode 100644 libdevcrypto/SHA3MAC.cpp delete mode 100644 libdevcrypto/SHA3MAC.h diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp index fc0cf15c4..1807bad19 100644 --- a/libdevcrypto/AES.cpp +++ b/libdevcrypto/AES.cpp @@ -23,14 +23,21 @@ #include "AES.h" using namespace std; +using namespace dev; +using namespace dev::crypto; using namespace dev::crypto::aes; -using namespace dev::crypto::pp; using namespace CryptoPP; +struct aes::Aes128Ctr +{ + Aes128Ctr(h128 _k) { mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); } + CryptoPP::CTR_Mode::Encryption mode; +}; + Stream::Stream(StreamType _t, h128 _ckey): m_cSecret(_ckey) { - (void)_t; // encrypt and decrypt are same operation w/ctr mode + (void)_t; // encrypt and decrypt are same operation w/ctr cryptor = new Aes128Ctr(_ckey); } @@ -39,13 +46,13 @@ Stream::~Stream() delete cryptor; } -void Stream::update(bytesRef io_bytes) +void Stream::update(bytesRef) { } -size_t Stream::streamOut(bytes& o_bytes) +size_t Stream::streamOut(bytes&) { - + return 0; } diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h index 753dcd14b..2bb852653 100644 --- a/libdevcrypto/AES.h +++ b/libdevcrypto/AES.h @@ -29,10 +29,10 @@ namespace dev { namespace crypto { -namespace pp { struct Aes128Ctr; } namespace aes { +struct Aes128Ctr; enum StreamType { Encrypt, Decrypt }; /** @@ -54,8 +54,9 @@ private: h128 m_cSecret; bytes m_text; - pp::Aes128Ctr* cryptor; + Aes128Ctr* cryptor; }; + /** * @brief Encrypted stream with inband SHA3 mac at specific interval. diff --git a/libdevcrypto/All.h b/libdevcrypto/All.h index 8018db4fb..9070725e9 100644 --- a/libdevcrypto/All.h +++ b/libdevcrypto/All.h @@ -1,11 +1,8 @@ #pragma once #include "Common.h" -#include "EC.h" +#include "AES.h" +#include "ECDHE.h" #include "FileSystem.h" -#include "MemoryDB.h" -#include "OverlayDB.h" #include "SHA3.h" -#include "SHA3MAC.h" -#include "TrieCommon.h" #include "TrieDB.h" diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index d82098655..2a105ff25 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -22,70 +22,46 @@ #include #include -#include "EC.h" #include "SHA3.h" #include "FileSystem.h" +#include "CryptoPP.h" #include "Common.h" using namespace std; using namespace dev; -using namespace crypto; +using namespace dev::crypto; -//#define ETH_ADDRESS_DEBUG 1 +static Secp256k1 s_secp256k1; -Address dev::toAddress(Secret _secret) +Public dev::toPublic(Secret _secret) { - return KeyPair(_secret).address(); + Public p; + s_secp256k1.toPublic(_secret, p); + return std::move(p); } -KeyPair KeyPair::create() +Address dev::toAddress(Public _public) { - static mt19937_64 s_eng(time(0)); - uniform_int_distribution d(0, 255); - - for (int i = 0; i < 100; ++i) - { - h256 sec; - for (unsigned i = 0; i < 32; ++i) - sec[i] = (byte)d(s_eng); - - KeyPair ret(sec); - if (ret.address()) - return ret; - } - return KeyPair(); -} - -KeyPair::KeyPair(h256 _sec): - m_secret(_sec) -{ - toPublic(m_secret, m_public); - if (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; - cout << "PUB: " << m_public << endl; - cout << "ADR: " << m_address << endl; -#endif + return s_secp256k1.toAddress(_public); } -KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password) +Address dev::toAddress(Secret _secret) { - return KeyPair(sha3(aesDecrypt(_seed, _password))); + Public p; + s_secp256k1.toPublic(_secret, p); + return s_secp256k1.toAddress(p); } void dev::encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher) { bytes io = _plain.toBytes(); - crypto::encrypt(_k, io); + s_secp256k1.encrypt(_k, io); o_cipher = std::move(io); } bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext) { bytes io = _cipher.toBytes(); - crypto::decrypt(_k, io); + s_secp256k1.decrypt(_k, io); if (io.empty()) return false; o_plaintext = std::move(io); @@ -94,17 +70,60 @@ bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext) Public dev::recover(Signature _sig, h256 _message) { - return crypto::recover(_sig, _message.ref()); + return s_secp256k1.recover(_sig, _message.ref()); } Signature dev::sign(Secret _k, h256 _hash) { - return crypto::sign(_k, _hash); + return s_secp256k1.sign(_k, _hash); } bool dev::verify(Public _p, Signature _s, h256 _hash) { - return crypto::verify(_p, _s, bytesConstRef(_hash.data(), 32), true); + return s_secp256k1.verify(_p, _s, bytesConstRef(_hash.data(), 32), true); +} + +KeyPair KeyPair::create() +{ + static mt19937_64 s_eng(time(0)); + uniform_int_distribution d(0, 255); + + for (int i = 0; i < 100; ++i) + { + h256 sec; + for (unsigned i = 0; i < 32; ++i) + sec[i] = (byte)d(s_eng); + + KeyPair ret(sec); + if (ret.address()) + return ret; + } + return KeyPair(); +} + +KeyPair::KeyPair(h256 _sec): + m_secret(_sec) +{ + if (s_secp256k1.verifySecret(m_secret, m_public)) + m_address = s_secp256k1.toAddress(m_public); +} + +KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password) +{ + return KeyPair(sha3(aesDecrypt(_seed, _password))); +} + +h256 crypto::kdf(Secret const& _priv, h256 const& _hash) +{ + // H(H(r||k)^h) + h256 s; + sha3mac(Nonce::get().ref(), _priv.ref(), s.ref()); + s ^= _hash; + sha3(s.ref(), s.ref()); + + if (!s || !_hash || !_priv) + BOOST_THROW_EXCEPTION(InvalidState()); + return std::move(s); } h256 Nonce::get(bool _commit) diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index e95eefa40..cd0996826 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -30,7 +30,7 @@ namespace dev { - + /// A secret key: 32 bytes. /// @NOTE This is not endian-specific; it's just a bunch of bytes. using Secret = h256; @@ -59,6 +59,12 @@ using AddressSet = std::set; using Secrets = h256s; /// Convert a secret key into the public key equivalent. +Public toPublic(Secret _secret); + +/// Convert a public key to address. +Address toAddress(Public _public); + +/// Convert a secret key into address of public key equivalent. /// @returns 0 if it's not a valid secret key. Address toAddress(Secret _secret); @@ -119,6 +125,9 @@ namespace crypto { struct InvalidState: public dev::Exception {}; +/// Key derivation +h256 kdf(Secret const& _priv, h256 const& _hash); + /** * @brief Generator for nonce material */ diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index 0694699ae..1edddefa1 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -21,35 +21,203 @@ #include "CryptoPP.h" +using namespace std; using namespace dev; using namespace dev::crypto; using namespace CryptoPP; +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."); -/// Integer and Point Conversion: +void Secp256k1::encrypt(Public const& _k, bytes& io_cipher) +{ + ECIES::Encryptor e; + initializeDLScheme(_k, e); -void pp::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p) + size_t plen = io_cipher.size(); + bytes ciphertext; + ciphertext.resize(e.CiphertextLength(plen)); + + { + lock_guard l(x_rng); + e.Encrypt(m_rng, io_cipher.data(), plen, ciphertext.data()); + } + + memset(io_cipher.data(), 0, io_cipher.size()); + io_cipher = std::move(ciphertext); +} + +void Secp256k1::decrypt(Secret const& _k, bytes& io_text) { - bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true)); + CryptoPP::ECIES::Decryptor d; + initializeDLScheme(_k, d); + + size_t clen = io_text.size(); + bytes plain; + plain.resize(d.MaxPlaintextLength(io_text.size())); - secp256k1Params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false); + DecodingResult r; + { + lock_guard l(x_rng); + r = d.Decrypt(m_rng, io_text.data(), clen, plain.data()); + } + + if (!r.isValidCoding) + { + io_text.clear(); + return; + } + + io_text.resize(r.messageLength); + io_text = std::move(plain); +} - assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true)); - memcpy(_p.data(), &prefixedKey[1], Public::size); +Signature Secp256k1::sign(Secret const& _k, bytesConstRef _message) +{ + return sign(_k, sha3(_message)); } -void pp::exponentToPublic(Integer const& _e, Public& _p) +Signature Secp256k1::sign(Secret const& _key, h256 const& _hash) { - CryptoPP::DL_PublicKey_EC pk; - pk.Initialize(secp256k1Params, secp256k1Params.ExponentiateBase(_e)); - pp::exportPublicKey(pk, _p); + Signature sig; + + Integer k(kdf(_key, _hash).data(), 32); + if (k == 0) + BOOST_THROW_EXCEPTION(InvalidState()); + k = 1 + (k % (m_qs - 1)); + + ECP::Point rp; + Integer r; + { + lock_guard l(x_params); + rp = m_params.ExponentiateBase(k); + r = m_params.ConvertElementToInteger(rp); + } + sig[64] = 0; +// sig[64] = (r >= m_q) ? 2 : 0; + + Integer kInv = k.InverseMod(m_q); + Integer z(_hash.asBytes().data(), 32); + Integer s = (kInv * (Integer(_key.asBytes().data(), 32)*r + z)) % m_q; + if (r == 0 || s == 0) + BOOST_THROW_EXCEPTION(InvalidState()); + +// if (s > m_qs) +// { +// s = m_q - s; +// if (sig[64]) +// sig[64] ^= 1; +// } + + sig[64] |= rp.y.IsOdd() ? 1 : 0; + r.Encode(sig.data(), 32); + s.Encode(sig.data() + 32, 32); + return sig; } -void pp::ecdhAgree(Secret const& _s, Public const& _r, h256& o_s) +bool Secp256k1::verify(Signature const& _signature, bytesConstRef _message) { - ECDH::Domain d(secp256k1Curve); + return !!recover(_signature, _message); +} + +bool Secp256k1::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) +{ + // todo: verify w/o recovery (if faster) + return _p == _hashed ? recover(_sig, _message) : recover(_sig, sha3(_message).ref()); +} + +Public Secp256k1::recover(Signature _signature, bytesConstRef _message) +{ + Public recovered; + + Integer r(_signature.data(), 32); + Integer s(_signature.data()+32, 32); + // cryptopp encodes sign of y as 0x02/0x03 instead of 0/1 or 27/28 + byte encodedpoint[33]; + encodedpoint[0] = _signature[64]|2; + memcpy(&encodedpoint[1], _signature.data(), 32); + + ECP::Element x; + { + lock_guard l(x_curve); + m_curve.DecodePoint(x, encodedpoint, 33); + if (!m_curve.VerifyPoint(x)) + return recovered; + } + +// if (_signature[64] & 2) +// { +// r += m_q; +// lock_guard l(x_params); +// if (r >= m_params.GetMaxExponent()) +// return recovered; +// } + + Integer z(_message.data(), 32); + Integer rn = r.InverseMod(m_q); + Integer u1 = m_q - (rn.Times(z)).Modulo(m_q); + Integer u2 = (rn.Times(s)).Modulo(m_q); + + ECP::Point p; + byte recoveredbytes[65]; + { + lock_guard l(x_curve); + // todo: make generator member + p = m_curve.CascadeMultiply(u2, x, u1, m_params.GetSubgroupGenerator()); + m_curve.EncodePoint(recoveredbytes, p, false); + } + memcpy(recovered.data(), &recoveredbytes[1], 64); + return recovered; +} + +bool Secp256k1::verifySecret(Secret const& _s, Public& _p) +{ + DL_PrivateKey_EC k; + k.Initialize(m_params, secretToExponent(_s)); + if (!k.Validate(m_rng, 3)) + return false; + + DL_PublicKey_EC pub; + k.MakePublicKey(pub); + if (!k.Validate(m_rng, 3)) + return false; + + exportPublicKey(pub, _p); + return true; +} + +void Secp256k1::agree(Secret const& _s, Public const& _r, h256& o_s) +{ + ECDH::Domain d(m_oid); assert(d.AgreedValueLength() == sizeof(o_s)); byte remote[65] = {0x04}; memcpy(&remote[1], _r.data(), 64); assert(d.Agree(o_s.data(), _s.data(), remote)); } + +void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p) +{ + bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true)); + + { + lock_guard l(x_params); + m_params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false); + assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true)); + } + + memcpy(_p.data(), &prefixedKey[1], Public::size); +} + +void Secp256k1::exponentToPublic(Integer const& _e, Public& _p) +{ + CryptoPP::DL_PublicKey_EC pk; + + { + lock_guard l(x_params); + pk.Initialize(m_params, m_params.ExponentiateBase(_e)); + } + + exportPublicKey(pk, _p); +} + diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h index 1ae4bee74..b8c1272d9 100644 --- a/libdevcrypto/CryptoPP.h +++ b/libdevcrypto/CryptoPP.h @@ -23,6 +23,7 @@ #pragma once +#include // need to leave this one disabled for link-time. blame cryptopp. #pragma GCC diagnostic ignored "-Wunused-function" #pragma warning(push) @@ -48,50 +49,85 @@ #include #pragma warning(pop) #pragma GCC diagnostic pop +#include "SHA3.h" #include "Common.h" namespace dev { namespace crypto { -namespace pp -{ - + using namespace CryptoPP; + +inline ECP::Point publicToPoint(Public const& _p) { Integer x(_p.data(), 32); Integer y(_p.data() + 32, 32); return std::move(ECP::Point(x,y)); } + +inline Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.data(), Secret::size)); } -/// CryptoPP random number pool -static CryptoPP::AutoSeededRandomPool PRNG; +/** + * CryptoPP secp256k1 algorithms. + */ +class Secp256k1 +{ +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()) {} -/// CryptoPP EC Cruve -static const CryptoPP::OID secp256k1Curve = CryptoPP::ASN1::secp256k1(); + Address toAddress(Public const& _p) { return right160(sha3(_p.ref())); } -static const CryptoPP::DL_GroupParameters_EC secp256k1Params(secp256k1Curve); + void toPublic(Secret const& _s, Public& o_public) { exponentToPublic(Integer(_s.data(), sizeof(_s)), o_public); } -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)); } + /// Encrypts text (replace input). + void encrypt(Public const& _k, bytes& io_cipher); -static Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.data(), Secret::size)); } - -void exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p); - -static void exportPrivateKey(CryptoPP::DL_PrivateKey_EC const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); } + /// Decrypts text (replace input). + void decrypt(Secret const& _k, bytes& io_text); -void exponentToPublic(Integer const& _e, Public& _p); - -void ecdhAgree(Secret const& _s, Public const& _r, h256& o_s); - -template -void initializeDLScheme(Secret const& _s, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, secretToExponent(_s)); } + /// @returns siganture of message. + Signature sign(Secret const& _k, bytesConstRef _message); -template -void initializeDLScheme(Public const& _p, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, publicToPoint(_p)); } + /// @returns compact siganture of message hash. + Signature sign(Secret const& _k, h256 const& _hash); -struct Aes128Ctr -{ - Aes128Ctr(h128 _k) { mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); } - CTR_Mode::Encryption mode; + /// 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); + + /// Verify secret key is valid. + bool verifySecret(Secret const& _s, Public& o_p); + + void agree(Secret const& _s, Public const& _r, h256& o_s); + +protected: + void exportPrivateKey(DL_PrivateKey_EC const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); } + + void exportPublicKey(DL_PublicKey_EC const& _k, Public& _p); + + void exponentToPublic(Integer const& _e, Public& _p); + + template void initializeDLScheme(Secret const& _s, T& io_operator) { std::lock_guard l(x_params); io_operator.AccessKey().Initialize(m_params, secretToExponent(_s)); } + + template void initializeDLScheme(Public const& _p, T& io_operator) { std::lock_guard l(x_params); io_operator.AccessKey().Initialize(m_params, publicToPoint(_p)); } + +private: + OID m_oid; + + std::mutex x_rng; + AutoSeededRandomPool m_rng; + + std::mutex x_params; + DL_GroupParameters_EC m_params; + + std::mutex x_curve; + DL_GroupParameters_EC::EllipticCurve m_curve; + + Integer m_q; + Integer m_qs; }; } } -} diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp deleted file mode 100644 index a509a5b41..000000000 --- a/libdevcrypto/EC.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . - */ -/** @file EC.cpp - * @author Alex Leverington - * @date 2014 - * - * ECDSA, ECIES - */ - -#include -#include "CryptoPP.h" -#include "SHA3.h" -#include "SHA3MAC.h" -#include "EC.h" - -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); -} - -h256 crypto::kdf(Secret const& _priv, h256 const& _hash) -{ - // H(H(r||k)^h) - h256 s; - sha3mac(Nonce::get().ref(), _priv.ref(), s.ref()); - s ^= _hash; - sha3(s.ref(), s.ref()); - - if (!s || !_hash || !_priv) - BOOST_THROW_EXCEPTION(InvalidState()); - return std::move(s); -} - -void crypto::encrypt(Public const& _k, bytes& io_cipher) -{ - ECIES::Encryptor 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(PRNG, io_cipher.data(), plen, c.data()); - memset(io_cipher.data(), 0, io_cipher.size()); - io_cipher = std::move(c); -} - -void crypto::decrypt(Secret const& _k, bytes& io_text) -{ - CryptoPP::ECIES::Decryptor 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(PRNG, io_text.data(), clen, p.data()); - if (!r.isValidCoding) - { - io_text.clear(); - return; - } - io_text.resize(r.messageLength); - io_text = std::move(p); -} - -Signature crypto::sign(Secret const& _k, bytesConstRef _message) -{ - 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 const& qs = secp256k1Params.GetSubgroupOrder(); - Integer e(_hash.asBytes().data(), 32); - - Integer k(kdf(_key, _hash).data(), 32); - if (k == 0) - BOOST_THROW_EXCEPTION(InvalidState()); - k = 1 + (k % (qs - 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 > qs) - { - 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; -} - -bool crypto::verify(Signature const& _signature, bytesConstRef _message) -{ - return crypto::verify(crypto::recover(_signature, _message), _signature, _message); -} - -bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) -{ - static size_t derMaxEncodingLength = 72; - if (_hashed) - { - assert(_message.size() == 32); - byte encpub[65] = {0x04}; - memcpy(&encpub[1], _p.data(), 64); - byte dersig[derMaxEncodingLength]; - size_t cssz = DSAConvertSignatureFormat(dersig, derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363); - assert(cssz <= derMaxEncodingLength); - return (1 == secp256k1_ecdsa_verify(_message.data(), _message.size(), dersig, cssz, encpub, 65)); - } - - ECDSA::Verifier verifier; - initializeDLScheme(_p, verifier); - return verifier.VerifyMessage(_message.data(), _message.size(), _sig.data(), sizeof(Signature) - 1); -} - -Public crypto::recover(Signature _signature, bytesConstRef _message) -{ - Integer heInt(_message.data(), 32); - - // 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]; - - 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()); - - 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) -{ - secp256k1_start(); - int ok = secp256k1_ecdsa_seckey_verify(_s.data()); - if (!ok) - return false; - - int pubkeylen = 65; - byte pubkey[pubkeylen]; - 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 deleted file mode 100644 index 2a4155edf..000000000 --- a/libdevcrypto/EC.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . - */ -/** @file EC.h - * @author Alex Leverington - * @date 2014 - * - * ECDSA, ECIES - */ - -#pragma once - -#include "Common.h" - -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. -Signature sign(Secret const& _k, bytesConstRef _message); - -/// Returns compact siganture of message hash. -Signature sign(Secret const& _k, h256 const& _hash); - -/// 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/ECDHE.cpp b/libdevcrypto/ECDHE.cpp index 6b3979874..d6874fa33 100644 --- a/libdevcrypto/ECDHE.cpp +++ b/libdevcrypto/ECDHE.cpp @@ -20,14 +20,14 @@ */ #include "SHA3.h" -#include "SHA3MAC.h" #include "CryptoPP.h" #include "ECDHE.h" using namespace std; using namespace dev; using namespace dev::crypto; -using namespace dev::crypto::pp; + +static Secp256k1 s_secp256k1; void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret) { @@ -36,12 +36,12 @@ void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret) BOOST_THROW_EXCEPTION(InvalidState()); m_remoteEphemeral = _remote; - ecdhAgree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret); + s_secp256k1.agree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret); } void ECDHEKeyExchange::agree(Public const& _remoteEphemeral) { - ecdhAgree(m_ephemeral.sec(), _remoteEphemeral, m_ephemeralSecret); + s_secp256k1.agree(m_ephemeral.sec(), _remoteEphemeral, m_ephemeralSecret); } void ECDHEKeyExchange::exchange(bytes& o_exchange) @@ -50,16 +50,29 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange) // didn't agree on public remote BOOST_THROW_EXCEPTION(InvalidState()); + // The key exchange payload is in two parts and is encrypted + // using ephemeral keypair. + // + // The first part is the 'prefix' which is a zero-knowledge proof + // allowing the remote to resume or emplace a previous session. + // If a session previously exists: + // prefix is sha3(token) // todo: ephemeral entropy from both sides + // If a session doesn't exist: + // prefix is sha3mac(m_ephemeralSecret, + // + // The second part is encrypted using the public key which relates to the prefix. + Public encpk = m_known.first|m_remoteEphemeral; bytes exchange(encpk.asBytes()); // This is the public key which we would like the remote to use, - // which maybe different than previously-known public key. - // Here we would pick an appropriate alias or generate a new one, + // which maybe different than the previously-known public key. + // + // Here we should pick an appropriate alias or generate a new one, // but for now, we use static alias passed to constructor. // Public p; - pp::exponentToPublic(pp::secretToExponent(m_alias.m_secret), p); + s_secp256k1.toPublic(m_alias.m_secret, p); exchange.resize(exchange.size() + sizeof(p)); memcpy(exchange.data() - sizeof(p), p.data(), sizeof(p)); @@ -70,7 +83,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange) h256 auth; sha3mac(m_alias.m_secret.ref(), m_ephemeralSecret.ref(), auth.ref()); - Signature sig = crypto::sign(m_alias.m_secret, auth); + Signature sig = s_secp256k1.sign(m_alias.m_secret, auth); exchange.resize(exchange.size() + sizeof(sig)); memcpy(exchange.data() - sizeof(sig), sig.data(), sizeof(sig)); @@ -78,7 +91,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange) h256 prefix(sha3((h256)(m_known.second|m_remoteEphemeral))); aes.update(prefix.ref()); - encrypt(encpk, exchange); + s_secp256k1.encrypt(encpk, exchange); aes.update(&exchange); aes.streamOut(o_exchange); diff --git a/libdevcrypto/ECDHE.h b/libdevcrypto/ECDHE.h index 88e5ba764..86c333cf9 100644 --- a/libdevcrypto/ECDHE.h +++ b/libdevcrypto/ECDHE.h @@ -24,7 +24,6 @@ #pragma once #include "AES.h" -#include "EC.h" namespace dev { @@ -33,6 +32,9 @@ namespace crypto typedef std::pair AliasSession; +/** + * @brief An addressable EC key pair. + */ class Alias { friend class ECDHEKeyExchange; // todo: remove diff --git a/libdevcrypto/SHA3.cpp b/libdevcrypto/SHA3.cpp index 4a0cd469e..1fc9be950 100644 --- a/libdevcrypto/SHA3.cpp +++ b/libdevcrypto/SHA3.cpp @@ -86,6 +86,16 @@ h256 sha3(bytesConstRef _input) sha3(_input, bytesRef(&ret[0], 32)); return ret; } + +void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output) +{ + CryptoPP::SHA3_256 ctx; + assert(_secret.size() > 0); + ctx.Update((byte*)_secret.data(), _secret.size()); + ctx.Update((byte*)_plain.data(), _plain.size()); + assert(_output.size() >= 32); + ctx.Final(_output.data()); +} bytes aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt) { diff --git a/libdevcrypto/SHA3.h b/libdevcrypto/SHA3.h index 7aa4db246..f27e378ba 100644 --- a/libdevcrypto/SHA3.h +++ b/libdevcrypto/SHA3.h @@ -55,6 +55,9 @@ inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_inpu /// Calculate SHA3-256 hash of the given input (presented as a binary-filled string), returning as a 256-bit hash. inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); } + +/// Calculate SHA3-256 MAC +void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output); /// Calculate SHA3-256 hash of the given input (presented as a FixedHash), returns a 256-bit hash. template inline h256 sha3(FixedHash const& _input) { return sha3(_input.ref()); } diff --git a/libdevcrypto/SHA3MAC.cpp b/libdevcrypto/SHA3MAC.cpp deleted file mode 100644 index 9498ef87b..000000000 --- a/libdevcrypto/SHA3MAC.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . - */ -/** @file SHA3MAC.cpp - * @author Alex Leverington - * @date 2014 - * - * SHA3 MAC - */ - -#include "CryptoPP.h" -#include "SHA3MAC.h" - -using namespace dev; -using namespace dev::crypto; -using namespace CryptoPP; - -void crypto::sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output) -{ - CryptoPP::SHA3_256 ctx; - assert(_secret.size() > 0); - ctx.Update((byte*)_secret.data(), _secret.size()); - ctx.Update((byte*)_plain.data(), _plain.size()); - assert(_output.size() >= 32); - ctx.Final(_output.data()); -} - diff --git a/libdevcrypto/SHA3MAC.h b/libdevcrypto/SHA3MAC.h deleted file mode 100644 index 4b2d06eac..000000000 --- a/libdevcrypto/SHA3MAC.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . - */ -/** @file SHA3MAC.h - * @author Alex Leverington - * @date 2014 - * - * SHA3 MAC - */ - -#pragma once - -#include -#include - -namespace dev -{ -namespace crypto -{ - -void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output); - -} -} - diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index 8e21884ee..3918ff6c7 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -28,7 +28,6 @@ using namespace std; using namespace dev; using namespace dev::eth; -//#define ETH_ADDRESS_DEBUG 1 namespace dev { namespace eth @@ -84,30 +83,4 @@ std::string formatBalance(u256 _b) return ret.str(); } -Address toAddress(Secret _private) -{ - 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); - assert(pubkeylen == 65); - 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; -} - }} diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 35e00f588..8add9e954 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -113,8 +113,6 @@ State::State(Address _coinbaseAddress, OverlayDB const& _db): m_ourAddress(_coinbaseAddress), m_blockReward(c_blockReward) { - secp256k1_start(); - // Initialise to the state entailed by the genesis block; this guarantees the trie is built correctly. m_state.init(); @@ -138,8 +136,6 @@ State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h): m_state(&m_db), m_blockReward(c_blockReward) { - secp256k1_start(); - // TODO THINK: is this necessary? m_state.init(); diff --git a/test/crypto.cpp b/test/crypto.cpp index 4e752fd1a..2a206bdd7 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -27,8 +27,7 @@ #include #include #include -#include -#include +#include #include #include @@ -39,6 +38,21 @@ using namespace CryptoPP; BOOST_AUTO_TEST_SUITE(devcrypto) +static Secp256k1 s_secp256k1; +static CryptoPP::AutoSeededRandomPool s_rng; +static CryptoPP::OID s_curveOID(CryptoPP::ASN1::secp256k1()); +static CryptoPP::DL_GroupParameters_EC s_params(s_curveOID); +static CryptoPP::DL_GroupParameters_EC::EllipticCurve s_curve(s_params.GetCurve()); + +BOOST_AUTO_TEST_CASE(verify_secert) +{ + h256 empty; + KeyPair kNot(empty); + BOOST_REQUIRE(!kNot.address()); + KeyPair k(sha3(empty)); + BOOST_REQUIRE(k.address()); +} + BOOST_AUTO_TEST_CASE(common_encrypt_decrypt) { string message("Now is the time for all good persons to come to the aid of humanity."); @@ -57,103 +71,50 @@ BOOST_AUTO_TEST_CASE(common_encrypt_decrypt) BOOST_REQUIRE(plain == asBytes(message)); } -BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1) -{ - ECIES::Decryptor d(pp::PRNG, pp::secp256k1Curve); - ECIES::Encryptor e(d.GetKey()); - - Secret s; - pp::exportPrivateKey(d.GetKey(), s); - - Public p; - pp::exportPublicKey(e.GetKey(), p); - - BOOST_REQUIRE(dev::toAddress(s) == right160(dev::sha3(p.ref()))); - - Secret previous = s; - for (auto i = 0; i < 2; i++) - { - ECIES::Decryptor d(pp::PRNG, pp::secp256k1Curve); - ECIES::Encryptor e(d.GetKey()); - - Secret s; - pp::exportPrivateKey(d.GetKey(), s); - BOOST_REQUIRE(s != previous); - - Public p; - pp::exportPublicKey(e.GetKey(), p); - - h160 secp256k1Addr = dev::toAddress(s); - h160 cryptoppAddr = right160(dev::sha3(p.ref())); - if (secp256k1Addr != cryptoppAddr) - { - BOOST_REQUIRE(secp256k1Addr == cryptoppAddr); - break; - } - } -} - BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_secp256k1libport) { - // cryptopp implementation of secp256k1lib sign_compact w/recid parameter and recovery of public key from signature - + secp256k1_start(); + // base secret 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 = 2; // Oct 29: successful @ 1500 + int tests = 2; while (sha3(&e, &e), secret = sha3(secret.asBytes()), tests--) { KeyPair key(secret); Public pkey = key.pub(); - pp::initializeDLScheme(secret, signer); + signer.AccessKey().Initialize(s_params, secretToExponent(secret)); h256 he(sha3(e)); Integer heInt(he.asBytes().data(), 32); h256 k(crypto::kdf(secret, he)); Integer kInt(k.asBytes().data(), 32); - kInt %= params.GetSubgroupOrder()-1; + kInt %= s_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); + ECP::Point rp = s_params.ExponentiateBase(kInt); + Integer const& q = s_params.GetGroupOrder(); + Integer r = s_params.ConvertElementToInteger(rp); Integer kInv = kInt.InverseMod(q); Integer s = (kInv * (Integer(secret.asBytes().data(), 32)*r + heInt)) % q; BOOST_REQUIRE(!!r && !!s); - -/* - // For future reference: - // According to maths, this codepath can't be reached, however, it's in secp256k1. - // Commenting this out diverges from codebase implementation. - // To be removed after upstream PR and proof are evaulated. - - if (s > params.GetSubgroupOrder()) - { - // note: this rarely happens - s = params.GetGroupOrder() - s; - if (recid) - recid ^= 1; - } - */ Signature sig; + sig[64] = rp.y.IsOdd() ? 1 : 0; r.Encode(sig.data(), 32); s.Encode(sig.data() + 32, 32); - sig[64] = recid; Public p = dev::recover(sig, he); BOOST_REQUIRE(p == pkey); // verify w/cryptopp - BOOST_REQUIRE(crypto::verify(pkey, sig, bytesConstRef(&e))); + BOOST_REQUIRE(s_secp256k1.verify(pkey, sig, bytesConstRef(&e))); // verify with secp256k1lib byte encpub[65] = {0x04}; @@ -167,17 +128,19 @@ BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_secp256k1libport) BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) { + secp256k1_start(); + // cryptopp integer encoding Integer nHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2H"); Integer nB(fromHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2").data(), 32); BOOST_REQUIRE(nHex == nB); bytes sbytes(fromHex("0xFFFF")); - Secret secret(sha3(sbytes)); // 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2 + Secret secret(sha3(sbytes)); KeyPair key(secret); bytes m(fromHex("0xFF")); - int tests = 3; + int tests = 2; while (m[0]++, tests--) { h256 hm(sha3(m)); @@ -187,42 +150,42 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) // raw sign w/cryptopp (doesn't pass through cryptopp hash filter) ECDSA::Signer signer; - pp::initializeDLScheme(key.sec(), signer); + signer.AccessKey().Initialize(s_params, secretToExponent(key.sec())); Integer r, s; signer.RawSign(kInt, hInt, r, s); // verify cryptopp raw-signature w/cryptopp ECDSA::Verifier verifier; - pp::initializeDLScheme(key.pub(), verifier); + verifier.AccessKey().Initialize(s_params, publicToPoint(key.pub())); 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(crypto::verify(key.pub(), sigppraw, bytesConstRef(&m))); BOOST_REQUIRE(dev::verify(key.pub(), sigppraw, hm)); // 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(crypto::verify(key.pub(), seclibsig, bytesConstRef(&m))); BOOST_REQUIRE(dev::verify(key.pub(), seclibsig, hm)); BOOST_REQUIRE(dev::recover(seclibsig, hm) == key.pub()); // sign with cryptopp (w/hash filter?), verify with cryptopp bytes sigppb(signer.MaxSignatureLength()); - size_t ssz = signer.SignMessage(pp::PRNG, m.data(), m.size(), sigppb.data()); + size_t ssz = signer.SignMessage(s_rng, m.data(), m.size(), sigppb.data()); Signature sigpp; memcpy(sigpp.data(), sigppb.data(), 64); BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppb.data(), ssz)); - BOOST_REQUIRE(crypto::verify(key.pub(), sigpp, bytesConstRef(&m))); +// BOOST_REQUIRE(crypto::verify(key.pub(), sigpp, bytesConstRef(&m))); BOOST_REQUIRE(dev::verify(key.pub(), sigpp, hm)); // sign with cryptopp and stringsource hash filter string sigstr; - StringSource ssrc(asString(m), true, new SignerFilter(pp::PRNG, signer, new StringSink(sigstr))); + StringSource ssrc(asString(m), true, new SignerFilter(s_rng, signer, new StringSink(sigstr))); FixedHash retsig((byte const*)sigstr.data(), Signature::ConstructFromPointer); BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), retsig.data(), 64)); - BOOST_REQUIRE(crypto::verify(key.pub(), retsig, bytesConstRef(&m))); +// BOOST_REQUIRE(crypto::verify(key.pub(), retsig, bytesConstRef(&m))); BOOST_REQUIRE(dev::verify(key.pub(), retsig, hm)); /// verification w/sec256lib @@ -248,22 +211,6 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) } } -BOOST_AUTO_TEST_CASE(cryptopp_public_export_import) -{ - ECIES::Decryptor d(pp::PRNG, pp::secp256k1Curve); - ECIES::Encryptor e(d.GetKey()); - - Secret s; - pp::exportPrivateKey(d.GetKey(), s); - Public p; - pp::exportPublicKey(e.GetKey(), p); - Address addr = right160(dev::sha3(p.ref())); - BOOST_REQUIRE(toAddress(s) == addr); - - KeyPair l(s); - BOOST_REQUIRE(l.address() == addr); -} - BOOST_AUTO_TEST_CASE(ecies_eckeypair) { KeyPair k = KeyPair::create(); @@ -272,10 +219,10 @@ BOOST_AUTO_TEST_CASE(ecies_eckeypair) string original = message; bytes b = asBytes(message); - encrypt(k.pub(), b); + s_secp256k1.encrypt(k.pub(), b); BOOST_REQUIRE(b != asBytes(original)); - decrypt(k.sec(), b); + s_secp256k1.decrypt(k.sec(), b); BOOST_REQUIRE(b == asBytes(original)); } @@ -283,15 +230,15 @@ BOOST_AUTO_TEST_CASE(ecdh) { cnote << "Testing ecdh..."; - ECDH::Domain dhLocal(pp::secp256k1Curve); + ECDH::Domain dhLocal(s_curveOID); SecByteBlock privLocal(dhLocal.PrivateKeyLength()); SecByteBlock pubLocal(dhLocal.PublicKeyLength()); - dhLocal.GenerateKeyPair(pp::PRNG, privLocal, pubLocal); + dhLocal.GenerateKeyPair(s_rng, privLocal, pubLocal); - ECDH::Domain dhRemote(pp::secp256k1Curve); + ECDH::Domain dhRemote(s_curveOID); SecByteBlock privRemote(dhRemote.PrivateKeyLength()); SecByteBlock pubRemote(dhRemote.PublicKeyLength()); - dhRemote.GenerateKeyPair(pp::PRNG, privRemote, pubRemote); + dhRemote.GenerateKeyPair(s_rng, privRemote, pubRemote); assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength()); @@ -323,7 +270,7 @@ BOOST_AUTO_TEST_CASE(ecdh) byte pubb[65] = {0x04}; memcpy(&pubb[1], b.pub().data(), 64); - ECDH::Domain dhA(pp::secp256k1Curve); + ECDH::Domain dhA(s_curveOID); Secret shared; BOOST_REQUIRE(dhA.Agree(shared.data(), a.sec().data(), pubb)); BOOST_REQUIRE(shared); From f560cfa78d23764636949f286edce8048fcfeb32 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 13 Nov 2014 03:13:30 +0100 Subject: [PATCH 10/27] fix compile --- libdevcrypto/AES.cpp | 5 ++++- libdevcrypto/AES.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp index 1807bad19..0682adea3 100644 --- a/libdevcrypto/AES.cpp +++ b/libdevcrypto/AES.cpp @@ -30,7 +30,10 @@ using namespace CryptoPP; struct aes::Aes128Ctr { - Aes128Ctr(h128 _k) { mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); } + Aes128Ctr(h128 _k) + { + mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); + } CryptoPP::CTR_Mode::Encryption mode; }; diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h index 2bb852653..7a1beefe5 100644 --- a/libdevcrypto/AES.h +++ b/libdevcrypto/AES.h @@ -19,10 +19,12 @@ * @date 2014 * * AES + * todo: use openssl */ #pragma once +#include #include "Common.h" namespace dev From c99e09dc49d13201d425eff9e24ea23c444ff597 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 13 Nov 2014 13:20:10 +0100 Subject: [PATCH 11/27] code review --- libdevcrypto/AES.cpp | 2 +- libdevcrypto/AES.h | 6 ++++++ libdevcrypto/Common.cpp | 26 +++++++++++--------------- libdevcrypto/Common.h | 18 +++++++++--------- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp index 0682adea3..bcfbbbdc0 100644 --- a/libdevcrypto/AES.cpp +++ b/libdevcrypto/AES.cpp @@ -34,7 +34,7 @@ struct aes::Aes128Ctr { mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); } - CryptoPP::CTR_Mode::Encryption mode; + CTR_Mode::Encryption mode; }; Stream::Stream(StreamType _t, h128 _ckey): diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h index 7a1beefe5..af4f781cd 100644 --- a/libdevcrypto/AES.h +++ b/libdevcrypto/AES.h @@ -53,6 +53,9 @@ public: virtual size_t streamOut(bytes& o_bytes); private: + Stream(Stream const&) = delete; + Stream& operator=(Stream const&) = delete; + h128 m_cSecret; bytes m_text; @@ -74,6 +77,9 @@ public: void adjustInterval(unsigned _interval) { m_macInterval = _interval; }; private: + AuthenticatedStream(AuthenticatedStream const&) = delete; + AuthenticatedStream& operator=(AuthenticatedStream const&) = delete; + std::atomic m_macInterval; h128 m_macSecret; }; diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index 9107fe9ca..fa5a544a1 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -33,33 +33,33 @@ using namespace dev::crypto; static Secp256k1 s_secp256k1; -Public dev::toPublic(Secret _secret) +Public dev::toPublic(Secret const& _secret) { Public p; s_secp256k1.toPublic(_secret, p); return std::move(p); } -Address dev::toAddress(Public _public) +Address dev::toAddress(Public const& _public) { return s_secp256k1.toAddress(_public); } -Address dev::toAddress(Secret _secret) +Address dev::toAddress(Secret const& _secret) { Public p; s_secp256k1.toPublic(_secret, p); return s_secp256k1.toAddress(p); } -void dev::encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher) +void dev::encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher) { bytes io = _plain.toBytes(); s_secp256k1.encrypt(_k, io); o_cipher = std::move(io); } -bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext) +bool dev::decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext) { bytes io = _cipher.toBytes(); s_secp256k1.decrypt(_k, io); @@ -69,19 +69,19 @@ bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext) return true; } -Public dev::recover(Signature _sig, h256 _message) +Public dev::recover(Signature const& _sig, h256 const& _message) { return s_secp256k1.recover(_sig, _message.ref()); } -Signature dev::sign(Secret _k, h256 _hash) +Signature dev::sign(Secret const& _k, h256 const& _hash) { return s_secp256k1.sign(_k, _hash); } -bool dev::verify(Public _p, Signature _s, h256 _hash) +bool dev::verify(Public const& _p, Signature const& _s, h256 const& _hash) { - return s_secp256k1.verify(_p, _s, bytesConstRef(_hash.data(), 32), true); + return s_secp256k1.verify(_p, _s, _hash.ref(), true); } KeyPair KeyPair::create() @@ -91,11 +91,7 @@ KeyPair KeyPair::create() for (int i = 0; i < 100; ++i) { - h256 sec; - for (unsigned i = 0; i < 32; ++i) - sec[i] = (byte)d(s_eng); - - KeyPair ret(sec); + KeyPair ret(FixedHash<32>::random(s_eng)); if (ret.address()) return ret; } @@ -144,7 +140,7 @@ h256 Nonce::get(bool _commit) else { // todo: replace w/entropy from user and system - std::mt19937_64 s_eng(time(0)); + std::mt19937_64 s_eng(time(0) + chrono::high_resolution_clock::now().time_since_epoch().count()); std::uniform_int_distribution d(0, 255); for (unsigned i = 0; i < 32; ++i) s_seed[i] = (byte)d(s_eng); diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index cd0996826..87d47937e 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -30,7 +30,7 @@ namespace dev { - + /// A secret key: 32 bytes. /// @NOTE This is not endian-specific; it's just a bunch of bytes. using Secret = h256; @@ -59,29 +59,29 @@ using AddressSet = std::set; using Secrets = h256s; /// Convert a secret key into the public key equivalent. -Public toPublic(Secret _secret); +Public toPublic(Secret const& _secret); /// Convert a public key to address. -Address toAddress(Public _public); +Address toAddress(Public const& _public); /// Convert a secret key into address of public key equivalent. /// @returns 0 if it's not a valid secret key. -Address toAddress(Secret _secret); +Address toAddress(Secret const& _secret); /// Encrypts plain text using Public key. -void encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher); +void encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher); /// Decrypts cipher using Secret key. -bool decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext); +bool decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext); /// Recovers Public key from signed message hash. -Public recover(Signature _sig, h256 _hash); +Public recover(Signature const& _sig, h256 const& _hash); /// Returns siganture of message hash. -Signature sign(Secret _k, h256 _hash); +Signature sign(Secret const& _k, h256 const& _hash); /// Verify signature. -bool verify(Public _k, Signature _s, h256 _hash); +bool verify(Public const& _k, Signature const& _s, h256 const& _hash); /// Simple class that represents a "key pair". /// All of the data of the class can be regenerated from the secret key (m_secret) alone. From fd5738ae64d3d1b0e68d010c78e69f6c283615d8 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 13 Nov 2014 13:31:43 +0100 Subject: [PATCH 12/27] fix hash in constructor --- libdevcrypto/AES.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h index af4f781cd..f0646eb85 100644 --- a/libdevcrypto/AES.h +++ b/libdevcrypto/AES.h @@ -71,10 +71,10 @@ class AuthenticatedStream: public Stream public: AuthenticatedStream(StreamType _t, h128 _ckey, h128 _mackey, unsigned _interval): Stream(_t, _ckey), m_macSecret(_mackey) { m_macInterval = _interval; } - AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval): Stream(_t, h128(_s)), m_macSecret(FixedHash<16>(_s[0]+16)) { m_macInterval = _interval; } + AuthenticatedStream(StreamType _t, Secret const& _s, unsigned _interval): Stream(_t, h128(_s)), m_macSecret(FixedHash<16>((byte const*)_s.data()+16,h128::ConstructFromPointer)) { m_macInterval = _interval; } /// Adjust mac interval. Next mac will be xored with value. - void adjustInterval(unsigned _interval) { m_macInterval = _interval; }; + void adjustInterval(unsigned _interval) { m_macInterval = _interval; } private: AuthenticatedStream(AuthenticatedStream const&) = delete; From cf3f821d71058bee97da2e21f3978f0b949ab927 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 13 Nov 2014 17:40:44 +0100 Subject: [PATCH 13/27] changes for code review --- libdevcrypto/AES.cpp | 3 +-- libdevcrypto/Common.h | 2 +- libdevcrypto/CryptoPP.cpp | 11 +++++++---- libdevcrypto/CryptoPP.h | 12 ++++++------ libdevcrypto/ECDHE.cpp | 17 ++++++++--------- libdevcrypto/ECDHE.h | 3 ++- test/crypto.cpp | 2 +- 7 files changed, 26 insertions(+), 24 deletions(-) diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp index bcfbbbdc0..56885ae36 100644 --- a/libdevcrypto/AES.cpp +++ b/libdevcrypto/AES.cpp @@ -37,10 +37,9 @@ struct aes::Aes128Ctr CTR_Mode::Encryption mode; }; -Stream::Stream(StreamType _t, h128 _ckey): +Stream::Stream(StreamType, h128 _ckey): m_cSecret(_ckey) { - (void)_t; // encrypt and decrypt are same operation w/ctr cryptor = new Aes128Ctr(_ckey); } diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index 87d47937e..2ec332d8d 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -52,7 +52,7 @@ using Address = h160; /// A vector of Ethereum addresses. using Addresses = h160s; -/// A vector of Ethereum addresses. +/// A set of Ethereum addresses. using AddressSet = std::set; /// A vector of secrets. diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index 1edddefa1..858fd53ff 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -80,6 +80,9 @@ Signature Secp256k1::sign(Secret const& _k, bytesConstRef _message) Signature Secp256k1::sign(Secret const& _key, h256 const& _hash) { + // assumption made by signing alogrithm + asserts(m_q == m_qs); + Signature sig; Integer k(kdf(_key, _hash).data(), 32); @@ -196,7 +199,7 @@ void Secp256k1::agree(Secret const& _s, Public const& _r, h256& o_s) assert(d.Agree(o_s.data(), _s.data(), remote)); } -void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& _p) +void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC const& _k, Public& o_p) { bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true)); @@ -206,10 +209,10 @@ void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC const& assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true)); } - memcpy(_p.data(), &prefixedKey[1], Public::size); + memcpy(o_p.data(), &prefixedKey[1], Public::size); } -void Secp256k1::exponentToPublic(Integer const& _e, Public& _p) +void Secp256k1::exponentToPublic(Integer const& _e, Public& o_p) { CryptoPP::DL_PublicKey_EC pk; @@ -218,6 +221,6 @@ void Secp256k1::exponentToPublic(Integer const& _e, Public& _p) pk.Initialize(m_params, m_params.ExponentiateBase(_e)); } - exportPublicKey(pk, _p); + exportPublicKey(pk, o_p); } diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h index b8c1272d9..69189aaab 100644 --- a/libdevcrypto/CryptoPP.h +++ b/libdevcrypto/CryptoPP.h @@ -84,10 +84,10 @@ public: /// @returns siganture of message. Signature sign(Secret const& _k, bytesConstRef _message); - /// @returns compact siganture of message hash. + /// @returns compact siganture of provided hash. Signature sign(Secret const& _k, h256 const& _hash); - /// Verify compact signature (public key is extracted from message). + /// Verify compact signature (public key is extracted from signature). bool verify(Signature const& _signature, bytesConstRef _message); /// Verify signature. @@ -96,17 +96,17 @@ public: /// Recovers public key from compact signature. Uses libsecp256k1. Public recover(Signature _signature, bytesConstRef _message); - /// Verify secret key is valid. + /// Verifies _s is a valid secret key and returns corresponding public key in o_p. bool verifySecret(Secret const& _s, Public& o_p); void agree(Secret const& _s, Public const& _r, h256& o_s); protected: - void exportPrivateKey(DL_PrivateKey_EC const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); } + void exportPrivateKey(DL_PrivateKey_EC const& _k, Secret& o_s) { _k.GetPrivateExponent().Encode(o_s.data(), Secret::size); } - void exportPublicKey(DL_PublicKey_EC const& _k, Public& _p); + void exportPublicKey(DL_PublicKey_EC const& _k, Public& o_p); - void exponentToPublic(Integer const& _e, Public& _p); + void exponentToPublic(Integer const& _e, Public& o_p); template void initializeDLScheme(Secret const& _s, T& io_operator) { std::lock_guard l(x_params); io_operator.AccessKey().Initialize(m_params, secretToExponent(_s)); } diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp index d6874fa33..7968ab7cc 100644 --- a/libdevcrypto/ECDHE.cpp +++ b/libdevcrypto/ECDHE.cpp @@ -58,11 +58,11 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange) // If a session previously exists: // prefix is sha3(token) // todo: ephemeral entropy from both sides // If a session doesn't exist: - // prefix is sha3mac(m_ephemeralSecret, + // prefix is sha3(m_ephemeralSecret) // // The second part is encrypted using the public key which relates to the prefix. - Public encpk = m_known.first|m_remoteEphemeral; + Public encpk = m_known.first | m_remoteEphemeral; bytes exchange(encpk.asBytes()); // This is the public key which we would like the remote to use, @@ -71,24 +71,23 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange) // Here we should pick an appropriate alias or generate a new one, // but for now, we use static alias passed to constructor. // - Public p; - s_secp256k1.toPublic(m_alias.m_secret, p); + Public p = toPublic(m_alias.m_secret); exchange.resize(exchange.size() + sizeof(p)); - memcpy(exchange.data() - sizeof(p), p.data(), sizeof(p)); + memcpy(&exchange[exchange.size() - sizeof(p)], p.data(), sizeof(p)); // protocol parameters; should be fixed size - bytes v(asBytes("\x80")); + bytes v({0x80}); exchange.resize(exchange.size() + v.size()); - memcpy(exchange.data() - v.size(), v.data(), v.size()); + memcpy(&exchange[exchange.size() - v.size()], v.data(), v.size()); h256 auth; sha3mac(m_alias.m_secret.ref(), m_ephemeralSecret.ref(), auth.ref()); Signature sig = s_secp256k1.sign(m_alias.m_secret, auth); exchange.resize(exchange.size() + sizeof(sig)); - memcpy(exchange.data() - sizeof(sig), sig.data(), sizeof(sig)); + memcpy(&exchange[exchange.size() - sizeof(sig)], sig.data(), sizeof(sig)); aes::AuthenticatedStream aes(aes::Encrypt, m_ephemeralSecret, 0); - h256 prefix(sha3((h256)(m_known.second|m_remoteEphemeral))); + h256 prefix(sha3((h256)m_remoteEphemeral | m_known.second)); aes.update(prefix.ref()); s_secp256k1.encrypt(encpk, exchange); diff --git a/libdevcrypto/ECDHE.h b/libdevcrypto/ECDHE.h index 86c333cf9..f77f7fcff 100644 --- a/libdevcrypto/ECDHE.h +++ b/libdevcrypto/ECDHE.h @@ -30,6 +30,7 @@ namespace dev namespace crypto { +/// Public key of remote and corresponding shared secret. typedef std::pair AliasSession; /** @@ -41,7 +42,7 @@ class Alias public: Alias(Secret _s): m_secret(_s) {}; - AliasSession session(Address _a) { return m_sessions.count(_a) ? AliasSession() : m_sessions.find(_a)->second; } + AliasSession session(Address _a) { return m_sessions.count(_a) ? m_sessions.find(_a)->second : AliasSession(); } private: std::map m_sessions; diff --git a/test/crypto.cpp b/test/crypto.cpp index 2a206bdd7..cd7d8e984 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) Secret secret(sha3(sbytes)); KeyPair key(secret); - bytes m(fromHex("0xFF")); + bytes m({0xFF}); int tests = 2; while (m[0]++, tests--) { From c9dbdb6a7ed1ef6274bac38685b7ff14c23b65e1 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 13 Nov 2014 18:00:58 +0100 Subject: [PATCH 14/27] fix ternary --- libdevcrypto/ECDHE.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp index 7968ab7cc..dd72e8176 100644 --- a/libdevcrypto/ECDHE.cpp +++ b/libdevcrypto/ECDHE.cpp @@ -62,7 +62,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange) // // The second part is encrypted using the public key which relates to the prefix. - Public encpk = m_known.first | m_remoteEphemeral; + Public encpk = m_known.first ? m_known.first : m_remoteEphemeral; bytes exchange(encpk.asBytes()); // This is the public key which we would like the remote to use, @@ -87,7 +87,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange) memcpy(&exchange[exchange.size() - sizeof(sig)], sig.data(), sizeof(sig)); aes::AuthenticatedStream aes(aes::Encrypt, m_ephemeralSecret, 0); - h256 prefix(sha3((h256)m_remoteEphemeral | m_known.second)); + h256 prefix(sha3(m_known.second ? m_known.second : (h256)m_remoteEphemeral)); aes.update(prefix.ref()); s_secp256k1.encrypt(encpk, exchange); From a25185172b8e3c03e3bb8f42c286b081fbeddf88 Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 14 Nov 2014 13:14:22 +0100 Subject: [PATCH 15/27] pr fix --- test/crypto.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/crypto.cpp b/test/crypto.cpp index cd7d8e984..d8bd25035 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -340,8 +340,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) // 68 % 255 should be difference of counter e.ProcessData(out, in, text.size()); - - (u128)ctr += (u128)(text.size() % 16); + ctr = h128(u128(ctr) + text.size() % 16); BOOST_REQUIRE(text != original); cipherCopy = text; From 20f3b4b4c1799abc130a8dee843aab34b2cbe733 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 14 Nov 2014 13:28:01 +0100 Subject: [PATCH 16/27] Spelling correction. --- libp2p/Host.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index bf8d96506..4b28a63a3 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -386,7 +386,7 @@ shared_ptr Host::noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, boo { RecursiveGuard l(x_peers); if (_a.port() < 30300 || _a.port() > 30303) - cwarn << "Wierd port being recorded!"; + cwarn << "Weird port being recorded: " << _a.port(); if (_a.port() >= /*49152*/32768) { From ffdfb74b45a29b57d61710e0d6bf6f5c2f8cb9d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Nov 2014 13:42:07 +0100 Subject: [PATCH 17/27] Update Visual Studio project files --- windows/LibEthereum.vcxproj | 7 ++++--- windows/LibEthereum.vcxproj.filters | 17 ++++++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 35ca956d3..0578a8f16 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -125,8 +125,8 @@ - + true true @@ -341,7 +341,8 @@ - + + true @@ -567,4 +568,4 @@ - + \ No newline at end of file diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index 514320472..114364008 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -40,9 +40,6 @@ libevmcore - - liblll - liblll @@ -202,6 +199,9 @@ libethereum + + libevmcore + @@ -248,9 +248,6 @@ liblll - - - libevmcore liblll @@ -435,6 +432,12 @@ libethereum + + libevmcore + + + libevmcore + @@ -471,4 +474,4 @@ {d838fece-fc20-42f6-bff5-97c236159b80} - + \ No newline at end of file From bd4fe9d26fb85da7ec93152a7037596a8ad6d78e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 14 Nov 2014 17:49:15 +0100 Subject: [PATCH 18/27] Don't log coinbases. --- libethereum/State.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index ec2a640a9..92793f65d 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -795,8 +795,6 @@ h256 State::oldBloom() const LogBloom State::logBloom() const { LogBloom ret; - auto sa = sha3(m_currentBlock.coinbaseAddress.ref()); - ret.shiftBloom<3>(sa); for (TransactionReceipt const& i: m_receipts) ret |= i.bloom(); return ret; From 7dfd83e8f5bfe8ef084e9afd23890b2e1b11bc9e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 12:59:16 +0100 Subject: [PATCH 19/27] Whisper API change for topics. Don't keep dead nodes. --- libp2p/Host.cpp | 6 +++--- libwhisper/Common.cpp | 2 +- libwhisper/Common.h | 7 +------ 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 4b28a63a3..be9f2f7ae 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -778,7 +778,7 @@ bytes Host::saveNodes() const { Node const& n = *(i.second); // TODO: PoC-7: Figure out why it ever shares these ports.//n.address.port() >= 30300 && n.address.port() <= 30305 && - if (!n.dead && n.address.port() > 0 && n.address.port() < /*49152*/32768 && n.id != id() && !isPrivateAddress(n.address.address())) + if (!n.dead && chrono::system_clock::now() - n.lastConnected < chrono::seconds(3600 * 48) && n.address.port() > 0 && n.address.port() < /*49152*/32768 && n.id != id() && !isPrivateAddress(n.address.address())) { nodes.appendList(10); if (n.address.address().is_v4()) @@ -786,8 +786,8 @@ bytes Host::saveNodes() const else nodes << n.address.address().to_v6().to_bytes(); nodes << n.address.port() << n.id << (int)n.idOrigin - << std::chrono::duration_cast(n.lastConnected.time_since_epoch()).count() - << std::chrono::duration_cast(n.lastAttempted.time_since_epoch()).count() + << chrono::duration_cast(n.lastConnected.time_since_epoch()).count() + << chrono::duration_cast(n.lastAttempted.time_since_epoch()).count() << n.failedAttempts << (unsigned)n.lastDisconnect << n.score << n.rating; count++; } diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp index 83f289875..0d54af089 100644 --- a/libwhisper/Common.cpp +++ b/libwhisper/Common.cpp @@ -69,7 +69,7 @@ TopicMask BuildTopicMask::toTopicMask() const TopicMask ret; ret.reserve(m_parts.size()); for (auto const& h: m_parts) - ret.push_back(make_pair(TopicPart(h), h ? ~TopicPart() : TopicPart())); + ret.push_back(make_pair(TopicPart(h), ~TopicPart())); return ret; } diff --git a/libwhisper/Common.h b/libwhisper/Common.h index 312cbf6d3..a704a2896 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -114,17 +114,12 @@ private: class BuildTopicMask: BuildTopic { public: - enum EmptyType { Empty }; - - BuildTopicMask() { shift(); } - BuildTopicMask(EmptyType) {} + template BuildTopicMask() {} template BuildTopicMask(T const& _t) { shift(_t); } template BuildTopicMask& shift(T const& _r) { BuildTopic::shift(_r); return *this; } BuildTopicMask& shiftRaw(h256 const& _h) { BuildTopic::shiftRaw(_h); return *this; } - BuildTopic& shift() { m_parts.push_back(h256()); return *this; } - BuildTopicMask& operator()() { shift(); return *this; } template BuildTopicMask& operator()(T const& _t) { shift(_t); return *this; } operator TopicMask() const { return toTopicMask(); } From 3b17797b4604c7ad6614c62edab5d7f2475f92b6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 14:50:45 +0100 Subject: [PATCH 20/27] Build fixes. --- libweb3jsonrpc/WebThreeStubServer.cpp | 6 +----- libwhisper/Common.h | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 092faae09..73c938ce2 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -240,7 +240,7 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, static pair toWatch(Json::Value const& _json) { - shh::BuildTopicMask bt(shh::BuildTopicMask::Empty); + shh::BuildTopicMask bt; Public to; if (!_json["to"].empty()) @@ -252,12 +252,8 @@ static pair toWatch(Json::Value const& _json) bt.shift(jsToBytes(_json["topic"].asString())); else if (_json["topic"].isArray()) for (auto i: _json["topic"]) - { if (i.isString()) bt.shift(jsToBytes(i.asString())); - else - bt.shift(); - } } return make_pair(bt.toTopicMask(), to); } diff --git a/libwhisper/Common.h b/libwhisper/Common.h index a704a2896..5ce7d3b1c 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -114,7 +114,7 @@ private: class BuildTopicMask: BuildTopic { public: - template BuildTopicMask() {} + BuildTopicMask() {} template BuildTopicMask(T const& _t) { shift(_t); } template BuildTopicMask& shift(T const& _r) { BuildTopic::shift(_r); return *this; } From c0b3f93e8e8a61df944a3bbbb5b1b01931be05c1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 15:14:40 +0100 Subject: [PATCH 21/27] Fix first part of stdserv.js. Still much to do. --- stdserv.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/stdserv.js b/stdserv.js index 55ae90d86..887586874 100644 --- a/stdserv.js +++ b/stdserv.js @@ -1,7 +1,9 @@ eth = web3.eth; +env = web3.env; env.note('Creating Config...') -var configCode = eth.lll(" +var config; +eth.lll(" { [[69]] (caller) (returnlll { @@ -12,13 +14,19 @@ var configCode = eth.lll(" ) (return @@ $0) }) -} -") -env.note('Config code: ' + configCode) -var config; -eth.transact({ 'code': configCode }, function(a) { config = a; }); +}" +).then(function(configCode) +{ + console.log('Config code: ' + configCode); + return eth.transact({ 'code': configCode }); +}).then(function(configAddress) +{ + config = configAddress; + console.log('Config at address ' + configAddress); +}); -env.note('Config at address ' + config) +// marek: TODO +/* var nameRegCode = eth.lll(" { @@ -306,7 +314,7 @@ eth.transact({ 'to': exchange, 'data': [web3.fromAscii('new'), gavCoin, '5000', env.note('Register gav.eth...') eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] }); - +*/ env.note('All done.') // env.load('/home/gav/Eth/cpp-ethereum/stdserv.js') From e2b3925683ff58beaa2b7a0f7c0d8fa00e7bc80a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 15:38:30 +0100 Subject: [PATCH 22/27] More fixing for std serv --- alethzero/MainWin.cpp | 5 ++++- stdserv.js | 40 +++++++++++++++++----------------------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 0ad5ba938..e10d01efc 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -355,6 +355,9 @@ void Main::on_enableOptimizer_triggered() void Main::load(QString _s) { + QString contents = QString::fromStdString(dev::asString(dev::contents(_s.toStdString()))); + ui->webView->page()->currentFrame()->evaluateJavaScript(contents); + /* QFile fin(_s); if (!fin.open(QFile::ReadOnly)) return; @@ -375,7 +378,7 @@ void Main::load(QString _s) //eval(line); line.clear(); } - } + }*/ } void Main::on_loadJS_triggered() diff --git a/stdserv.js b/stdserv.js index 887586874..375a8379f 100644 --- a/stdserv.js +++ b/stdserv.js @@ -1,29 +1,23 @@ eth = web3.eth; env = web3.env; -env.note('Creating Config...') -var config; -eth.lll(" -{ - [[69]] (caller) - (returnlll { - (when (&& (= (calldatasize) 64) (= (caller) @@69)) - (for {} (< @i (calldatasize)) [i](+ @i 64) - [[ (calldataload @i) ]] (calldataload (+ @i 32)) - ) - ) - (return @@ $0) - }) -}" -).then(function(configCode) -{ - console.log('Config code: ' + configCode); - return eth.transact({ 'code': configCode }); -}).then(function(configAddress) -{ - config = configAddress; - console.log('Config at address ' + configAddress); -}); +var configSource = +"{"+ +" [[69]] (caller)"+ +" (returnlll {"+ +" (when (&& (= (calldatasize) 64) (= (caller) @@69))"+ +" (for {} (< @i (calldatasize)) [i](+ @i 64)"+ +" [[ (calldataload @i) ]] (calldataload (+ @i 32))"+ +" )"+ +" )"+ +" (return @@ $0)"+ +" })"+ +"}"; + +console.log('Creating Config...') +var config = eth.lll(configSource); +config = config.then(function (configCode) { console.log('Config code: ' + configCode); return eth.transact({ 'code': configCode }); }); +config.then(function(configAddress) { console.log('Config at address ' + configAddress); config = configAddress; return configAddress; }); // marek: TODO /* From c80fe4728988f66ef0bdaadbdf4d51ce8aec235f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 21:07:47 +0100 Subject: [PATCH 23/27] Fix std services except DNS Reg whose contract needs rewriting. --- alethzero/MainWin.cpp | 7 +- alethzero/MainWin.h | 1 + libdevcore/CommonJS.cpp | 31 +-- libdevcore/CommonJS.h | 11 +- libdevcore/Exceptions.h | 4 +- libethereum/Executive.cpp | 6 +- libevm/VM.h | 2 +- libqethereum/QEthereum.h | 1 + libweb3jsonrpc/WebThreeStubServer.cpp | 4 +- stdserv.js | 324 +++----------------------- 10 files changed, 62 insertions(+), 329 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index e10d01efc..dc5b326bc 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -353,6 +353,11 @@ void Main::on_enableOptimizer_triggered() on_data_textChanged(); } +QString Main::contents(QString _s) +{ + return QString::fromStdString(dev::asString(dev::contents(_s.toStdString()))); +} + void Main::load(QString _s) { QString contents = QString::fromStdString(dev::asString(dev::contents(_s.toStdString()))); @@ -682,7 +687,7 @@ void Main::on_importKeyFile_triggered() try { js::mValue val; - json_spirit::read_string(asString(contents(s.toStdString())), val); + json_spirit::read_string(asString(dev::contents(s.toStdString())), val); auto obj = val.get_obj(); if (obj["encseed"].type() == js::str_type) { diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 9f7ad97de..14877f610 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -85,6 +85,7 @@ public slots: void note(QString _entry); void debug(QString _entry); void warn(QString _entry); + QString contents(QString _file); void onKeysChanged(); diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index 96f4b1896..c09a5b565 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -38,31 +38,20 @@ bytes jsToBytes(std::string const& _s) return bytes(); } -std::string jsPadded(std::string const& _s, unsigned _l, unsigned _r) +bytes padded(bytes _b, unsigned _l) { - bytes b = jsToBytes(_s); - while (b.size() < _l) - b.insert(b.begin(), 0); - while (b.size() < _r) - b.push_back(0); - return asString(b).substr(b.size() - std::max(_l, _r)); + while (_b.size() < _l) + _b.insert(_b.begin(), 0); + while (_b.size() < _l) + _b.push_back(0); + return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l))); } -std::string jsPadded(std::string const& _s, unsigned _l) +bytes unpadded(bytes _b) { - if (_s.substr(0, 2) == "0x" || _s.find_first_not_of("0123456789") == std::string::npos) - // Numeric: pad to right - return jsPadded(_s, _l, _l); - else - // Text: pad to the left - return jsPadded(_s, 0, _l); -} - -std::string jsUnpadded(std::string _s) -{ - auto p = _s.find_last_not_of((char)0); - _s.resize(p == std::string::npos ? 0 : (p + 1)); - return _s; + auto p = asString(_b).find_last_not_of((char)0); + _b.resize(p == std::string::npos ? 0 : (p + 1)); + return _b; } } diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h index be98c2372..80e1a9ca1 100644 --- a/libdevcore/CommonJS.h +++ b/libdevcore/CommonJS.h @@ -47,9 +47,8 @@ inline std::string toJS(dev::bytes const& _n) } bytes jsToBytes(std::string const& _s); -std::string jsPadded(std::string const& _s, unsigned _l, unsigned _r); -std::string jsPadded(std::string const& _s, unsigned _l); -std::string jsUnpadded(std::string _s); +bytes padded(bytes _b, unsigned _l); +bytes unpadded(bytes _s); template FixedHash jsToFixed(std::string const& _s) { @@ -61,7 +60,7 @@ template FixedHash jsToFixed(std::string const& _s) return (typename FixedHash::Arith)(_s); else // Binary - return FixedHash(asBytes(jsPadded(_s, N))); + return FixedHash(); // FAIL } inline std::string jsToFixed(double _s) @@ -79,7 +78,7 @@ template boost::multiprecision::number>(_s); else // Binary - return fromBigEndian>>(asBytes(jsPadded(_s, N))); + return 0; // FAIL } inline Address jsToAddress(std::string const& _s) { return jsToFixed(_s); } @@ -89,7 +88,7 @@ inline u256 jsToU256(std::string const& _s) { return jsToInt<32>(_s); } inline std::string jsToBinary(std::string const& _s) { - return jsUnpadded(dev::toString(jsToBytes(_s))); + return dev::toString(unpadded(jsToBytes(_s))); } inline std::string jsToDecimal(std::string const& _s) diff --git a/libdevcore/Exceptions.h b/libdevcore/Exceptions.h index bbc928da4..5d03c195f 100644 --- a/libdevcore/Exceptions.h +++ b/libdevcore/Exceptions.h @@ -45,7 +45,7 @@ struct FileError: virtual Exception {}; typedef boost::error_info errinfo_invalidSymbol; typedef boost::error_info errinfo_wrongAddress; typedef boost::error_info errinfo_comment; -typedef boost::error_info errinfo_required; -typedef boost::error_info errinfo_got; +typedef boost::error_info errinfo_required; +typedef boost::error_info errinfo_got; typedef boost::tuple RequirementError; } diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index f8c526ac7..c3a8b2a80 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -71,7 +71,7 @@ bool Executive::setup(bytesConstRef _rlp) if (m_t.gas() < gasCost) { clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << gasCost << " Got" << m_t.gas(); - BOOST_THROW_EXCEPTION(OutOfGas()); + BOOST_THROW_EXCEPTION(OutOfGas() << RequirementError((bigint)gasCost, (bigint)m_t.gas())); } u256 cost = m_t.value() + m_t.gas() * m_t.gasPrice(); @@ -80,14 +80,14 @@ bool Executive::setup(bytesConstRef _rlp) if (m_s.balance(m_sender) < cost) { clog(StateDetail) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_sender); - BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((int)cost, (int)m_s.balance(m_sender))); + BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((bigint)cost, (bigint)m_s.balance(m_sender))); } u256 startGasUsed = m_s.gasUsed(); if (startGasUsed + m_t.gas() > m_s.m_currentBlock.gasLimit) { clog(StateDetail) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas(); - BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((int)(m_s.m_currentBlock.gasLimit - startGasUsed), (int)m_t.gas())); + BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(m_s.m_currentBlock.gasLimit - startGasUsed), (bigint)m_t.gas())); } // Increment associated nonce for sender. diff --git a/libevm/VM.h b/libevm/VM.h index 52149a9a1..487c8cd1a 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -71,7 +71,7 @@ public: template bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1); - void require(u256 _n) { if (m_stack.size() < _n) BOOST_THROW_EXCEPTION(StackTooSmall() << RequirementError(int(_n), m_stack.size())); } + void require(u256 _n) { if (m_stack.size() < _n) BOOST_THROW_EXCEPTION(StackTooSmall() << RequirementError((bigint)_n, (bigint)m_stack.size())); } void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } } u256 gas() const { return m_gas; } u256 curPC() const { return m_curPC; } diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h index 4f276b7e1..0824b0139 100644 --- a/libqethereum/QEthereum.h +++ b/libqethereum/QEthereum.h @@ -83,6 +83,7 @@ private: { \ _frame->disconnect(); \ _frame->addToJavaScriptWindowObject("_web3", qweb, QWebFrame::ScriptOwnership); \ + _frame->addToJavaScriptWindowObject("env", _env, QWebFrame::QtOwnership); \ _frame->evaluateJavaScript(contentsOfQResource(":/js/es6-promise-2.0.0.js")); \ _frame->evaluateJavaScript(contentsOfQResource(":/js/main.js")); \ _frame->evaluateJavaScript(contentsOfQResource(":/js/qt.js")); \ diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 73c938ce2..03c2a37ac 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -370,10 +370,10 @@ static TransactionSkeleton toTransaction(Json::Value const& _json) ret.data = jsToBytes(_json["code"].asString()); else if (_json["data"].isArray()) for (auto i: _json["data"]) - dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32))); + dev::operator +=(ret.data, padded(jsToBytes(i.asString()), 32)); else if (_json["code"].isArray()) for (auto i: _json["code"]) - dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32))); + dev::operator +=(ret.data, padded(jsToBytes(i.asString()), 32)); else if (_json["dataclose"].isArray()) for (auto i: _json["dataclose"]) dev::operator +=(ret.data, jsToBytes(i.asString())); diff --git a/stdserv.js b/stdserv.js index 375a8379f..fe681414e 100644 --- a/stdserv.js +++ b/stdserv.js @@ -1,69 +1,41 @@ -eth = web3.eth; -env = web3.env; - -var configSource = -"{"+ -" [[69]] (caller)"+ -" (returnlll {"+ -" (when (&& (= (calldatasize) 64) (= (caller) @@69))"+ -" (for {} (< @i (calldatasize)) [i](+ @i 64)"+ -" [[ (calldataload @i) ]] (calldataload (+ @i 32))"+ -" )"+ -" )"+ -" (return @@ $0)"+ -" })"+ -"}"; - -console.log('Creating Config...') -var config = eth.lll(configSource); -config = config.then(function (configCode) { console.log('Config code: ' + configCode); return eth.transact({ 'code': configCode }); }); -config.then(function(configAddress) { console.log('Config at address ' + configAddress); config = configAddress; return configAddress; }); - -// marek: TODO +var compile = function(name) { return web3.eth.lll(env.contents("../../dapp-bin/" + name + "/" + name + ".lll")); }; +var create = function(code) { return web3.eth.transact({ 'code': code }); }; +var send = function(from, val, to) { return web3.eth.transact({ 'from': from, 'value': val, 'to': to }); }; +var initService = function(name, index, dep) { return dep.then(function(){ var ret = compile(name).then(create); register(ret, index); return ret; }); }; + +var config = compile("config").then(create); +var register = function(address, index) { return web3.eth.transact({ 'to': config, 'gas': '10000', 'data': [index + '', address] }); }; +var nameReg = initService("namereg", 0, config); +var regName = function(account, name) { return web3.eth.transact({ 'from': account, 'to': nameReg, 'gas': '10000', 'data': [ web3.fromAscii('register'), web3.fromAscii(name) ] }); }; +var coins = initService("coins", 1, nameReg); +var coin = initService("coin", 2, coins); +var approve = function(account, approvedAddress) { web3.eth.transact({ 'from': account, 'to': coin, 'gas': '10000', 'data': [ web3.fromAscii('approve'), approvedAddress ] }); }; +var exchange = initService("exchange", 3, coin); +var offer = function(account, haveCoin, haveVal, wantCoin, wantVal) { web3.eth.transact({ 'from': account, 'to': exchange, 'gas': '10000', 'data': [web3.fromAscii('new'), haveCoin, haveVal, wantCoin, wantVal] }); }; + +config.then(function() { + web3.eth.accounts.then(function(accounts) + { + var funded = send(accounts[0], '100000000000000000000', accounts[1]); + funded.then(function(){ env.note("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); regName(accounts[1], 'Gav Would'); env.note("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); approve(accounts[1], exchange); }); + regName(accounts[0], 'Gav'); + approve(accounts[0], exchange).then(function(){ offer(accounts[0], coin, '5000', '0', '5000000000000000000'); }); + + // TODO: once we have a new implementation of DNSReg. + // env.note('Register gav.eth...') + // eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] }); + }); +}); + +// TODO /* - -var nameRegCode = eth.lll(" -{ - [[(address)]] 'NameReg - [['NameReg]] (address) - [[config]] 'Config - [['Config]] config - [[69]] (caller) - (returnlll { - (when (= $0 'register) { - (when @@ $32 (stop)) - (when @@(caller) [[@@(caller)]] 0) - [[$32]] (caller) - [[(caller)]] $32 - (stop) - }) - (when (&& (= $0 'unregister) @@(caller)) { - [[@@(caller)]] 0 - [[(caller)]] 0 - (stop) - }) - (when (&& (= $0 'kill) (= (caller) @@69)) (suicide (caller))) - (return @@ $0) - }) -} -"); -env.note('NameReg code: ' + nameRegCode) - -var nameReg; - -env.note('Create NameReg...') -eth.transact({ 'code': nameRegCode }, function(a) { nameReg = a; }); - -env.note('Register NameReg...') -eth.transact({ 'to': config, 'data': ['0', nameReg] }); - var nameRegJeff; env.note('Create NameRegJeff...') eth.transact({ 'code': nameRegCode }, function(a) { nameRegJeff = a; }); env.note('Register NameRegJeff...') -eth.transact({ 'to': config, 'data': ['4', nameReg] }); +eth.transact({ 'to': config, 'data': ['4', nameRegJeff] }); var dnsRegCode = '0x60006000546000600053602001546000600053604001546020604060206020600073661005d2720d855f1d9976f88bb10c1a3398c77f6103e8f17f7265676973746572000000000000000000000000000000000000000000000000600053606001600060200201547f446e735265670000000000000000000000000000000000000000000000000000600053606001600160200201546000600060006000604060606000600053604001536103e8f1327f6f776e65720000000000000000000000000000000000000000000000000000005761011663000000e46000396101166000f20060006000547f72656769737465720000000000000000000000000000000000000000000000006000602002350e0f630000006d596000600160200235560e0f630000006c59600032560e0f0f6300000057596000325657600260200235600160200235576001602002353257007f64657265676973746572000000000000000000000000000000000000000000006000602002350e0f63000000b95960016020023532560e0f63000000b959600032576000600160200235577f6b696c6c000000000000000000000000000000000000000000000000000000006000602002350e0f630000011559327f6f776e6572000000000000000000000000000000000000000000000000000000560e0f63000001155932ff00'; @@ -75,240 +47,6 @@ env.note('DnsReg at address ' + dnsReg) env.note('Register DnsReg...') eth.transact({ 'to': config, 'data': ['4', dnsReg] }); - -var coinRegCode = eth.lll(" -{ -(regname 'CoinReg) -(returnlll { - (def 'name $0) - (def 'denom $32) - (def 'address (caller)) - (when (|| (& 0xffffffffffffffffffffffffff name) @@name) (stop)) - (set 'n (+ @@0 1)) - [[0]] @n - [[@n]] name - [[name]] address - [[(sha3 name)]] denom -}) -} -"); - -var coinReg; -env.note('Create CoinReg...') -eth.transact({ 'code': coinRegCode }, function(a) { coinReg = a; }); - -env.note('Register CoinReg...') -eth.transact({ 'to': config, 'data': ['1', coinReg] }); - -var gavCoinCode = eth.lll(" -{ -[[ (caller) ]] 0x1000000 -[[ 0x69 ]] (caller) -[[ 0x42 ]] (number) - -(regname 'GavCoin) -(regcoin 'GAV 1000) - -(returnlll { - (when (&& (= $0 'kill) (= (caller) @@0x69)) (suicide (caller))) - (when (= $0 'balance) (return @@$32)) - (when (= $0 'approved) (return @@ (sha3pair (if (= (calldatasize) 64) (caller) $64) $32)) ) - - (when (= $0 'approve) { - [[(sha3pair (caller) $32)]] $32 - (stop) - }) - - (when (= $0 'send) { - (set 'fromVar (if (= (calldatasize) 96) - (caller) - { - (when (! @@ (sha3pair (origin) (caller))) (return 0)) - (origin) - } - )) - (def 'to $32) - (def 'value $64) - (def 'from (get 'fromVar)) - (set 'fromBal @@from) - (when (< @fromBal value) (return 0)) - [[ from ]]: (- @fromBal value) - [[ to ]]: (+ @@to value) - (return 1) - }) - - (set 'n @@0x42) - (when (&& (|| (= $0 'mine) (! (calldatasize))) (> (number) @n)) { - (set 'b (- (number) @n)) - [[(coinbase)]] (+ @@(coinbase) (* 1000 @b)) - [[(caller)]] (+ @@(caller) (* 1000 @b)) - [[0x42]] (number) - (return @b) - }) - - (return @@ $0) -}) -} -"); - -var gavCoin; -env.note('Create GavCoin...') -eth.transact({ 'code': gavCoinCode }, function(a) { gavCoin = a; }); - -env.note('Register GavCoin...') -eth.transact({ 'to': config, 'data': ['2', gavCoin] }); - - -var exchangeCode = eth.lll(" -{ -(regname 'Exchange) - -(def 'min (a b) (if (< a b) a b)) - -(def 'head (_list) @@ _list) -(def 'next (_item) @@ _item) -(def 'inc (itemref) [itemref]: (next @itemref)) -(def 'rateof (_item) @@ (+ _item 1)) -(def 'idof (_item) @@ (+ _item 2)) -(def 'wantof (_item) @@ (+ _item 3)) -(def 'newitem (rate who want list) { - (set 'pos (sha3trip rate who list)) - [[ (+ @pos 1) ]] rate - [[ (+ @pos 2) ]] who - [[ (+ @pos 3) ]] want - @pos -}) -(def 'stitchitem (parent pos) { - [[ pos ]] @@ parent - [[ parent ]] pos -}) -(def 'addwant (_item amount) [[ (+ _item 3) ]] (+ @@ (+ _item 3) amount)) -(def 'deductwant (_item amount) [[ (+ _item 3) ]] (- @@ (+ _item 3) amount)) - -(def 'xfer (contract to amount) - (if contract { - [0] 'send - [32] to - [64] amount - (msg allgas contract 0 0 96) - } - (send to amount) - ) -) - -(def 'fpdiv (a b) (/ (+ (/ b 2) (* a (exp 2 128))) b)) -(def 'fpmul (a b) (/ (* a b) (exp 2 128)) ) - -(returnlll { - (when (= $0 'new) { - (set 'offer $32) - (set 'xoffer (if @offer $64 (callvalue))) - (set 'want $96) - (set 'xwant $128) - (set 'rate (fpdiv @xoffer @xwant)) - (set 'irate (fpdiv @xwant @xoffer)) - - (unless (&& @rate @irate @xoffer @xwant) (stop)) - - (when @offer { - (set 'arg1 'send) - (set 'arg2 (address)) - (set 'arg3 @xoffer) - (set 'arg4 (caller)) - (unless (msg allgas @offer 0 arg1 128) (stop)) - }) - (set 'list (sha3pair @offer @want)) - (set 'ilist (sha3pair @want @offer)) - - (set 'last @ilist) - (set 'item @@ @last) - - (for {} (&& @item (>= (rateof @item) @irate)) {} { - (set 'offerA (min @xoffer (wantof @item))) - (set 'wantA (fpmul @offerA (rateof @item))) - - (set 'xoffer (- @xoffer @offerA)) - (set 'xwant (- @xwant @wantA)) - - (deductwant @item @offerA) - - (xfer @offer (idof @item) @offerA) - (xfer @want (caller) @wantA) - - (unless @xoffer (stop)) - - (set 'item @@ @item) - [[ @last ]] @item - }) - - (set 'last @list) - (set 'item @@ @last) - - (set 'newpos (newitem @rate (caller) @xwant @list)) - - (for {} (&& @item (!= @item @newpos) (>= (rateof @item) @rate)) { (set 'last @item) (inc item) } {}) - (if (= @item @newpos) - (addwant @item @wantx) - (stitchitem @last @newpos) - ) - (stop) - }) - (when (= $0 'delete) { - (set 'offer $32) - (set 'want $64) - (set 'rate $96) - (set 'list (sha3pair @offer @want)) - (set 'last @list) - (set 'item @@ @last) - (for {} (&& @item (!= (idof @item) (caller)) (!= (rateof @item) @rate)) { (set 'last @item) (inc item) } {}) - (when @item { - (set 'xoffer (fpmul (wantof @item) (rateof @item))) - [[ @last ]] @@ @item - (xfer @offer (caller) @xoffer) - }) - (stop) - }) - (when (= $0 'price) { - (set 'offer $32) - (set 'want $96) - (set 'item (head (sha3pair @offer @want))) - (return (if @item (rateof @list) 0)) - }) -}) -} -"); - -var exchange; -env.note('Create Exchange...') -eth.transact({ 'code': exchangeCode }, function(a) { exchange = a; }); - -env.note('Register Exchange...') -eth.transact({ 'to': config, 'data': ['3', exchange] }); - - - - -env.note('Register my name...') -eth.transact({ 'to': nameReg, 'data': [ web3.fromAscii('register'), web3.fromAscii('Gav') ] }); - -env.note('Dole out ETH to other address...') -eth.transact({ 'value': '100000000000000000000', 'to': eth.accounts[1] }); - -env.note('Register my other name...') -eth.transact({ 'from': eth.keys[1], 'to': nameReg, 'data': [ web3.fromAscii('register'), web3.fromAscii("Gav Would") ] }); - -env.note('Approve Exchange...') -eth.transact({ 'to': gavCoin, 'data': [ web3.fromAscii('approve'), exchange ] }); - -env.note('Approve Exchange on other address...') -eth.transact({ 'from': eth.keys[1], 'to': gavCoin, 'data': [ web3.fromAscii('approve'), exchange ] }); - -env.note('Make offer 5000GAV/5ETH...') -eth.transact({ 'to': exchange, 'data': [web3.fromAscii('new'), gavCoin, '5000', '0', '5000000000000000000'] }); - -env.note('Register gav.eth...') -eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] }); */ -env.note('All done.') // env.load('/home/gav/Eth/cpp-ethereum/stdserv.js') From d7972e726dccccdcecc826944dba49de731ef9b1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 21:26:39 +0100 Subject: [PATCH 24/27] Minor UI changes and reduction of verbosity. --- alethzero/MainWin.cpp | 2 +- libethereum/State.cpp | 4 ++-- libp2p/Host.cpp | 2 +- libweb3jsonrpc/WebThreeStubServer.cpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index dc5b326bc..280a70fe1 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -956,7 +956,7 @@ void Main::refreshBlockCount() cwatch << "refreshBlockCount()"; auto d = ethereum()->blockChain().details(); auto diff = BlockInfo(ethereum()->blockChain().block()).difficulty; - ui->blockCount->setText(QString("%6 #%1 @%3 T%2 N%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(dev::eth::c_protocolVersion).arg(dev::eth::c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet")); + ui->blockCount->setText(QString("%6 #%1 @%3 T%2 PV%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(dev::eth::c_protocolVersion).arg(dev::eth::c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet")); } static bool blockMatch(string const& _f, dev::eth::BlockDetails const& _b, h256 _h, BlockChain const& _bc) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index ee93fdc55..69faf983c 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -322,8 +322,8 @@ StateDiff State::diff(State const& _c) const for (auto i: _c.m_cache) ads.insert(i.first); - cnote << *this; - cnote << _c; +// cnote << *this; +// cnote << _c; for (auto i: ads) { diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index be9f2f7ae..996e219db 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -385,7 +385,7 @@ void Host::populateAddresses() shared_ptr Host::noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, bool _ready, NodeId _oldId) { RecursiveGuard l(x_peers); - if (_a.port() < 30300 || _a.port() > 30303) + if (_a.port() < 30300 || _a.port() > 30305) cwarn << "Weird port being recorded: " << _a.port(); if (_a.port() >= /*49152*/32768) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 03c2a37ac..5b362cde5 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -507,7 +507,7 @@ std::string WebThreeStubServer::shh_newGroup(std::string const& _id, std::string std::string WebThreeStubServer::shh_newIdentity() { - cnote << this << m_ids; +// cnote << this << m_ids; KeyPair kp = KeyPair::create(); m_ids[kp.pub()] = kp.secret(); return toJS(kp.pub()); @@ -535,7 +535,7 @@ int WebThreeStubServer::eth_peerCount() bool WebThreeStubServer::shh_post(Json::Value const& _json) { - cnote << this << m_ids; +// cnote << this << m_ids; shh::Message m = toMessage(_json); Secret from; From ecf4ede0308a3bb7cc8a970e638c16b4dafc5aef Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 22:00:41 +0100 Subject: [PATCH 25/27] Clean up Alex's Windows mess :-P --- windows/LibEthereum.vcxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 0578a8f16..06f868023 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -68,14 +68,14 @@ true + - + - @@ -568,4 +568,4 @@ - \ No newline at end of file + From 0f7e159df48eea17819fda72471d4c416ce132d8 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 22:35:14 +0100 Subject: [PATCH 26/27] Brain-dead MSVC strikes again. --- libdevcrypto/ECDHE.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp index dd72e8176..deae3bc6d 100644 --- a/libdevcrypto/ECDHE.cpp +++ b/libdevcrypto/ECDHE.cpp @@ -76,7 +76,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange) memcpy(&exchange[exchange.size() - sizeof(p)], p.data(), sizeof(p)); // protocol parameters; should be fixed size - bytes v({0x80}); + bytes v(1, 0x80); exchange.resize(exchange.size() + v.size()); memcpy(&exchange[exchange.size() - v.size()], v.data(), v.size()); From 6af670af27f74e9cb5c8566d1e5a226adbd7bfb6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 23:02:53 +0100 Subject: [PATCH 27/27] Windows build fix. --- test/crypto.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/crypto.cpp b/test/crypto.cpp index d8bd25035..08236135a 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) Secret secret(sha3(sbytes)); KeyPair key(secret); - bytes m({0xFF}); + bytes m(1, 0xff); int tests = 2; while (m[0]++, tests--) {