sveneh
10 years ago
61 changed files with 1581 additions and 1244 deletions
@ -1,40 +1,60 @@ |
|||||
/*
|
/*
|
||||
This file is part of cpp-ethereum. |
This file is part of cpp-ethereum. |
||||
|
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify |
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 |
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
(at your option) any later version. |
||||
|
|
||||
cpp-ethereum is distributed in the hope that it will be useful, |
cpp-ethereum is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
GNU General Public License for more details. |
||||
|
|
||||
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
*/ |
||||
/** @file SHA3MAC.cpp
|
/** @file AES.cpp
|
||||
* @author Alex Leverington <nessence@gmail.com> |
* @author Alex Leverington <nessence@gmail.com> |
||||
* @date 2014 |
* @date 2014 |
||||
* |
|
||||
* SHA3 MAC |
|
||||
*/ |
*/ |
||||
|
|
||||
#include "CryptoPP.h" |
#include "CryptoPP.h" |
||||
#include "SHA3MAC.h" |
#include "AES.h" |
||||
|
|
||||
|
using namespace std; |
||||
using namespace dev; |
using namespace dev; |
||||
using namespace dev::crypto; |
using namespace dev::crypto; |
||||
|
using namespace dev::crypto::aes; |
||||
using namespace CryptoPP; |
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; |
return 0; |
||||
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()); |
|
||||
} |
} |
||||
|
|
@ -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 |
#pragma once |
||||
|
|
||||
#include "Common.h" |
#include "Common.h" |
||||
#include "CryptoPP.h" |
#include "AES.h" |
||||
#include "EC.h" |
#include "ECDHE.h" |
||||
#include "FileSystem.h" |
#include "FileSystem.h" |
||||
#include "MemoryDB.h" |
|
||||
#include "OverlayDB.h" |
|
||||
#include "SHA3.h" |
#include "SHA3.h" |
||||
#include "SHA3MAC.h" |
|
||||
#include "TrieCommon.h" |
|
||||
#include "TrieDB.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