Browse Source

abstract cryptopp. add/test encrypt/decrypt for key.

cl-refactor
subtly 10 years ago
parent
commit
066aa26f71
  1. 63
      libdevcrypto/EC.cpp
  2. 76
      libdevcrypto/EC.h
  3. 53
      libdevcrypto/ECIES.cpp
  4. 62
      test/crypto.cpp

63
libdevcrypto/EC.cpp

@ -32,19 +32,74 @@
#include <files.h>
#pragma warning(pop)
#pragma GCC diagnostic pop
#include "SHA3.h"
#include "EC.h"
// CryptoPP and dev conflict so dev and pp namespace are used explicitly
using namespace std;
using namespace dev::crypto;
using namespace CryptoPP;
dev::Public pp::exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k) {
Public p;
ECP::Point q(_k.GetPublicElement());
q.x.Encode(&p.data()[0], 32);
q.y.Encode(&p.data()[32], 32);
return p;
}
pp::ECKeyPair::ECKeyPair():
m_decryptor(pp::PRNG(), pp::secp256k1())
{
}
ECKeyPair ECKeyPair::create()
{
ECKeyPair k;
ECIES<ECP>::Decryptor d(PRNG(), secp256k1());
k.m_sec = d.GetKey();
ECIES<ECP>::Encryptor e(d);
k.m_pub = e.GetKey();
// export public key and set address
ECIES<ECP>::Encryptor e(k.m_decryptor.GetKey());
k.m_public = pp::exportPublicKey(e.GetKey());
k.m_address = dev::right160(dev::sha3(k.m_public.ref()));
return k;
}
void ECKeyPair::encrypt(bytes& _text)
{
ECIES<ECP>::Encryptor e(m_decryptor);
std::string c;
StringSource ss(_text.data(), _text.size(), true, new PK_EncryptorFilter(pp::PRNG(), e, new StringSink(c)));
bzero(_text.data(), _text.size() * sizeof(byte));
_text = std::move(asBytes(c));
}
void ECKeyPair::encrypt(bytes& _plain, Public _key)
{
const char* xbytes = (char*)&_key[0];
Integer x(xbytes);
const char* ybytes = (char*)&_key[32];
Integer y(ybytes);
DL_PublicKey_EC<ECP> p;
p.Initialize(pp::secp256k1(), ECP::Point(x,y));
ECIES<ECP>::Encryptor e(p);
// todo: determine size and use _plain as input and output.
std::string c;
StringSource ss(_plain.data(), _plain.size(), true, new PK_EncryptorFilter(pp::PRNG(), e, new StringSink(c)));
bzero(_plain.data(), _plain.size() * sizeof(byte));
_plain = std::move(asBytes(c));
}
dev::bytes ECKeyPair::decrypt(bytesConstRef _c)
{
std::string p;
StringSource ss(_c.data(), _c.size(), true, new PK_DecryptorFilter(pp::PRNG(), m_decryptor, new StringSink(p)));
return std::move(asBytes(p));
}

76
libdevcrypto/EC.h

