sveneh
10 years ago
61 changed files with 1581 additions and 1244 deletions
@ -1,40 +1,60 @@ |
|||
/*
|
|||
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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file SHA3MAC.cpp
|
|||
/** @file AES.cpp
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
* |
|||
* SHA3 MAC |
|||
*/ |
|||
|
|||
#include "CryptoPP.h" |
|||
#include "SHA3MAC.h" |
|||
#include "AES.h" |
|||
|
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::crypto; |
|||
using namespace dev::crypto::aes; |
|||
using namespace CryptoPP; |
|||
|
|||
void crypto::sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output) |
|||
struct aes::Aes128Ctr |
|||
{ |
|||
Aes128Ctr(h128 _k) |
|||
{ |
|||
mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); |
|||
} |
|||
CTR_Mode<AES>::Encryption mode; |
|||
}; |
|||
|
|||
Stream::Stream(StreamType, h128 _ckey): |
|||
m_cSecret(_ckey) |
|||
{ |
|||
cryptor = new Aes128Ctr(_ckey); |
|||
} |
|||
|
|||
Stream::~Stream() |
|||
{ |
|||
delete cryptor; |
|||
} |
|||
|
|||
void Stream::update(bytesRef) |
|||
{ |
|||
|
|||
} |
|||
|
|||
size_t Stream::streamOut(bytes&) |
|||
{ |
|||
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()); |
|||
return 0; |
|||
} |
|||
|
@ -0,0 +1,89 @@ |
|||
/*
|
|||
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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file AES.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
* |
|||
* AES |
|||
* todo: use openssl |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <atomic> |
|||
#include "Common.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace crypto |
|||
{ |
|||
namespace aes |
|||
{ |
|||
|
|||
struct Aes128Ctr; |
|||
enum StreamType { Encrypt, Decrypt }; |
|||
|
|||
/**
|
|||
* @brief Encrypted stream |
|||
*/ |
|||
class Stream |
|||
{ |
|||
public: |
|||
// streamtype maybe irrelevant w/ctr
|
|||
Stream(StreamType _t, h128 _ckey); |
|||
~Stream(); |
|||
|
|||
virtual void update(bytesRef io_bytes); |
|||
|
|||
/// Move ciphertext to _bytes.
|
|||
virtual size_t streamOut(bytes& o_bytes); |
|||
|
|||
private: |
|||
Stream(Stream const&) = delete; |
|||
Stream& operator=(Stream const&) = delete; |
|||
|
|||
h128 m_cSecret; |
|||
bytes m_text; |
|||
|
|||
Aes128Ctr* cryptor; |
|||
}; |
|||
|
|||
|
|||
/**
|
|||
* @brief Encrypted stream with inband SHA3 mac at specific interval. |
|||
*/ |
|||
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>((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; } |
|||
|
|||
private: |
|||
AuthenticatedStream(AuthenticatedStream const&) = delete; |
|||
AuthenticatedStream& operator=(AuthenticatedStream const&) = delete; |
|||
|
|||
std::atomic<unsigned> m_macInterval; |
|||
h128 m_macSecret; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
} |
@ -1,12 +1,8 @@ |
|||
#pragma once |
|||
|
|||
#include "Common.h" |
|||
#include "CryptoPP.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" |
|||
|
@ -1,200 +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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/**
|
|||
* @file EC.cpp |
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
* |
|||
* ECDSA, ECIES |
|||
*/ |
|||
|
|||
#include <secp256k1/secp256k1.h> |
|||
#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<ECP>::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<CryptoPP::ECP>::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<ECP,SHA3_256>::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<ECP, SHA3_256>::Verifier verifier; |
|||
initializeDLScheme(_p, verifier); |
|||
return verifier.VerifyMessage(_message.data(), _message.size(), _sig.data(), sizeof(Signature) - 1); |
|||
} |
|||
|
|||
Public crypto::recover(Signature _signature, bytesConstRef _message) |
|||
{ |
|||
secp256k1_start(); |
|||
|
|||
int pubkeylen = 65; |
|||
byte pubkey[pubkeylen]; |
|||
if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64])) |
|||
return Public(); |
|||
|
|||
#if ETH_CRYPTO_TRACE |
|||
h256* sig = (h256 const*)_signature.data(); |
|||
cout << "---- RECOVER -------------------------------" << endl; |
|||
cout << "MSG: " << _message << endl; |
|||
cout << "R S V: " << sig[0] << " " << sig[1] << " " << (int)(_signature[64] - 27) << "+27" << endl; |
|||
cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl; |
|||
#endif |
|||
|
|||
Public ret; |
|||
memcpy(&ret, &(pubkey[1]), sizeof(Public)); |
|||
return ret; |
|||
} |
|||
|
|||
bool crypto::verifySecret(Secret const& _s, Public const& _p) |
|||
{ |
|||
secp256k1_start(); |
|||
int ok = secp256k1_ecdsa_seckey_verify(_s.data()); |
|||
if (!ok) |
|||
return false; |
|||
|
|||
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; |
|||
} |
|||
|
@ -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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file EC.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @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); |
|||
|
|||
} |
|||
|
|||
} |
|||
|
@ -0,0 +1,100 @@ |
|||
/*
|
|||
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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file ECDHE.cpp
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "SHA3.h" |
|||
#include "CryptoPP.h" |
|||
#include "ECDHE.h" |
|||
|
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::crypto; |
|||
|
|||
static Secp256k1 s_secp256k1; |
|||
|
|||
void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret) |
|||
{ |
|||
if (m_remoteEphemeral) |
|||
// agreement can only occur once
|
|||
BOOST_THROW_EXCEPTION(InvalidState()); |
|||
|
|||
m_remoteEphemeral = _remote; |
|||
s_secp256k1.agree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret); |
|||
} |
|||
|
|||
void ECDHEKeyExchange::agree(Public const& _remoteEphemeral) |
|||
{ |
|||
s_secp256k1.agree(m_ephemeral.sec(), _remoteEphemeral, m_ephemeralSecret); |
|||
} |
|||
|
|||
void ECDHEKeyExchange::exchange(bytes& o_exchange) |
|||
{ |
|||
if (!m_ephemeralSecret) |
|||
// 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 sha3(m_ephemeralSecret)
|
|||
//
|
|||
// The second part is encrypted using the public key which relates to the prefix.
|
|||
|
|||
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,
|
|||
// 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 = toPublic(m_alias.m_secret); |
|||
exchange.resize(exchange.size() + sizeof(p)); |
|||
memcpy(&exchange[exchange.size() - sizeof(p)], p.data(), sizeof(p)); |
|||
|
|||
// protocol parameters; should be fixed size
|
|||
bytes v({0x80}); |
|||
exchange.resize(exchange.size() + 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[exchange.size() - sizeof(sig)], sig.data(), sizeof(sig)); |
|||
|
|||
aes::AuthenticatedStream aes(aes::Encrypt, m_ephemeralSecret, 0); |
|||
h256 prefix(sha3(m_known.second ? m_known.second : (h256)m_remoteEphemeral)); |
|||
aes.update(prefix.ref()); |
|||
|
|||
s_secp256k1.encrypt(encpk, exchange); |
|||
aes.update(&exchange); |
|||
|
|||
aes.streamOut(o_exchange); |
|||
} |
|||
|
|||
|
|||
|
@ -0,0 +1,109 @@ |
|||
/*
|
|||
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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file ECDHE.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
* |
|||
* Elliptic curve Diffie-Hellman ephemeral key exchange |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include "AES.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace crypto |
|||
{ |
|||
|
|||
/// Public key of remote and corresponding shared secret.
|
|||
typedef std::pair<Public,h256> AliasSession; |
|||
|
|||
/**
|
|||
* @brief An addressable EC key pair. |
|||
*/ |
|||
class Alias |
|||
{ |
|||
friend class ECDHEKeyExchange; // todo: remove
|
|||
public: |
|||
Alias(Secret _s): m_secret(_s) {}; |
|||
|
|||
AliasSession session(Address _a) { return m_sessions.count(_a) ? m_sessions.find(_a)->second : AliasSession(); } |
|||
|
|||
private: |
|||
std::map<Address,AliasSession> m_sessions; |
|||
Secret m_secret; |
|||
}; |
|||
|
|||
/**
|
|||
* @brief Derive DH shared secret from EC keypairs. |
|||
* As ephemeral keys are single-use, agreement is limited to a single occurence. |
|||
*/ |
|||
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(); } |
|||
|
|||
/// 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.
|
|||
}; |
|||
|
|||
/**
|
|||
* @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: private 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) {}; |
|||
|
|||
/// 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); |
|||
|
|||
/// 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: |
|||
Secret m_ephemeralSecret; |
|||
Alias m_alias; |
|||
AliasSession m_known; |
|||
Secret m_sharedAliasSecret; |
|||
|
|||
FixedHash<16> m_sharedC; |
|||
FixedHash<16> m_sharedM; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
@ -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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file SHA3MAC.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
* |
|||
* SHA3 MAC |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/FixedHash.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace crypto |
|||
{ |
|||
|
|||
void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output); |
|||
|
|||
} |
|||
} |
|||
|
@ -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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file CryptoHeaders.h
|
|||
* @author Tim Hughes <tim@twistedfury.com> |
|||
* @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 <sha.h> |
|||
#include <sha3.h> |
|||
#include <ripemd.h> |
|||
#include <secp256k1/secp256k1.h> |
|||
#pragma warning(pop) |
|||
#pragma GCC diagnostic pop |
@ -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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file TestHelperCrypto.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <libdevcrypto/CryptoPP.h> |
|||
|
|||
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); |
|||
} |
@ -0,0 +1,214 @@ |
|||
/*
|
|||
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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/**
|
|||
* @author Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2014 |
|||
* Unit tests for the solidity compiler JSON Interface output. |
|||
*/ |
|||
|
|||
#include <boost/test/unit_test.hpp> |
|||
#include <libsolidity/CompilerStack.h> |
|||
#include <jsonrpc/json/json.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace solidity |
|||
{ |
|||
namespace test |
|||
{ |
|||
|
|||
class InterfaceChecker |
|||
{ |
|||
public: |
|||
bool checkInterface(std::string const& _code, std::string const& _expectedInterfaceString) |
|||
{ |
|||
m_compilerStack.parse(_code); |
|||
std::string generatedInterfaceString = m_compilerStack.getInterface(); |
|||
Json::Value generatedInterface; |
|||
m_reader.parse(generatedInterfaceString, generatedInterface); |
|||
Json::Value expectedInterface; |
|||
m_reader.parse(_expectedInterfaceString, expectedInterface); |
|||
return expectedInterface == generatedInterface; |
|||
} |
|||
|
|||
private: |
|||
CompilerStack m_compilerStack; |
|||
Json::Reader m_reader; |
|||
}; |
|||
|
|||
BOOST_FIXTURE_TEST_SUITE(SolidityCompilerJSONInterfaceOutput, InterfaceChecker) |
|||
|
|||
BOOST_AUTO_TEST_CASE(basic_test) |
|||
{ |
|||
char const* sourceCode = "contract test {\n" |
|||
" function f(uint a) returns(uint d) { return a * 7; }\n" |
|||
"}\n"; |
|||
|
|||
char const* interface = R"([ |
|||
{ |
|||
"name": "f", |
|||
"inputs": [ |
|||
{ |
|||
"name": "a", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "d", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
} |
|||
])"; |
|||
|
|||
BOOST_CHECK(checkInterface(sourceCode, interface)); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE(empty_contract) |
|||
{ |
|||
char const* sourceCode = "contract test {\n" |
|||
"}\n"; |
|||
|
|||
char const* interface = "[]"; |
|||
|
|||
BOOST_CHECK(checkInterface(sourceCode, interface)); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE(multiple_methods) |
|||
{ |
|||
char const* sourceCode = "contract test {\n" |
|||
" function f(uint a) returns(uint d) { return a * 7; }\n" |
|||
" function g(uint b) returns(uint e) { return b * 8; }\n" |
|||
"}\n"; |
|||
|
|||
char const* interface = R"([ |
|||
{ |
|||
"name": "f", |
|||
"inputs": [ |
|||
{ |
|||
"name": "a", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "d", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"name": "g", |
|||
"inputs": [ |
|||
{ |
|||
"name": "b", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "e", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
} |
|||
])"; |
|||
|
|||
BOOST_CHECK(checkInterface(sourceCode, interface)); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE(multiple_params) |
|||
{ |
|||
char const* sourceCode = "contract test {\n" |
|||
" function f(uint a, uint b) returns(uint d) { return a + b; }\n" |
|||
"}\n"; |
|||
|
|||
char const* interface = R"([ |
|||
{ |
|||
"name": "f", |
|||
"inputs": [ |
|||
{ |
|||
"name": "a", |
|||
"type": "uint256" |
|||
}, |
|||
{ |
|||
"name": "b", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "d", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
} |
|||
])"; |
|||
|
|||
BOOST_CHECK(checkInterface(sourceCode, interface)); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE(multiple_methods_order) |
|||
{ |
|||
// methods are expected to be in alpabetical order
|
|||
char const* sourceCode = "contract test {\n" |
|||
" function f(uint a) returns(uint d) { return a * 7; }\n" |
|||
" function c(uint b) returns(uint e) { return b * 8; }\n" |
|||
"}\n"; |
|||
|
|||
char const* interface = R"([ |
|||
{ |
|||
"name": "c", |
|||
"inputs": [ |
|||
{ |
|||
"name": "b", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "e", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
"name": "f", |
|||
"inputs": [ |
|||
{ |
|||
"name": "a", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "d", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
} |
|||
])"; |
|||
|
|||
BOOST_CHECK(checkInterface(sourceCode, interface)); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_SUITE_END() |
|||
|
|||
} |
|||
} |
|||
} |
Loading…
Reference in new issue