aboutsummaryrefslogtreecommitdiffstats
path: root/crypto.cpp
diff options
context:
space:
mode:
authorartur-zawlocki <artur.zawlocki@gmail.com>2014-10-29 19:02:37 +0800
committerartur-zawlocki <artur.zawlocki@gmail.com>2014-10-29 19:02:37 +0800
commitec9330609fa965b8928a99fd8e9b1e10a7c45fa0 (patch)
tree4228317d344014175e85fcc3dde0966bf6c2f092 /crypto.cpp
parent621d7fa4b04a030b8f6c828d18c6976c600683f2 (diff)
parentf73a461e13b1d8f88e93b57c66933549bb855b8c (diff)
downloaddexon-solidity-ec9330609fa965b8928a99fd8e9b1e10a7c45fa0.tar.gz
dexon-solidity-ec9330609fa965b8928a99fd8e9b1e10a7c45fa0.tar.zst
dexon-solidity-ec9330609fa965b8928a99fd8e9b1e10a7c45fa0.zip
Merge branch 'develop-evmcc' of github.com:imapp-pl/ethereum into develop-evmcc
Conflicts: test/vm.cpp
Diffstat (limited to 'crypto.cpp')
-rw-r--r--crypto.cpp335
1 files changed, 239 insertions, 96 deletions
diff --git a/crypto.cpp b/crypto.cpp
index e71ee228..67286bfc 100644
--- a/crypto.cpp
+++ b/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...";
@@ -201,6 +341,7 @@ BOOST_AUTO_TEST_CASE(eth_keypairs)
{
eth::Transaction t;
t.nonce = 0;
+ t.type = eth::Transaction::MessageCall;
t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b"));
t.value = 1000;
auto rlp = t.rlp(false);
@@ -229,6 +370,7 @@ int cryptoTest()
{
eth::Transaction t;
t.nonce = 0;
+ t.type = eth::Transaction::MessageCall;
t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b"));
t.value = 1000;
auto rlp = t.rlp(false);
@@ -257,6 +399,7 @@ int cryptoTest()
Transaction t;
t.nonce = 0;
t.value = 1; // 1 wei.
+ t.type = eth::Transaction::MessageCall;
t.receiveAddress = toAddress(sha3("123"));
bytes sig64 = toBigEndian(t.vrs.r) + toBigEndian(t.vrs.s);