Browse Source

aes, ecdh, ecdhe

cl-refactor
subtly 10 years ago
parent
commit
554681992d
  1. 23
      libdevcrypto/AES.cpp
  2. 78
      libdevcrypto/AES.h
  3. 10
      libdevcrypto/CryptoPP.cpp
  4. 4
      libdevcrypto/CryptoPP.h
  5. 79
      libdevcrypto/ECDHE.cpp
  6. 102
      libdevcrypto/ECDHE.h

23
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 <http://www.gnu.org/licenses/>.
*/
/** @file AES.cpp
* @author Alex Leverington <nessence@gmail.com>
* @date 2014
*/
#include "AES.h"

78
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 <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;
};
}
}
}

10
libdevcrypto/CryptoPP.cpp

@ -31,6 +31,7 @@ using namespace CryptoPP;
void pp::exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> 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<CryptoPP::ECP> pk;
pk.Initialize(secp256k1Params, secp256k1Params.ExponentiateBase(_e));
pp::exportPublicKey(pk, _p);
}
}
void pp::ecdhAgree(Secret _s, Public _r, h256& o_s)
{
ECDH<ECP>::Domain d(secp256k1Curve);
assert(d.AgreedValueLength() == sizeof(o_s));
d.Agree(o_s.data(), _s.data(), _r.data());
}

4
libdevcrypto/CryptoPP.h

@ -76,7 +76,9 @@ void exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k, Public&
static void exportPrivateKey(CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> 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 <class T>
void initializeDLScheme(Secret const& _s, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, secretToExponent(_s)); }

79
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 <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);
}

102
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 <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…
Cancel
Save