@ -31,32 +31,84 @@ namespace dev
namespace crypto
{
using PublicTrustNonce = h256;
typedef std::pair<PublicTrustNonce,Public> PublicTrust;
namespace pp
// cryptopp wrappers
{
/// RNG used by CryptoPP
inline CryptoPP::AutoSeededRandomPool& PRNG() { static CryptoPP::AutoSeededRandomPool prng; return prng; }
inline CryptoPP::OID secp256k1() { return CryptoPP::ASN1::secp256k1(); }
/// EC curve used by CryptoPP
inline CryptoPP::OID const& secp256k1() { static CryptoPP::OID curve = CryptoPP::ASN1::secp256k1(); return curve; }
Public exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k);
/**
* @brief CryptoPP-specific EC keypair
*/
class ECKeyPair
{
public:
/// Create a new, randomly generated keypair.
Address const& address() const { return m_address; }
Public const& publicKey() const { return m_public; }
protected:
ECKeyPair();
CryptoPP::ECIES<CryptoPP::ECP>::Decryptor m_decryptor;
Address m_address;
Public m_public;
};
}
/// ECDSA Signature
using Signature = FixedHash<65>;
/// Secret nonce from trusted key exchange.
using Nonce = h256;
/// Public key with nonce corresponding to trusted key exchange.
typedef std::pair<Nonce,Public> PublicTrust;
/**
* @brief EC KeyPair
* @todo remove secret access
* @todo Integrate and/or replace KeyPair, move to common.h
*/
class ECKeyPair: public pp::ECKeyPair
{
friend class ECDHETKeyExchange;
friend class ECIESEncryptor;
friend class ECIESDecryptor;
public:
static ECKeyPair create();
/// deprecate
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pub() { return m_pub; }
/// deprecate
CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> sec() { return m_sec; }
/// Replaces text with ciphertext.
static void encrypt(bytes& _text, Public _key);
/// @returns ciphertext.
static bytes encrypt(bytesConstRef _text, Public _key);
/// Recover public key from signature.
static Public recover(Signature _sig, h256 _messageHash);
/// Sign message.
Signature sign(h256 _messageHash);
/// Decrypt ciphertext.
bytes decrypt(bytesConstRef _cipher);
/// Encrypt using our own public key.
void encrypt(bytes& _text);
private:
ECKeyPair() {}
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> m_pub;
CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> m_sec;
ECKeyPair() {};
std::map<Address,PublicTrust> m_trustEgress;
std::set<PublicTrustNonce> m_trustIngress;
std::set<Nonce> m_trustIngress;
};
}

53
libdevcrypto/ECIES.cpp

@ -29,30 +29,31 @@ using namespace dev;
using namespace dev::crypto;
using namespace CryptoPP;
ECIESEncryptor::ECIESEncryptor(ECKeyPair* _k)
{
m_encryptor.AccessKey().AccessGroupParameters().Initialize(secp256k1());
m_encryptor.AccessKey().SetPublicElement(_k->pub().GetPublicElement());
}
void ECIESEncryptor::encrypt(bytes& _message)
{
std::string c;
StringSource ss(_message.data(), _message.size(), true, new PK_EncryptorFilter(PRNG(), m_encryptor, new StringSink(c)));
bzero(_message.data(), _message.size() * sizeof(byte));
_message = std::move(bytesConstRef(c).toBytes());
}
ECIESDecryptor::ECIESDecryptor(ECKeyPair* _k)
{
m_decryptor.AccessKey().AccessGroupParameters().Initialize(secp256k1());
m_decryptor.AccessKey().SetPrivateExponent(_k->sec().GetPrivateExponent());
}
bytes ECIESDecryptor::decrypt(bytesConstRef& _c)
{
std::string p;
StringSource ss(_c.data(), _c.size(), true, new PK_DecryptorFilter(PRNG(), m_decryptor, new StringSink(p)));
return std::move(bytesConstRef(p).toBytes());
}
//ECIESEncryptor::ECIESEncryptor(ECKeyPair* _k)
//{
// m_encryptor.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1());
// m_encryptor.AccessKey().SetPublicElement(_k->pub().GetPublicElement());
//}
//
//void ECIESEncryptor::encrypt(bytes& _message)
//{
// // todo: determine size and use _message as input and output.
// std::string c;
// StringSource ss(_message.data(), _message.size(), true, new PK_EncryptorFilter(pp::PRNG(), m_encryptor, new StringSink(c)));
// bzero(_message.data(), _message.size() * sizeof(byte));
// _message = std::move(asBytes(c));
//}
//
//ECIESDecryptor::ECIESDecryptor(ECKeyPair* _k)
//{
// m_decryptor.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1());
// m_decryptor.AccessKey().SetPrivateExponent(_k->sec().GetPrivateExponent());
//}
//
//bytes ECIESDecryptor::decrypt(bytesConstRef& _c)
//{
// std::string p;
// StringSource ss(_c.data(), _c.size(), true, new PK_DecryptorFilter(pp::PRNG(), m_decryptor, new StringSink(p)));
// return std::move(asBytes(p));
//}

62
test/crypto.cpp

