Browse Source

Merge pull request #413 from ethereum/crypto

Crypto: encrypt/decrypt, move cryptopp to implementation, tests.
cl-refactor
Gav Wood 10 years ago
parent
commit
1e585233da
  1. 4
      CodingStandards.txt
  2. 17
      libdevcrypto/Common.cpp
  3. 9
      libdevcrypto/Common.h
  4. 43
      libdevcrypto/CryptoHeaders.h
  5. 74
      libdevcrypto/CryptoPP.cpp
  6. 85
      libdevcrypto/CryptoPP.h
  7. 73
      libdevcrypto/EC.cpp
  8. 41
      libdevcrypto/EC.h
  9. 2
      libdevcrypto/SHA3.cpp
  10. 39
      libdevcrypto/SHA3MAC.cpp
  11. 38
      libdevcrypto/SHA3MAC.h
  12. 2
      libethcore/ProofOfWork.cpp
  13. 18
      test/TestHelperCrypto.h
  14. 332
      test/crypto.cpp

4
CodingStandards.txt

@ -72,8 +72,8 @@ All other entities' first alpha is lower case.
4. Variable prefixes:
a. Leading underscore "_" to parameter names (both normal and template).
- Exception: "o_parameterName" when it is used exclusively for output. See 7(f).
- Exception: "io_parameterName" when it is used for both input and output. See 7(f).
- Exception: "o_parameterName" when it is used exclusively for output. See 6(f).
- Exception: "io_parameterName" when it is used for both input and output. See 6(f).
b. Leading "c_" to const variables (unless part of an external API).
c. Leading "g_" to global (non-const) variables.
d. Leading "s_" to static (non-const, non-global) variables.

17
libdevcrypto/Common.cpp

@ -22,6 +22,7 @@
#include "Common.h"
#include <random>
#include <secp256k1/secp256k1.h>
#include "EC.h"
#include "SHA3.h"
using namespace std;
using namespace dev;
@ -108,16 +109,20 @@ KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _pass
return KeyPair(sha3(aesDecrypt(_seed, _password)));
}
void dev::encrypt(Public _k, bytesConstRef _plain, bytes& _cipher)
void dev::encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher)
{
(void)_k;
_cipher = _plain.toBytes();
bytes io = _plain.toBytes();
crypto::encrypt(_k, io);
o_cipher = std::move(io);
}
bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& _plain)
bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext)
{
(void)_k;
_plain = _cipher.toBytes();
bytes io = _cipher.toBytes();
crypto::decrypt(_k, io);
if (io.empty())
return false;
o_plaintext = std::move(io);
return true;
}

9
libdevcrypto/Common.h

@ -57,9 +57,16 @@ using Secrets = h256s;
/// @returns 0 if it's not a valid secret key.
Address toAddress(Secret _secret);
/// Encrypts plain text using Public key.
void encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher);
bool decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plain);
/// Decrypts cipher using Secret key.
bool decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext);
/// Recovers Public key from signed message.
Public recover(Signature _sig, h256 _message);
/// Returns siganture of message hash.
Signature sign(Secret _k, h256 _message);
/// Simple class that represents a "key pair".

43
libdevcrypto/CryptoHeaders.h

@ -1,43 +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"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
#pragma GCC diagnostic ignored "-Wextra"
#include <sha.h>
#include <sha3.h>
#include <ripemd.h>
#include <aes.h>
#include <pwdbased.h>
#include <modes.h>
#include <filters.h>
#include <secp256k1/secp256k1.h>
#pragma warning(pop)
#pragma GCC diagnostic pop

74
libdevcrypto/CryptoPP.cpp

