subtly
10 years ago
6 changed files with 294 additions and 2 deletions
@ -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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file AES.cpp
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file AES.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @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<unsigned> m_macInterval; |
|||
Secret128 m_macSecret; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
} |
@ -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 <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file ECDHE.cpp
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @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); |
|||
} |
|||
|
|||
|
|||
|
@ -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 <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" |
|||
#include "EC.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace crypto |
|||
{ |
|||
|
|||
typedef std::pair<Public,h256> 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<Address,AliasSession> 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; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
Loading…
Reference in new issue