@ -38,22 +38,36 @@ using namespace CryptoPP;
BOOST_AUTO_TEST_SUITE(devcrypto)
BOOST_AUTO_TEST_CASE(ecies)
BOOST_AUTO_TEST_CASE(eckeypair_encrypt)
{
ECKeyPair k = ECKeyPair::create();
string message("Now is the time for all good persons to come to the aide of humanity.");
string original = message;
string message("Now is the time for all good men to come to the aide of humanity.");
bytes b = bytesRef(message).toBytes();
ECIESEncryptor(&k).encrypt(b);
bytesConstRef br(&b);
bytes plain = ECIESDecryptor(&k).decrypt(br);
bytes b = asBytes(message);
k.encrypt(b);
assert(b != asBytes(original));
// ideally, decryptor will go a step further, accept a bytesRef and zero input.
assert(plain != b);
bytes p = k.decrypt(&b);
assert(p == asBytes(original));
}
// plaintext is same as output
assert(plain == bytesConstRef(message).toBytes());
BOOST_AUTO_TEST_CASE(ecies)
{
// ECKeyPair k = ECKeyPair::create();
//
// string message("Now is the time for all good persons to come to the aide of humanity.");
// bytes b = bytesRef(message).toBytes();
// ECIESEncryptor(&k).encrypt(b);
//
// bytesConstRef br(&b);
// bytes plain = ECIESDecryptor(&k).decrypt(br);
//
// // ideally, decryptor will go a step further, accept a bytesRef and zero input.
// assert(plain != b);
//
// // plaintext is same as output
// assert(plain == bytesConstRef(message).toBytes());
}
BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac)
@ -73,9 +87,9 @@ 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.");
ECIES<ECP>::Decryptor localDecryptor(crypto::PRNG(), crypto::secp256k1());
ECIES<ECP>::Decryptor localDecryptor(pp::PRNG(), pp::secp256k1());
SavePrivateKey(localDecryptor.GetPrivateKey());
ECIES<ECP>::Encryptor localEncryptor(localDecryptor);
@ -83,31 +97,31 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message)
ECIES<ECP>::Decryptor futureDecryptor;
LoadPrivateKey(futureDecryptor.AccessPrivateKey());
futureDecryptor.GetPrivateKey().ThrowIfInvalid(crypto::PRNG(), 3);
futureDecryptor.GetPrivateKey().ThrowIfInvalid(pp::PRNG(), 3);
ECIES<ECP>::Encryptor futureEncryptor;
LoadPublicKey(futureEncryptor.AccessPublicKey());
futureEncryptor.GetPublicKey().ThrowIfInvalid(crypto::PRNG(), 3);
futureEncryptor.GetPublicKey().ThrowIfInvalid(pp::PRNG(), 3);
// encrypt/decrypt with local
string cipherLocal;
StringSource ss1 (message, true, new PK_EncryptorFilter(crypto::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(crypto::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(crypto::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(crypto::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(crypto::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(crypto::PRNG(), localDecryptor, new StringSink(plainLocalFromFuture) ) );
StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG(), localDecryptor, new StringSink(plainLocalFromFuture) ) );
assert(plainLocal == message);
@ -126,12 +140,12 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdh_prime)
ECDH<ECP>::Domain dhLocal(curve);
SecByteBlock privLocal(dhLocal.PrivateKeyLength());
SecByteBlock pubLocal(dhLocal.PublicKeyLength());
dhLocal.GenerateKeyPair(dev::crypto::PRNG(), privLocal, pubLocal);
dhLocal.GenerateKeyPair(pp::PRNG(), privLocal, pubLocal);
ECDH<ECP>::Domain dhRemote(curve);
SecByteBlock privRemote(dhRemote.PrivateKeyLength());
SecByteBlock pubRemote(dhRemote.PublicKeyLength());
dhRemote.GenerateKeyPair(dev::crypto::PRNG(), privRemote, pubRemote);
dhRemote.GenerateKeyPair(pp::PRNG(), privRemote, pubRemote);
assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength());
@ -168,7 +182,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr)
byte ctr[ AES::BLOCKSIZE ];
rng.GenerateBlock( ctr, sizeof(ctr) );
string text = "Now is the time for all good men to come to the aide of humanity.";
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];

Loading…
Cancel
Save