@ -0,0 +1,74 @@
/*
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 CryptoPP.cpp
* @author Alex Leverington <nessence@gmail.com>
* @date 2014
*/
#include "CryptoPP.h"
using namespace dev;
using namespace dev::crypto;
using namespace CryptoPP;
ECP::Point pp::PointFromPublic(Public const& _p)
{
ECP::Point p;
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pub;
pub.AccessGroupParameters().Initialize(pp::secp256k1());
bytes prefixedKey(pub.GetGroupParameters().GetEncodedElementSize(true));
prefixedKey[0] = 0x04;
assert(Public::size == prefixedKey.size() - 1);
memcpy(&prefixedKey[1], _p.data(), prefixedKey.size() - 1);
pub.GetGroupParameters().GetCurve().DecodePoint(p, prefixedKey.data(), prefixedKey.size());
return std::move(p);
}
Integer pp::ExponentFromSecret(Secret const& _s)
{
static_assert(Secret::size == 32, "Secret key must be 32 bytes.");
return std::move(Integer(_s.data(), Secret::size));
}
void pp::PublicFromExponent(Integer const& _e, Public& _p)
{
CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> k;
k.AccessGroupParameters().Initialize(secp256k1());
k.SetPrivateExponent(_e);
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> p;
p.AccessGroupParameters().Initialize(secp256k1());
k.MakePublicKey(p);
pp::PublicFromDL_PublicKey_EC(p, _p);
}
void pp::PublicFromDL_PublicKey_EC(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k, Public& _p)
{
bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
_k.GetGroupParameters().GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
static_assert(Public::size == 64, "Public key must be 64 bytes.");
assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
memcpy(_p.data(), &prefixedKey[1], Public::size);
}
void pp::SecretFromDL_PrivateKey_EC(CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> const& _k, Secret& _s)
{
_k.GetPrivateExponent().Encode(_s.data(), Secret::size);
}

85
libdevcrypto/CryptoPP.h

@ -0,0 +1,85 @@
/*
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 CryptoPP.h
* @author Alex Leverington <nessence@gmail.com>
* @date 2014
*
* CryptoPP headers and helper methods
*/
#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 "-Wunused-function"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
#pragma GCC diagnostic ignored "-Wextra"
#include <sha.h>
#include <sha3.h>
#include <ripemd.h>
#include <aes.h>
#include <pwdbased.h>
#include <modes.h>
#include <filters.h>
#include <eccrypto.h>
#include <ecp.h>
#include <files.h>
#include <osrng.h>
#include <oids.h>
#include <secp256k1/secp256k1.h>
#pragma warning(pop)
#pragma GCC diagnostic pop
#include "Common.h"
namespace dev
{
namespace crypto
{
namespace pp
{
/// RNG used by CryptoPP
inline CryptoPP::AutoSeededRandomPool& PRNG() { static CryptoPP::AutoSeededRandomPool prng; return prng; }
/// EC curve used by CryptoPP
inline CryptoPP::OID const& secp256k1() { static CryptoPP::OID curve = CryptoPP::ASN1::secp256k1(); return curve; }
/// Conversion from bytes to cryptopp point
CryptoPP::ECP::Point PointFromPublic(Public const& _p);
/// Conversion from bytes to cryptopp exponent
CryptoPP::Integer ExponentFromSecret(Secret const& _s);
/// Conversion from cryptopp exponent Integer to bytes
void PublicFromExponent(CryptoPP::Integer const& _k, Public& _s);
/// Conversion from cryptopp public key to bytes
void PublicFromDL_PublicKey_EC(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k, Public& _p);
/// Conversion from cryptopp private key to bytes
void SecretFromDL_PrivateKey_EC(CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> const& _k, Secret& _s);
}
}
}

73
libdevcrypto/EC.cpp

