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> #include <files.h>
#pragma warning(pop) #pragma warning(pop)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#include "SHA3.h"
#include "EC.h" #include "EC.h"
// CryptoPP and dev conflict so dev and pp namespace are used explicitly
using namespace std; using namespace std;
using namespace dev::crypto; using namespace dev::crypto;
using namespace CryptoPP; 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 ECKeyPair::create()
{ {
ECKeyPair k; ECKeyPair k;
ECIES<ECP>::Decryptor d(PRNG(), secp256k1());
k.m_sec = d.GetKey(); // export public key and set address
ECIES<ECP>::Encryptor e(d); ECIES<ECP>::Encryptor e(k.m_decryptor.GetKey());
k.m_pub = e.GetKey(); k.m_public = pp::exportPublicKey(e.GetKey());
k.m_address = dev::right160(dev::sha3(k.m_public.ref()));
return k; 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 namespace crypto
{ {
using PublicTrustNonce = h256; namespace pp
typedef std::pair<PublicTrustNonce,Public> PublicTrust; // cryptopp wrappers
{
/// RNG used by CryptoPP
inline CryptoPP::AutoSeededRandomPool& PRNG() { static CryptoPP::AutoSeededRandomPool prng; return prng; } 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 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 ECDHETKeyExchange;
friend class ECIESEncryptor;
friend class ECIESDecryptor;
public: public:
static ECKeyPair create(); static ECKeyPair create();
/// deprecate /// Replaces text with ciphertext.
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pub() { return m_pub; } static void encrypt(bytes& _text, Public _key);
/// deprecate
CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> sec() { return m_sec; } /// @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: private:
ECKeyPair() {} ECKeyPair() {};
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> m_pub;
CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> m_sec;
std::map<Address,PublicTrust> m_trustEgress; 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 dev::crypto;
using namespace CryptoPP; using namespace CryptoPP;
ECIESEncryptor::ECIESEncryptor(ECKeyPair* _k) //ECIESEncryptor::ECIESEncryptor(ECKeyPair* _k)
{ //{
m_encryptor.AccessKey().AccessGroupParameters().Initialize(secp256k1()); // m_encryptor.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1());
m_encryptor.AccessKey().SetPublicElement(_k->pub().GetPublicElement()); // m_encryptor.AccessKey().SetPublicElement(_k->pub().GetPublicElement());
} //}
//
void ECIESEncryptor::encrypt(bytes& _message) //void ECIESEncryptor::encrypt(bytes& _message)
{ //{
std::string c; // // todo: determine size and use _message as input and output.
StringSource ss(_message.data(), _message.size(), true, new PK_EncryptorFilter(PRNG(), m_encryptor, new StringSink(c))); // std::string c;
bzero(_message.data(), _message.size() * sizeof(byte)); // StringSource ss(_message.data(), _message.size(), true, new PK_EncryptorFilter(pp::PRNG(), m_encryptor, new StringSink(c)));
_message = std::move(bytesConstRef(c).toBytes()); // bzero(_message.data(), _message.size() * sizeof(byte));
} // _message = std::move(asBytes(c));
//}
ECIESDecryptor::ECIESDecryptor(ECKeyPair* _k) //
{ //ECIESDecryptor::ECIESDecryptor(ECKeyPair* _k)
m_decryptor.AccessKey().AccessGroupParameters().Initialize(secp256k1()); //{
m_decryptor.AccessKey().SetPrivateExponent(_k->sec().GetPrivateExponent()); // m_decryptor.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1());
} // m_decryptor.AccessKey().SetPrivateExponent(_k->sec().GetPrivateExponent());
//}
bytes ECIESDecryptor::decrypt(bytesConstRef& _c) //
{ //bytes ECIESDecryptor::decrypt(bytesConstRef& _c)
std::string p; //{
StringSource ss(_c.data(), _c.size(), true, new PK_DecryptorFilter(PRNG(), m_decryptor, new StringSink(p))); // std::string p;
return std::move(bytesConstRef(p).toBytes()); // 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_SUITE(devcrypto)
BOOST_AUTO_TEST_CASE(ecies) BOOST_AUTO_TEST_CASE(eckeypair_encrypt)
{ {
ECKeyPair k = ECKeyPair::create(); 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 = asBytes(message);
bytes b = bytesRef(message).toBytes(); k.encrypt(b);
ECIESEncryptor(&k).encrypt(b); assert(b != asBytes(original));
bytesConstRef br(&b);
bytes plain = ECIESDecryptor(&k).decrypt(br);
// ideally, decryptor will go a step further, accept a bytesRef and zero input. bytes p = k.decrypt(&b);
assert(plain != b); assert(p == asBytes(original));
}
// plaintext is same as output BOOST_AUTO_TEST_CASE(ecies)
assert(plain == bytesConstRef(message).toBytes()); {
// 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) BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac)
@ -73,9 +87,9 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message)
{ {
cnote << "Testing 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()); SavePrivateKey(localDecryptor.GetPrivateKey());
ECIES<ECP>::Encryptor localEncryptor(localDecryptor); ECIES<ECP>::Encryptor localEncryptor(localDecryptor);
@ -83,31 +97,31 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message)
ECIES<ECP>::Decryptor futureDecryptor; ECIES<ECP>::Decryptor futureDecryptor;
LoadPrivateKey(futureDecryptor.AccessPrivateKey()); LoadPrivateKey(futureDecryptor.AccessPrivateKey());
futureDecryptor.GetPrivateKey().ThrowIfInvalid(crypto::PRNG(), 3); futureDecryptor.GetPrivateKey().ThrowIfInvalid(pp::PRNG(), 3);
ECIES<ECP>::Encryptor futureEncryptor; ECIES<ECP>::Encryptor futureEncryptor;
LoadPublicKey(futureEncryptor.AccessPublicKey()); LoadPublicKey(futureEncryptor.AccessPublicKey());
futureEncryptor.GetPublicKey().ThrowIfInvalid(crypto::PRNG(), 3); futureEncryptor.GetPublicKey().ThrowIfInvalid(pp::PRNG(), 3);
// encrypt/decrypt with local // encrypt/decrypt with local
string cipherLocal; 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; 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 // encrypt/decrypt with future
string cipherFuture; 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; 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 // decrypt local w/future
string plainFutureFromLocal; 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 // decrypt future w/local
string plainLocalFromFuture; 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); assert(plainLocal == message);
@ -126,12 +140,12 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdh_prime)
ECDH<ECP>::Domain dhLocal(curve); ECDH<ECP>::Domain dhLocal(curve);
SecByteBlock privLocal(dhLocal.PrivateKeyLength()); SecByteBlock privLocal(dhLocal.PrivateKeyLength());
SecByteBlock pubLocal(dhLocal.PublicKeyLength()); SecByteBlock pubLocal(dhLocal.PublicKeyLength());
dhLocal.GenerateKeyPair(dev::crypto::PRNG(), privLocal, pubLocal); dhLocal.GenerateKeyPair(pp::PRNG(), privLocal, pubLocal);
ECDH<ECP>::Domain dhRemote(curve); ECDH<ECP>::Domain dhRemote(curve);
SecByteBlock privRemote(dhRemote.PrivateKeyLength()); SecByteBlock privRemote(dhRemote.PrivateKeyLength());
SecByteBlock pubRemote(dhRemote.PublicKeyLength()); SecByteBlock pubRemote(dhRemote.PublicKeyLength());
dhRemote.GenerateKeyPair(dev::crypto::PRNG(), privRemote, pubRemote); dhRemote.GenerateKeyPair(pp::PRNG(), privRemote, pubRemote);
assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength()); assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength());
@ -168,7 +182,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr)
byte ctr[ AES::BLOCKSIZE ]; byte ctr[ AES::BLOCKSIZE ];
rng.GenerateBlock( ctr, sizeof(ctr) ); 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 // c++11 ftw
unsigned char const* in = (unsigned char*)&text[0]; unsigned char const* in = (unsigned char*)&text[0];
unsigned char* out = (unsigned char*)&text[0]; unsigned char* out = (unsigned char*)&text[0];

Loading…
Cancel
Save