@ -0,0 +1,73 @@
/*
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
*
* Shared EC classes and functions.
*/
#pragma warning(push)
#pragma warning(disable:4100 4244)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
#pragma GCC diagnostic ignored "-Wextra"
#include <files.h>
#pragma warning(pop)
#pragma GCC diagnostic pop
#include "CryptoPP.h"
#include "SHA3.h"
#include "EC.h"
// CryptoPP and dev conflict so dev and pp namespace are used explicitly
using namespace std;
using namespace dev;
using namespace dev::crypto;
using namespace CryptoPP;
void dev::crypto::encrypt(Public const& _key, bytes& io_cipher)
{
ECIES<ECP>::Encryptor e;
e.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1());
e.AccessKey().SetPublicElement(pp::PointFromPublic(_key));
size_t plen = io_cipher.size();
bytes c;
c.resize(e.CiphertextLength(plen));
// todo: use StringSource with _plain as input and output.
e.Encrypt(pp::PRNG(), io_cipher.data(), plen, c.data());
bzero(io_cipher.data(), io_cipher.size());
io_cipher = std::move(c);
}
void dev::crypto::decrypt(Secret const& _k, bytes& io_text)
{
CryptoPP::ECIES<CryptoPP::ECP>::Decryptor d;
d.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1());
d.AccessKey().SetPrivateExponent(pp::ExponentFromSecret(_k));
size_t clen = io_text.size();
bytes p;
p.resize(d.MaxPlaintextLength(io_text.size()));
// todo: use StringSource with _c as input and output.
DecodingResult r = d.Decrypt(pp::PRNG(), io_text.data(), clen, p.data());
assert(r.messageLength);
io_text.resize(r.messageLength);
io_text = std::move(p);
}

41
libdevcrypto/EC.h

@ -0,0 +1,41 @@
/*
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
*
* Shared EC classes and functions.
*/
#pragma once
#include "Common.h"
namespace dev
{
namespace crypto
{
/// Encrypts text (in place).
void encrypt(Public const& _k, bytes& io_cipher);
/// Decrypts text (in place).
void decrypt(Secret const& _k, bytes& io_text);
}
}

2
libdevcrypto/SHA3.cpp

@ -20,7 +20,7 @@
*/
#include "SHA3.h"
#include "CryptoHeaders.h"
#include "CryptoPP.h"
using namespace std;
using namespace dev;

39
libdevcrypto/SHA3MAC.cpp

@ -0,0 +1,39 @@
/*
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
* @author Alex Leverington <nessence@gmail.com>
* @date 2014
*
* SHA3 MAC
*/
#include "CryptoPP.h"
#include "SHA3MAC.h"
using namespace dev;
using namespace dev::crypto;
using namespace CryptoPP;
void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output)
{
CryptoPP::SHA3_256 ctx;
ctx.Update((byte*)_secret.data(), _secret.size());
ctx.Update((byte*)_plain.data(), _plain.size());
assert(_output.size() >= 32);
ctx.Final(_output.data());
}

38
libdevcrypto/SHA3MAC.h

@ -0,0 +1,38 @@
/*
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);
}
}

2
libethcore/ProofOfWork.cpp

@ -26,7 +26,7 @@
#include <array>
#include <random>
#include <thread>
#include <libethcore/CryptoHeaders.h>
#include <libdevcrypto/CryptoPP.h>
#include <libdevcore/Common.h>
#include "ProofOfWork.h"
using namespace std;

18
test/TestHelperCrypto.h

@ -21,23 +21,7 @@
#pragma once
//#include <ostream>
#pragma warning(push)
#pragma warning(disable:4100 4244)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
#pragma GCC diagnostic ignored "-Wextra"
#include <eccrypto.h>
#include <ecp.h>
#include <files.h>
#include <osrng.h>
#include <oids.h>
#pragma warning(pop)
#pragma GCC diagnostic pop
#include <libdevcrypto/CryptoPP.h>
using namespace std;
using namespace CryptoPP;

332
test/crypto.cpp

@ -27,37 +27,163 @@
#include <libdevcore/Log.h>
#include <libethereum/Transaction.h>
#include <boost/test/unit_test.hpp>
#include <libdevcrypto/EC.h>
#include "TestHelperCrypto.h"
using namespace std;
using namespace dev;
using namespace dev::crypto;
using namespace CryptoPP;
namespace dev
{
namespace crypto
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.");
bytes m = asBytes(message);
bytesConstRef bcr(&m);
KeyPair k = KeyPair::create();
bytes cipher;
encrypt(k.pub(), bcr, cipher);
assert(cipher != asBytes(message) && cipher.size() > 0);
bytes plain;
decrypt(k.sec(), bytesConstRef(&cipher), plain);
assert(asString(plain) == message);
assert(plain == asBytes(message));
}
inline CryptoPP::AutoSeededRandomPool& PRNG() {
static CryptoPP::AutoSeededRandomPool prng;
return prng;
BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1)
{
ECIES<ECP>::Decryptor d(pp::PRNG(), pp::secp256k1());
ECIES<ECP>::Encryptor e(d.GetKey());
Secret s;
pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s);
Public p;
pp::PublicFromDL_PublicKey_EC(e.GetKey(), p);
assert(dev::toAddress(s) == right160(dev::sha3(p.ref())));
Secret previous = s;
for (auto i = 0; i < 30; i++)
{
ECIES<ECP>::Decryptor d(pp::PRNG(), pp::secp256k1());
ECIES<ECP>::Encryptor e(d.GetKey());
Secret s;
pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s);
assert(s != previous);
Public p;
pp::PublicFromDL_PublicKey_EC(e.GetKey(), p);
assert(dev::toAddress(s) == right160(dev::sha3(p.ref())));
}
}
BOOST_AUTO_TEST_CASE(cryptopp_keys_cryptor_sipaseckp256k1)
{
KeyPair k = KeyPair::create();
Secret s = k.sec();
// Convert secret to exponent used by pp
Integer e = pp::ExponentFromSecret(s);
// Test that exported DL_EC private is same as exponent from Secret
CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> privatek;
privatek.AccessGroupParameters().Initialize(pp::secp256k1());
privatek.SetPrivateExponent(e);
assert(e == privatek.GetPrivateExponent());
// Test that exported secret is same as decryptor(privatek) secret
ECIES<ECP>::Decryptor d;
d.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1());
d.AccessKey().SetPrivateExponent(e);
assert(d.AccessKey().GetPrivateExponent() == e);
// Test that decryptor->encryptor->public == private->makepublic->public
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pubk;
pubk.AccessGroupParameters().Initialize(pp::secp256k1());
privatek.MakePublicKey(pubk);
ECIES<ECP>::Encryptor enc(d);
assert(pubk.GetPublicElement() == enc.AccessKey().GetPublicElement());
// Test against sipa/seckp256k1
Public p;
pp::PublicFromExponent(pp::ExponentFromSecret(s), p);
assert(toAddress(s) == dev::right160(dev::sha3(p.ref())));
assert(k.pub() == p);
}
BOOST_AUTO_TEST_CASE(cryptopp_public_export_import)
{
ECIES<ECP>::Decryptor d(pp::PRNG(), pp::secp256k1());
ECIES<ECP>::Encryptor e(d.GetKey());
Secret s;
pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s);
Public p;
pp::PublicFromDL_PublicKey_EC(e.GetKey(), p);
Address addr = right160(dev::sha3(p.ref()));
assert(toAddress(s) == addr);
KeyPair l(s);
assert(l.address() == addr);
DL_PublicKey_EC<ECP> pub;
pub.Initialize(pp::secp256k1(), pp::PointFromPublic(p));
assert(pub.GetPublicElement() == e.GetKey().GetPublicElement());
KeyPair k = KeyPair::create();
Public p2;
pp::PublicFromExponent(pp::ExponentFromSecret(k.sec()), p2);
assert(k.pub() == p2);
Address a = k.address();
Address a2 = toAddress(k.sec());
assert(a2 == a);
}
using namespace CryptoPP;
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 original = message;
bytes b = asBytes(message);
encrypt(k.pub(), b);
assert(b != asBytes(original));
BOOST_AUTO_TEST_SUITE(crypto)
decrypt(k.sec(), b);
assert(b == asBytes(original));
}
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_AUTO_TEST_CASE(cryptopp_ecies_message)
{
cnote << "Testing cryptopp_ecies_message...";
string const message("Now is the time for all good men to come to the aide of humanity.");
string const message("Now is the time for all good persons to come to the aide of humanity.");
AutoSeededRandomPool prng;
ECIES<ECP>::Decryptor localDecryptor(prng, ASN1::secp256r1());
ECIES<ECP>::Decryptor localDecryptor(pp::PRNG(), pp::secp256k1());
SavePrivateKey(localDecryptor.GetPrivateKey());
ECIES<ECP>::Encryptor localEncryptor(localDecryptor);
@ -65,31 +191,31 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message)
ECIES<ECP>::Decryptor futureDecryptor;
LoadPrivateKey(futureDecryptor.AccessPrivateKey());
futureDecryptor.GetPrivateKey().ThrowIfInvalid(prng, 3);
futureDecryptor.GetPrivateKey().ThrowIfInvalid(pp::PRNG(), 3);
ECIES<ECP>::Encryptor futureEncryptor;
LoadPublicKey(futureEncryptor.AccessPublicKey());
futureEncryptor.GetPublicKey().ThrowIfInvalid(prng, 3);
futureEncryptor.GetPublicKey().ThrowIfInvalid(pp::PRNG(), 3);
// encrypt/decrypt with local
string cipherLocal;
StringSource ss1 (message, true, new PK_EncryptorFilter(prng, localEncryptor, new StringSink(cipherLocal) ) );
StringSource ss1 (message, true, new PK_EncryptorFilter(pp::PRNG(), localEncryptor, new StringSink(cipherLocal) ) );
string plainLocal;
StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(prng, localDecryptor, new StringSink(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(prng, futureEncryptor, new StringSink(cipherFuture) ) );
StringSource ss3 (message, true, new PK_EncryptorFilter(pp::PRNG(), futureEncryptor, new StringSink(cipherFuture) ) );
string plainFuture;
StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(prng, futureDecryptor, new StringSink(plainFuture) ) );
StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG(), futureDecryptor, new StringSink(plainFuture) ) );
// decrypt local w/future
string plainFutureFromLocal;
StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(prng, futureDecryptor, new StringSink(plainFutureFromLocal) ) );
StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG(), futureDecryptor, new StringSink(plainFutureFromLocal) ) );
// decrypt future w/local
string plainLocalFromFuture;
StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(prng, localDecryptor, new StringSink(plainLocalFromFuture) ) );
StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG(), localDecryptor, new StringSink(plainLocalFromFuture) ) );
assert(plainLocal == message);
@ -98,98 +224,112 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message)
assert(plainLocalFromFuture == plainLocal);
}
BOOST_AUTO_TEST_CASE(cryptopp_ecdh_prime)
BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr)
{
cnote << "Testing cryptopp_ecdh_prime...";
const int aesKeyLen = 16;
assert(sizeof(char) == sizeof(byte));
using namespace CryptoPP;
OID curve = ASN1::secp256r1();
ECDH<ECP>::Domain dhLocal(curve);
SecByteBlock privLocal(dhLocal.PrivateKeyLength());
SecByteBlock pubLocal(dhLocal.PublicKeyLength());
dhLocal.GenerateKeyPair(dev::crypto::PRNG(), privLocal, pubLocal);
// generate test key
AutoSeededRandomPool rng;
SecByteBlock key(0x00, aesKeyLen);
rng.GenerateBlock(key, key.size());
ECDH<ECP>::Domain dhRemote(curve);
SecByteBlock privRemote(dhRemote.PrivateKeyLength());
SecByteBlock pubRemote(dhRemote.PublicKeyLength());
dhRemote.GenerateKeyPair(dev::crypto::PRNG(), privRemote, pubRemote);
// cryptopp uses IV as nonce/counter which is same as using nonce w/0 ctr
byte ctr[AES::BLOCKSIZE];
rng.GenerateBlock(ctr, sizeof(ctr));
assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength());
string text = "Now is the time for all good persons to come to the aide of humanity.";
// c++11 ftw
unsigned char const* in = (unsigned char*)&text[0];
unsigned char* out = (unsigned char*)&text[0];
string original = text;
// local: send public to remote; remote: send public to local
string cipherCopy;
try
{
CTR_Mode<AES>::Encryption e;
e.SetKeyWithIV(key, key.size(), ctr);
e.ProcessData(out, in, text.size());
assert(text != original);
cipherCopy = text;
}
catch(CryptoPP::Exception& e)
{
cerr << e.what() << endl;
}
// Local
SecByteBlock sharedLocal(dhLocal.AgreedValueLength());
assert(dhLocal.Agree(sharedLocal, privLocal, pubRemote));
try
{
CTR_Mode< AES >::Decryption d;
d.SetKeyWithIV(key, key.size(), ctr);
d.ProcessData(out, in, text.size());
assert(text == original);
}
catch(CryptoPP::Exception& e)
{
cerr << e.what() << endl;
}
// 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());
// reencrypt ciphertext...
try
{
assert(cipherCopy != text);
in = (unsigned char*)&cipherCopy[0];
out = (unsigned char*)&cipherCopy[0];
CTR_Mode<AES>::Encryption e;
e.SetKeyWithIV(key, key.size(), ctr);
e.ProcessData(out, in, text.size());
// yep, ctr mode.
assert(cipherCopy == original);
}
catch(CryptoPP::Exception& e)
{
cerr << e.what() << endl;
}
assert(ssLocal != 0);
assert(ssLocal == ssRemote);
}
BOOST_AUTO_TEST_CASE(cryptopp_ecdh_aes128_cbc_noauth)
BOOST_AUTO_TEST_CASE(cryptopp_aes128_cbc)
{
// ECDH gives 256-bit shared while aes uses 128-bits
// Use first 128-bits of shared secret as symmetric key
// IV is 0
// New connections require new ECDH keypairs
const int aesKeyLen = 16;
assert(sizeof(char) == sizeof(byte));
AutoSeededRandomPool rng;
SecByteBlock key(0x00, aesKeyLen);
rng.GenerateBlock(key, key.size());
}
// Generate random IV
byte iv[AES::BLOCKSIZE];
rng.GenerateBlock(iv, AES::BLOCKSIZE);
BOOST_AUTO_TEST_CASE(cryptopp_eth_fbba)
{
// Initial Authentication:
//
// New/Known Peer:
// pubkeyL = knownR? ? myKnown : myECDH
// pubkeyR = knownR? ? theirKnown : theirECDH
//
// Initial message = hmac(k=sha3(shared-secret[128..255]), address(pubkeyL)) || ECIES encrypt(pubkeyR, pubkeyL)
//
// Key Exchange (this could occur after handshake messages):
// If peers do not know each other they will need to exchange public keys.
//
// Drop ECDH (this could occur after handshake messages):
// After authentication and/or key exchange, both sides generate shared key
// from their 'known' keys and use this to encrypt all future messages.
//
// v2: If one side doesn't trust the other then a single-use key maybe sent.
// This will need to be tracked for future connections; when non-trusting peer
// wants to trust the other, it can request that it's old, 'new', public key be
// accepted. And, if the peer *really* doesn't trust the other side, it can request
// that a new, 'new', public key be accepted.
//
// Handshake (all or nothing, padded):
// All Peers (except blacklisted):
//
//
// New Peer:
//
//
// Known Untrusted Peer:
//
//
// Known Trusted Peer:
//
//
// Blacklisted Peeer:
// Already dropped by now.
//
//
// MAC:
// ...
}
string string128("AAAAAAAAAAAAAAAA");
string plainOriginal = string128;
CryptoPP::CBC_Mode<Rijndael>::Encryption cbcEncryption(key, key.size(), iv);
cbcEncryption.ProcessData((byte*)&string128[0], (byte*)&string128[0], string128.size());
assert(string128 != plainOriginal);
CBC_Mode<Rijndael>::Decryption cbcDecryption(key, key.size(), iv);
cbcDecryption.ProcessData((byte*)&string128[0], (byte*)&string128[0], string128.size());
assert(plainOriginal == string128);
// plaintext whose size isn't divisible by block size must use stream filter for padding
string string192("AAAAAAAAAAAAAAAABBBBBBBB");
plainOriginal = string192;
string cipher;
StreamTransformationFilter* aesStream = new StreamTransformationFilter(cbcEncryption, new StringSink(cipher));
StringSource source(string192, true, aesStream);
assert(cipher.size() == 32);
cbcDecryption.ProcessData((byte*)&cipher[0], (byte*)&string192[0], cipher.size());
assert(string192 == plainOriginal);
}
BOOST_AUTO_TEST_CASE(eth_keypairs)
{
cnote << "Testing Crypto...";

Loading…
Cancel
Save