Browse Source

refactor and thread-safe cryptopp. for now, remove secp256klib calls. ecdh and tests. move sha3mac into sha3.

cl-refactor
subtly 10 years ago
parent
commit
fab63ce0a0
  1. 17
      libdevcrypto/AES.cpp
  2. 5
      libdevcrypto/AES.h
  3. 7
      libdevcrypto/All.h
  4. 103
      libdevcrypto/Common.cpp
  5. 11
      libdevcrypto/Common.h
  6. 192
      libdevcrypto/CryptoPP.cpp
  7. 90
      libdevcrypto/CryptoPP.h
  8. 208
      libdevcrypto/EC.cpp
  9. 62
      libdevcrypto/EC.h
  10. 31
      libdevcrypto/ECDHE.cpp
  11. 4
      libdevcrypto/ECDHE.h
  12. 10
      libdevcrypto/SHA3.cpp
  13. 3
      libdevcrypto/SHA3.h
  14. 40
      libdevcrypto/SHA3MAC.cpp
  15. 38
      libdevcrypto/SHA3MAC.h
  16. 27
      libethcore/CommonEth.cpp
  17. 4
      libethereum/State.cpp
  18. 143
      test/crypto.cpp

17
libdevcrypto/AES.cpp

@ -23,14 +23,21 @@
#include "AES.h"
using namespace std;
using namespace dev;
using namespace dev::crypto;
using namespace dev::crypto::aes;
using namespace dev::crypto::pp;
using namespace CryptoPP;
struct aes::Aes128Ctr
{
Aes128Ctr(h128 _k) { mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); }
CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption mode;
};
Stream::Stream(StreamType _t, h128 _ckey):
m_cSecret(_ckey)
{
(void)_t; // encrypt and decrypt are same operation w/ctr mode
(void)_t; // encrypt and decrypt are same operation w/ctr
cryptor = new Aes128Ctr(_ckey);
}
@ -39,13 +46,13 @@ Stream::~Stream()
delete cryptor;
}
void Stream::update(bytesRef io_bytes)
void Stream::update(bytesRef)
{
}
size_t Stream::streamOut(bytes& o_bytes)
size_t Stream::streamOut(bytes&)
{
return 0;
}

5
libdevcrypto/AES.h

@ -29,10 +29,10 @@ namespace dev
{
namespace crypto
{
namespace pp { struct Aes128Ctr; }
namespace aes
{
struct Aes128Ctr;
enum StreamType { Encrypt, Decrypt };
/**
@ -54,8 +54,9 @@ private:
h128 m_cSecret;
bytes m_text;
pp::Aes128Ctr* cryptor;
Aes128Ctr* cryptor;
};
/**
* @brief Encrypted stream with inband SHA3 mac at specific interval.

7
libdevcrypto/All.h

@ -1,11 +1,8 @@
#pragma once
#include "Common.h"
#include "EC.h"
#include "AES.h"
#include "ECDHE.h"
#include "FileSystem.h"
#include "MemoryDB.h"
#include "OverlayDB.h"
#include "SHA3.h"
#include "SHA3MAC.h"
#include "TrieCommon.h"
#include "TrieDB.h"

103
libdevcrypto/Common.cpp

@ -22,70 +22,46 @@
#include <random>
#include <mutex>
#include "EC.h"
#include "SHA3.h"
#include "FileSystem.h"
#include "CryptoPP.h"
#include "Common.h"
using namespace std;
using namespace dev;
using namespace crypto;
using namespace dev::crypto;
//#define ETH_ADDRESS_DEBUG 1
static Secp256k1 s_secp256k1;
Address dev::toAddress(Secret _secret)
Public dev::toPublic(Secret _secret)
{
return KeyPair(_secret).address();
Public p;
s_secp256k1.toPublic(_secret, p);
return std::move(p);
}
KeyPair KeyPair::create()
Address dev::toAddress(Public _public)
{
static mt19937_64 s_eng(time(0));
uniform_int_distribution<uint16_t> d(0, 255);
for (int i = 0; i < 100; ++i)
{
h256 sec;
for (unsigned i = 0; i < 32; ++i)
sec[i] = (byte)d(s_eng);
KeyPair ret(sec);
if (ret.address())
return ret;
}
return KeyPair();
}
KeyPair::KeyPair(h256 _sec):
m_secret(_sec)
{
toPublic(m_secret, m_public);
if (verifySecret(m_secret, m_public))
m_address = right160(dev::sha3(m_public.ref()));
#if ETH_ADDRESS_DEBUG
cout << "---- ADDRESS -------------------------------" << endl;
cout << "SEC: " << m_secret << endl;
cout << "PUB: " << m_public << endl;
cout << "ADR: " << m_address << endl;
#endif
return s_secp256k1.toAddress(_public);
}
KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password)
Address dev::toAddress(Secret _secret)
{
return KeyPair(sha3(aesDecrypt(_seed, _password)));
Public p;
s_secp256k1.toPublic(_secret, p);
return s_secp256k1.toAddress(p);
}
void dev::encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher)
{
bytes io = _plain.toBytes();
crypto::encrypt(_k, io);
s_secp256k1.encrypt(_k, io);
o_cipher = std::move(io);
}
bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext)
{
bytes io = _cipher.toBytes();
crypto::decrypt(_k, io);
s_secp256k1.decrypt(_k, io);
if (io.empty())
return false;
o_plaintext = std::move(io);
@ -94,17 +70,60 @@ bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext)
Public dev::recover(Signature _sig, h256 _message)
{
return crypto::recover(_sig, _message.ref());
return s_secp256k1.recover(_sig, _message.ref());
}
Signature dev::sign(Secret _k, h256 _hash)
{
return crypto::sign(_k, _hash);
return s_secp256k1.sign(_k, _hash);
}
bool dev::verify(Public _p, Signature _s, h256 _hash)
{
return crypto::verify(_p, _s, bytesConstRef(_hash.data(), 32), true);
return s_secp256k1.verify(_p, _s, bytesConstRef(_hash.data(), 32), true);
}
KeyPair KeyPair::create()
{
static mt19937_64 s_eng(time(0));
uniform_int_distribution<uint16_t> d(0, 255);
for (int i = 0; i < 100; ++i)
{
h256 sec;
for (unsigned i = 0; i < 32; ++i)
sec[i] = (byte)d(s_eng);
KeyPair ret(sec);
if (ret.address())
return ret;
}
return KeyPair();
}
KeyPair::KeyPair(h256 _sec):
m_secret(_sec)
{
if (s_secp256k1.verifySecret(m_secret, m_public))
m_address = s_secp256k1.toAddress(m_public);
}
KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password)
{
return KeyPair(sha3(aesDecrypt(_seed, _password)));
}
h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
{
// H(H(r||k)^h)
h256 s;
sha3mac(Nonce::get().ref(), _priv.ref(), s.ref());
s ^= _hash;
sha3(s.ref(), s.ref());
if (!s || !_hash || !_priv)
BOOST_THROW_EXCEPTION(InvalidState());
return std::move(s);
}
h256 Nonce::get(bool _commit)

11
libdevcrypto/Common.h

@ -30,7 +30,7 @@
namespace dev
{
/// A secret key: 32 bytes.
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
using Secret = h256;
@ -59,6 +59,12 @@ using AddressSet = std::set<h160>;
using Secrets = h256s;
/// Convert a secret key into the public key equivalent.
Public toPublic(Secret _secret);
/// Convert a public key to address.
Address toAddress(Public _public);
/// Convert a secret key into address of public key equivalent.
/// @returns 0 if it's not a valid secret key.
Address toAddress(Secret _secret);
@ -119,6 +125,9 @@ namespace crypto
{
struct InvalidState: public dev::Exception {};
/// Key derivation
h256 kdf(Secret const& _priv, h256 const& _hash);
/**
* @brief Generator for nonce material
*/

192
libdevcrypto/CryptoPP.cpp

@ -21,35 +21,203 @@
#include "CryptoPP.h"
using namespace std;
using namespace dev;
using namespace dev::crypto;
using namespace CryptoPP;
static_assert(dev::Secret::size == 32, "Secret key must be 32 bytes.");
static_assert(dev::Public::size == 64, "Public key must be 64 bytes.");
static_assert(dev::Signature::size == 65, "Signature must be 65 bytes.");
/// Integer and Point Conversion:
void Secp256k1::encrypt(Public const& _k, bytes& io_cipher)
{
ECIES<ECP>::Encryptor e;
initializeDLScheme(_k, e);
void pp::exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k, Public& _p)
size_t plen = io_cipher.size();
bytes ciphertext;
ciphertext.resize(e.CiphertextLength(plen));
{
lock_guard<mutex> l(x_rng);
e.Encrypt(m_rng, io_cipher.data(), plen, ciphertext.data());
}
memset(io_cipher.data(), 0, io_cipher.size());
io_cipher = std::move(ciphertext);
}
void Secp256k1::decrypt(Secret const& _k, bytes& io_text)
{
bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
CryptoPP::ECIES<CryptoPP::ECP>::Decryptor d;
initializeDLScheme(_k, d);
size_t clen = io_text.size();
bytes plain;
plain.resize(d.MaxPlaintextLength(io_text.size()));
secp256k1Params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
DecodingResult r;
{
lock_guard<mutex> l(x_rng);
r = d.Decrypt(m_rng, io_text.data(), clen, plain.data());
}
if (!r.isValidCoding)
{
io_text.clear();
return;
}
io_text.resize(r.messageLength);
io_text = std::move(plain);
}
assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
memcpy(_p.data(), &prefixedKey[1], Public::size);
Signature Secp256k1::sign(Secret const& _k, bytesConstRef _message)
{
return sign(_k, sha3(_message));
}
void pp::exponentToPublic(Integer const& _e, Public& _p)
Signature Secp256k1::sign(Secret const& _key, h256 const& _hash)
{
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pk;
pk.Initialize(secp256k1Params, secp256k1Params.ExponentiateBase(_e));
pp::exportPublicKey(pk, _p);
Signature sig;
Integer k(kdf(_key, _hash).data(), 32);
if (k == 0)
BOOST_THROW_EXCEPTION(InvalidState());
k = 1 + (k % (m_qs - 1));
ECP::Point rp;
Integer r;
{
lock_guard<mutex> l(x_params);
rp = m_params.ExponentiateBase(k);
r = m_params.ConvertElementToInteger(rp);
}
sig[64] = 0;
// sig[64] = (r >= m_q) ? 2 : 0;
Integer kInv = k.InverseMod(m_q);
Integer z(_hash.asBytes().data(), 32);
Integer s = (kInv * (Integer(_key.asBytes().data(), 32)*r + z)) % m_q;
if (r == 0 || s == 0)
BOOST_THROW_EXCEPTION(InvalidState());
// if (s > m_qs)
// {
// s = m_q - s;
// if (sig[64])
// sig[64] ^= 1;
// }
sig[64] |= rp.y.IsOdd() ? 1 : 0;
r.Encode(sig.data(), 32);
s.Encode(sig.data() + 32, 32);
return sig;
}
void pp::ecdhAgree(Secret const& _s, Public const& _r, h256& o_s)
bool Secp256k1::verify(Signature const& _signature, bytesConstRef _message)
{
ECDH<ECP>::Domain d(secp256k1Curve);
return !!recover(_signature, _message);
}
bool Secp256k1::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed)
{
// todo: verify w/o recovery (if faster)
return _p == _hashed ? recover(_sig, _message) : recover(_sig, sha3(_message).ref());
}
Public Secp256k1::recover(Signature _signature, bytesConstRef _message)
{
Public recovered;
Integer r(_signature.data(), 32);
Integer s(_signature.data()+32, 32);
// cryptopp encodes sign of y as 0x02/0x03 instead of 0/1 or 27/28
byte encodedpoint[33];
encodedpoint[0] = _signature[64]|2;
memcpy(&encodedpoint[1], _signature.data(), 32);
ECP::Element x;
{
lock_guard<mutex> l(x_curve);
m_curve.DecodePoint(x, encodedpoint, 33);
if (!m_curve.VerifyPoint(x))
return recovered;
}
// if (_signature[64] & 2)
// {
// r += m_q;
// lock_guard<mutex> l(x_params);
// if (r >= m_params.GetMaxExponent())
// return recovered;
// }
Integer z(_message.data(), 32);
Integer rn = r.InverseMod(m_q);
Integer u1 = m_q - (rn.Times(z)).Modulo(m_q);
Integer u2 = (rn.Times(s)).Modulo(m_q);
ECP::Point p;
byte recoveredbytes[65];
{
lock_guard<mutex> l(x_curve);
// todo: make generator member
p = m_curve.CascadeMultiply(u2, x, u1, m_params.GetSubgroupGenerator());
m_curve.EncodePoint(recoveredbytes, p, false);
}
memcpy(recovered.data(), &recoveredbytes[1], 64);
return recovered;
}
bool Secp256k1::verifySecret(Secret const& _s, Public& _p)
{
DL_PrivateKey_EC<ECP> k;
k.Initialize(m_params, secretToExponent(_s));
if (!k.Validate(m_rng, 3))
return false;
DL_PublicKey_EC<CryptoPP::ECP> pub;
k.MakePublicKey(pub);
if (!k.Validate(m_rng, 3))
return false;
exportPublicKey(pub, _p);
return true;
}
void Secp256k1::agree(Secret const& _s, Public const& _r, h256& o_s)
{
ECDH<ECP>::Domain d(m_oid);
assert(d.AgreedValueLength() == sizeof(o_s));
byte remote[65] = {0x04};
memcpy(&remote[1], _r.data(), 64);
assert(d.Agree(o_s.data(), _s.data(), remote));
}
void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k, Public& _p)
{
bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
{
lock_guard<mutex> l(x_params);
m_params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
}
memcpy(_p.data(), &prefixedKey[1], Public::size);
}
void Secp256k1::exponentToPublic(Integer const& _e, Public& _p)
{
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pk;
{
lock_guard<mutex> l(x_params);
pk.Initialize(m_params, m_params.ExponentiateBase(_e));
}
exportPublicKey(pk, _p);
}

90
libdevcrypto/CryptoPP.h

@ -23,6 +23,7 @@
#pragma once
#include <mutex>
// need to leave this one disabled for link-time. blame cryptopp.
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma warning(push)
@ -48,50 +49,85 @@
#include <dsa.h>
#pragma warning(pop)
#pragma GCC diagnostic pop
#include "SHA3.h"
#include "Common.h"
namespace dev
{
namespace crypto
{
namespace pp
{
using namespace CryptoPP;
inline ECP::Point publicToPoint(Public const& _p) { Integer x(_p.data(), 32); Integer y(_p.data() + 32, 32); return std::move(ECP::Point(x,y)); }
inline Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.data(), Secret::size)); }
/// CryptoPP random number pool
static CryptoPP::AutoSeededRandomPool PRNG;
/**
* CryptoPP secp256k1 algorithms.
*/
class Secp256k1
{
public:
Secp256k1(): m_oid(ASN1::secp256k1()), m_params(m_oid), m_curve(m_params.GetCurve()), m_q(m_params.GetGroupOrder()), m_qs(m_params.GetSubgroupOrder()) {}
/// CryptoPP EC Cruve
static const CryptoPP::OID secp256k1Curve = CryptoPP::ASN1::secp256k1();
Address toAddress(Public const& _p) { return right160(sha3(_p.ref())); }
static const CryptoPP::DL_GroupParameters_EC<CryptoPP::ECP> secp256k1Params(secp256k1Curve);
void toPublic(Secret const& _s, Public& o_public) { exponentToPublic(Integer(_s.data(), sizeof(_s)), o_public); }
static ECP::Point publicToPoint(Public const& _p) { Integer x(_p.data(), 32); Integer y(_p.data() + 32, 32); return std::move(ECP::Point(x,y)); }
/// Encrypts text (replace input).
void encrypt(Public const& _k, bytes& io_cipher);
static Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.data(), Secret::size)); }
void exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k, Public& _p);
static void exportPrivateKey(CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); }
/// Decrypts text (replace input).
void decrypt(Secret const& _k, bytes& io_text);
void exponentToPublic(Integer const& _e, Public& _p);
void ecdhAgree(Secret const& _s, Public const& _r, h256& o_s);
template <class T>
void initializeDLScheme(Secret const& _s, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, secretToExponent(_s)); }
/// @returns siganture of message.
Signature sign(Secret const& _k, bytesConstRef _message);
template <class T>
void initializeDLScheme(Public const& _p, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, publicToPoint(_p)); }
/// @returns compact siganture of message hash.
Signature sign(Secret const& _k, h256 const& _hash);
struct Aes128Ctr
{
Aes128Ctr(h128 _k) { mode.SetKeyWithIV(_k.data(), sizeof(h128), Nonce::get().data()); }
CTR_Mode<AES>::Encryption mode;
/// Verify compact signature (public key is extracted from message).
bool verify(Signature const& _signature, bytesConstRef _message);
/// Verify signature.
bool verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed = false);
/// Recovers public key from compact signature. Uses libsecp256k1.
Public recover(Signature _signature, bytesConstRef _message);
/// Verify secret key is valid.
bool verifySecret(Secret const& _s, Public& o_p);
void agree(Secret const& _s, Public const& _r, h256& o_s);
protected:
void exportPrivateKey(DL_PrivateKey_EC<ECP> const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); }
void exportPublicKey(DL_PublicKey_EC<ECP> const& _k, Public& _p);
void exponentToPublic(Integer const& _e, Public& _p);
template <class T> void initializeDLScheme(Secret const& _s, T& io_operator) { std::lock_guard<std::mutex> l(x_params); io_operator.AccessKey().Initialize(m_params, secretToExponent(_s)); }
template <class T> void initializeDLScheme(Public const& _p, T& io_operator) { std::lock_guard<std::mutex> l(x_params); io_operator.AccessKey().Initialize(m_params, publicToPoint(_p)); }
private:
OID m_oid;
std::mutex x_rng;
AutoSeededRandomPool m_rng;
std::mutex x_params;
DL_GroupParameters_EC<ECP> m_params;
std::mutex x_curve;
DL_GroupParameters_EC<ECP>::EllipticCurve m_curve;
Integer m_q;
Integer m_qs;
};
}
}
}

208
libdevcrypto/EC.cpp

@ -1,208 +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 EC.cpp
* @author Alex Leverington <nessence@gmail.com>
* @date 2014
*
* ECDSA, ECIES
*/
#include <secp256k1/secp256k1.h>
#include "CryptoPP.h"
#include "SHA3.h"
#include "SHA3MAC.h"
#include "EC.h"
static_assert(dev::Secret::size == 32, "Secret key must be 32 bytes.");
static_assert(dev::Public::size == 64, "Public key must be 64 bytes.");
static_assert(dev::Signature::size == 65, "Signature must be 65 bytes.");
using namespace std;
using namespace dev;
using namespace dev::crypto;
using namespace CryptoPP;
using namespace pp;
void crypto::toPublic(Secret const& _s, Public& o_public)
{
exponentToPublic(Integer(_s.data(), sizeof(_s)), o_public);
}
h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
{
// H(H(r||k)^h)
h256 s;
sha3mac(Nonce::get().ref(), _priv.ref(), s.ref());
s ^= _hash;
sha3(s.ref(), s.ref());
if (!s || !_hash || !_priv)
BOOST_THROW_EXCEPTION(InvalidState());
return std::move(s);
}
void crypto::encrypt(Public const& _k, bytes& io_cipher)
{
ECIES<ECP>::Encryptor e;
initializeDLScheme(_k, e);
size_t plen = io_cipher.size();
bytes c;
c.resize(e.CiphertextLength(plen));
// todo: use StringSource with io_cipher as input and output.
e.Encrypt(PRNG, io_cipher.data(), plen, c.data());
memset(io_cipher.data(), 0, io_cipher.size());
io_cipher = std::move(c);
}
void crypto::decrypt(Secret const& _k, bytes& io_text)
{
CryptoPP::ECIES<CryptoPP::ECP>::Decryptor d;
initializeDLScheme(_k, d);
size_t clen = io_text.size();
bytes p;
p.resize(d.MaxPlaintextLength(io_text.size()));
// todo: use StringSource with io_text as input and output.
DecodingResult r = d.Decrypt(PRNG, io_text.data(), clen, p.data());
if (!r.isValidCoding)
{
io_text.clear();
return;
}
io_text.resize(r.messageLength);
io_text = std::move(p);
}
Signature crypto::sign(Secret const& _k, bytesConstRef _message)
{
return crypto::sign(_k, sha3(_message));
}
Signature crypto::sign(Secret const& _key, h256 const& _hash)
{
ECDSA<ECP,SHA3_256>::Signer signer;
initializeDLScheme(_key, signer);
Integer const& q = secp256k1Params.GetGroupOrder();
Integer const& qs = secp256k1Params.GetSubgroupOrder();
Integer e(_hash.asBytes().data(), 32);
Integer k(kdf(_key, _hash).data(), 32);
if (k == 0)
BOOST_THROW_EXCEPTION(InvalidState());
k = 1 + (k % (qs - 1));
ECP::Point rp = secp256k1Params.ExponentiateBase(k);
Integer r = secp256k1Params.ConvertElementToInteger(rp);
int recid = ((r >= q) ? 2 : 0) | (rp.y.IsOdd() ? 1 : 0);
Integer kInv = k.InverseMod(q);
Integer s = (kInv * (Integer(_key.asBytes().data(), 32)*r + e)) % q;
assert(!!r && !!s);
if (s > qs)
{
s = q - s;
if (recid)
recid ^= 1;
}
Signature sig;
r.Encode(sig.data(), 32);
s.Encode(sig.data() + 32, 32);
sig[64] = recid;
return sig;
}
bool crypto::verify(Signature const& _signature, bytesConstRef _message)
{
return crypto::verify(crypto::recover(_signature, _message), _signature, _message);
}
bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed)
{
static size_t derMaxEncodingLength = 72;
if (_hashed)
{
assert(_message.size() == 32);
byte encpub[65] = {0x04};
memcpy(&encpub[1], _p.data(), 64);
byte dersig[derMaxEncodingLength];
size_t cssz = DSAConvertSignatureFormat(dersig, derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363);
assert(cssz <= derMaxEncodingLength);
return (1 == secp256k1_ecdsa_verify(_message.data(), _message.size(), dersig, cssz, encpub, 65));
}
ECDSA<ECP, SHA3_256>::Verifier verifier;
initializeDLScheme(_p, verifier);
return verifier.VerifyMessage(_message.data(), _message.size(), _sig.data(), sizeof(Signature) - 1);
}
Public crypto::recover(Signature _signature, bytesConstRef _message)
{
Integer heInt(_message.data(), 32);
// a different curve would require additional check for v (aka, recid)
Integer r(_signature.data(), 32);
Integer s(_signature.data()+32, 32);
unsigned recid = _signature[64];
byte encodedpoint[33];
encodedpoint[0] = recid|2;
memcpy(&encodedpoint[1], _signature.data(), 32);
ECP::Element x;
secp256k1Params.GetCurve().DecodePoint(x, encodedpoint, 33);
if (!secp256k1Params.GetCurve().VerifyPoint(x))
BOOST_THROW_EXCEPTION(InvalidState());
Integer rn = r.InverseMod(secp256k1Params.GetGroupOrder());
Integer u1 = secp256k1Params.GetGroupOrder() - (rn.Times(heInt)).Modulo(secp256k1Params.GetGroupOrder());
Integer u2 = (rn.Times(s)).Modulo(secp256k1Params.GetGroupOrder());
ECP::Point p = secp256k1Params.GetCurve().CascadeMultiply(u2, x, u1, secp256k1Params.GetSubgroupGenerator());
byte recoveredbytes[65];
secp256k1Params.GetCurve().EncodePoint(recoveredbytes, p, false);
Public recovered;
memcpy(recovered.data(), &recoveredbytes[1], 64);
return recovered;
}
bool crypto::verifySecret(Secret const& _s, Public const& _p)
{
secp256k1_start();
int ok = secp256k1_ecdsa_seckey_verify(_s.data());
if (!ok)
return false;
int pubkeylen = 65;
byte pubkey[pubkeylen];
ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0);
if (!ok || pubkeylen != 65)
return false;
ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
if (!ok)
return false;
for (int i = 0; i < 32; i++)
if (pubkey[i+1]!=_p[i])
return false;
return true;
}

62
libdevcrypto/EC.h

@ -1,62 +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 EC.h
* @author Alex Leverington <nessence@gmail.com>
* @date 2014
*
* ECDSA, ECIES
*/
#pragma once
#include "Common.h"
namespace dev
{
namespace crypto
{
void toPublic(Secret const& _s, Public& o_public);
h256 kdf(Secret const& _priv, h256 const& _hash);
/// Encrypts text (in place).
void encrypt(Public const& _k, bytes& io_cipher);
/// Decrypts text (in place).
void decrypt(Secret const& _k, bytes& io_text);
/// Returns siganture of message.
Signature sign(Secret const& _k, bytesConstRef _message);
/// Returns compact siganture of message hash.
Signature sign(Secret const& _k, h256 const& _hash);
/// Verify compact signature (public key is extracted from message).
bool verify(Signature const& _signature, bytesConstRef _message);
/// Verify signature.
bool verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed = false);
/// Recovers public key from compact signature. Uses libsecp256k1.
Public recover(Signature _signature, bytesConstRef _message);
bool verifySecret(Secret const& _s, Public const& _p);
}
}

31
libdevcrypto/ECDHE.cpp

@ -20,14 +20,14 @@
*/
#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;
static Secp256k1 s_secp256k1;
void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret)
{
@ -36,12 +36,12 @@ void ECDHE::agree(Public const& _remote, Secret& o_sharedSecret)
BOOST_THROW_EXCEPTION(InvalidState());
m_remoteEphemeral = _remote;
ecdhAgree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret);
s_secp256k1.agree(m_ephemeral.sec(), m_remoteEphemeral, o_sharedSecret);
}
void ECDHEKeyExchange::agree(Public const& _remoteEphemeral)
{
ecdhAgree(m_ephemeral.sec(), _remoteEphemeral, m_ephemeralSecret);
s_secp256k1.agree(m_ephemeral.sec(), _remoteEphemeral, m_ephemeralSecret);
}
void ECDHEKeyExchange::exchange(bytes& o_exchange)
@ -50,16 +50,29 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange)
// didn't agree on public remote
BOOST_THROW_EXCEPTION(InvalidState());
// The key exchange payload is in two parts and is encrypted
// using ephemeral keypair.
//
// The first part is the 'prefix' which is a zero-knowledge proof
// allowing the remote to resume or emplace a previous session.
// If a session previously exists:
// prefix is sha3(token) // todo: ephemeral entropy from both sides
// If a session doesn't exist:
// prefix is sha3mac(m_ephemeralSecret,
//
// The second part is encrypted using the public key which relates to the prefix.
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,
// which maybe different than the previously-known public key.
//
// Here we should 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);
s_secp256k1.toPublic(m_alias.m_secret, p);
exchange.resize(exchange.size() + sizeof(p));
memcpy(exchange.data() - sizeof(p), p.data(), sizeof(p));
@ -70,7 +83,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange)
h256 auth;
sha3mac(m_alias.m_secret.ref(), m_ephemeralSecret.ref(), auth.ref());
Signature sig = crypto::sign(m_alias.m_secret, auth);
Signature sig = s_secp256k1.sign(m_alias.m_secret, auth);
exchange.resize(exchange.size() + sizeof(sig));
memcpy(exchange.data() - sizeof(sig), sig.data(), sizeof(sig));
@ -78,7 +91,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange)
h256 prefix(sha3((h256)(m_known.second|m_remoteEphemeral)));
aes.update(prefix.ref());
encrypt(encpk, exchange);
s_secp256k1.encrypt(encpk, exchange);
aes.update(&exchange);
aes.streamOut(o_exchange);

4
libdevcrypto/ECDHE.h

@ -24,7 +24,6 @@
#pragma once
#include "AES.h"
#include "EC.h"
namespace dev
{
@ -33,6 +32,9 @@ namespace crypto
typedef std::pair<Public,h256> AliasSession;
/**
* @brief An addressable EC key pair.
*/
class Alias
{
friend class ECDHEKeyExchange; // todo: remove

10
libdevcrypto/SHA3.cpp

@ -86,6 +86,16 @@ h256 sha3(bytesConstRef _input)
sha3(_input, bytesRef(&ret[0], 32));
return ret;
}
void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output)
{
CryptoPP::SHA3_256 ctx;
assert(_secret.size() > 0);
ctx.Update((byte*)_secret.data(), _secret.size());
ctx.Update((byte*)_plain.data(), _plain.size());
assert(_output.size() >= 32);
ctx.Final(_output.data());
}
bytes aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt)
{

3
libdevcrypto/SHA3.h

@ -55,6 +55,9 @@ inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_inpu
/// Calculate SHA3-256 hash of the given input (presented as a binary-filled string), returning as a 256-bit hash.
inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); }
/// Calculate SHA3-256 MAC
void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output);
/// Calculate SHA3-256 hash of the given input (presented as a FixedHash), returns a 256-bit hash.
template<unsigned N> inline h256 sha3(FixedHash<N> const& _input) { return sha3(_input.ref()); }

40
libdevcrypto/SHA3MAC.cpp

@ -1,40 +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 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 crypto::sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output)
{
CryptoPP::SHA3_256 ctx;
assert(_secret.size() > 0);
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

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

27
libethcore/CommonEth.cpp

@ -28,7 +28,6 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
//#define ETH_ADDRESS_DEBUG 1
namespace dev
{
namespace eth
@ -84,30 +83,4 @@ std::string formatBalance(u256 _b)
return ret.str();
}
Address toAddress(Secret _private)
{
secp256k1_start();
byte pubkey[65];
int pubkeylen = 65;
int ok = secp256k1_ecdsa_seckey_verify(_private.data());
if (!ok)
return Address();
ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _private.data(), 0);
assert(pubkeylen == 65);
if (!ok)
return Address();
ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
if (!ok)
return Address();
auto ret = right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64)));
#if ETH_ADDRESS_DEBUG
cout << "---- ADDRESS -------------------------------" << endl;
cout << "SEC: " << _private << endl;
cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
cout << "ADR: " << ret << endl;
#endif
return ret;
}
}}

4
libethereum/State.cpp

@ -113,8 +113,6 @@ State::State(Address _coinbaseAddress, OverlayDB const& _db):
m_ourAddress(_coinbaseAddress),
m_blockReward(c_blockReward)
{
secp256k1_start();
// Initialise to the state entailed by the genesis block; this guarantees the trie is built correctly.
m_state.init();
@ -138,8 +136,6 @@ State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h):
m_state(&m_db),
m_blockReward(c_blockReward)
{
secp256k1_start();
// TODO THINK: is this necessary?
m_state.init();

143
test/crypto.cpp

@ -27,8 +27,7 @@
#include <libdevcore/Log.h>
#include <libethereum/Transaction.h>
#include <boost/test/unit_test.hpp>
#include <libdevcrypto/SHA3MAC.h>
#include <libdevcrypto/EC.h>
#include <libdevcrypto/SHA3.h>
#include <libdevcrypto/ECDHE.h>
#include <libdevcrypto/CryptoPP.h>
@ -39,6 +38,21 @@ using namespace CryptoPP;
BOOST_AUTO_TEST_SUITE(devcrypto)
static Secp256k1 s_secp256k1;
static CryptoPP::AutoSeededRandomPool s_rng;
static CryptoPP::OID s_curveOID(CryptoPP::ASN1::secp256k1());
static CryptoPP::DL_GroupParameters_EC<CryptoPP::ECP> s_params(s_curveOID);
static CryptoPP::DL_GroupParameters_EC<CryptoPP::ECP>::EllipticCurve s_curve(s_params.GetCurve());
BOOST_AUTO_TEST_CASE(verify_secert)
{
h256 empty;
KeyPair kNot(empty);
BOOST_REQUIRE(!kNot.address());
KeyPair k(sha3(empty));
BOOST_REQUIRE(k.address());
}
BOOST_AUTO_TEST_CASE(common_encrypt_decrypt)
{
string message("Now is the time for all good persons to come to the aid of humanity.");
@ -57,103 +71,50 @@ BOOST_AUTO_TEST_CASE(common_encrypt_decrypt)
BOOST_REQUIRE(plain == asBytes(message));
}
BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1)
{
ECIES<ECP>::Decryptor d(pp::PRNG, pp::secp256k1Curve);
ECIES<ECP>::Encryptor e(d.GetKey());
Secret s;
pp::exportPrivateKey(d.GetKey(), s);
Public p;
pp::exportPublicKey(e.GetKey(), p);
BOOST_REQUIRE(dev::toAddress(s) == right160(dev::sha3(p.ref())));
Secret previous = s;
for (auto i = 0; i < 2; i++)
{
ECIES<ECP>::Decryptor d(pp::PRNG, pp::secp256k1Curve);
ECIES<ECP>::Encryptor e(d.GetKey());
Secret s;
pp::exportPrivateKey(d.GetKey(), s);
BOOST_REQUIRE(s != previous);
Public p;
pp::exportPublicKey(e.GetKey(), p);
h160 secp256k1Addr = dev::toAddress(s);
h160 cryptoppAddr = right160(dev::sha3(p.ref()));
if (secp256k1Addr != cryptoppAddr)
{
BOOST_REQUIRE(secp256k1Addr == cryptoppAddr);
break;
}
}
}
BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_secp256k1libport)
{
// cryptopp implementation of secp256k1lib sign_compact w/recid parameter and recovery of public key from signature
secp256k1_start();
// base secret
Secret secret(sha3("privacy"));
// we get ec params from signer
const CryptoPP::DL_GroupParameters_EC<CryptoPP::ECP> params = pp::secp256k1Params;
ECDSA<ECP, SHA3_256>::Signer signer;
// e := sha3(msg)
bytes e(fromHex("0x01"));
e.resize(32);
int tests = 2; // Oct 29: successful @ 1500
int tests = 2;
while (sha3(&e, &e), secret = sha3(secret.asBytes()), tests--)
{
KeyPair key(secret);
Public pkey = key.pub();
pp::initializeDLScheme(secret, signer);
signer.AccessKey().Initialize(s_params, secretToExponent(secret));
h256 he(sha3(e));
Integer heInt(he.asBytes().data(), 32);
h256 k(crypto::kdf(secret, he));
Integer kInt(k.asBytes().data(), 32);
kInt %= params.GetSubgroupOrder()-1;
kInt %= s_params.GetSubgroupOrder()-1;
ECP::Point rp = params.ExponentiateBase(kInt);
Integer const& q = params.GetGroupOrder();
Integer r = params.ConvertElementToInteger(rp);
int recid = ((r >= q) ? 2 : 0) | (rp.y.IsOdd() ? 1 : 0);
ECP::Point rp = s_params.ExponentiateBase(kInt);
Integer const& q = s_params.GetGroupOrder();
Integer r = s_params.ConvertElementToInteger(rp);
Integer kInv = kInt.InverseMod(q);
Integer s = (kInv * (Integer(secret.asBytes().data(), 32)*r + heInt)) % q;
BOOST_REQUIRE(!!r && !!s);
/*
// For future reference:
// According to maths, this codepath can't be reached, however, it's in secp256k1.
// Commenting this out diverges from codebase implementation.
// To be removed after upstream PR and proof are evaulated.
if (s > params.GetSubgroupOrder())
{
// note: this rarely happens
s = params.GetGroupOrder() - s;
if (recid)
recid ^= 1;
}
*/
Signature sig;
sig[64] = rp.y.IsOdd() ? 1 : 0;
r.Encode(sig.data(), 32);
s.Encode(sig.data() + 32, 32);
sig[64] = recid;
Public p = dev::recover(sig, he);
BOOST_REQUIRE(p == pkey);
// verify w/cryptopp
BOOST_REQUIRE(crypto::verify(pkey, sig, bytesConstRef(&e)));
BOOST_REQUIRE(s_secp256k1.verify(pkey, sig, bytesConstRef(&e)));
// verify with secp256k1lib
byte encpub[65] = {0x04};
@ -167,17 +128,19 @@ BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_secp256k1libport)
BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
{
secp256k1_start();
// cryptopp integer encoding
Integer nHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2H");
Integer nB(fromHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2").data(), 32);
BOOST_REQUIRE(nHex == nB);
bytes sbytes(fromHex("0xFFFF"));
Secret secret(sha3(sbytes)); // 5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2
Secret secret(sha3(sbytes));
KeyPair key(secret);
bytes m(fromHex("0xFF"));
int tests = 3;
int tests = 2;
while (m[0]++, tests--)
{
h256 hm(sha3(m));
@ -187,42 +150,42 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
// raw sign w/cryptopp (doesn't pass through cryptopp hash filter)
ECDSA<ECP, SHA3_256>::Signer signer;
pp::initializeDLScheme(key.sec(), signer);
signer.AccessKey().Initialize(s_params, secretToExponent(key.sec()));
Integer r, s;
signer.RawSign(kInt, hInt, r, s);
// verify cryptopp raw-signature w/cryptopp
ECDSA<ECP, SHA3_256>::Verifier verifier;
pp::initializeDLScheme(key.pub(), verifier);
verifier.AccessKey().Initialize(s_params, publicToPoint(key.pub()));
Signature sigppraw;
r.Encode(sigppraw.data(), 32);
s.Encode(sigppraw.data() + 32, 32);
BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppraw.data(), 64));
BOOST_REQUIRE(crypto::verify(key.pub(), sigppraw, bytesConstRef(&m)));
// BOOST_REQUIRE(crypto::verify(key.pub(), sigppraw, bytesConstRef(&m)));
BOOST_REQUIRE(dev::verify(key.pub(), sigppraw, hm));
// sign with cryptopp, verify, recover w/sec256lib
Signature seclibsig(dev::sign(key.sec(), hm));
BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), seclibsig.data(), 64));
BOOST_REQUIRE(crypto::verify(key.pub(), seclibsig, bytesConstRef(&m)));
// BOOST_REQUIRE(crypto::verify(key.pub(), seclibsig, bytesConstRef(&m)));
BOOST_REQUIRE(dev::verify(key.pub(), seclibsig, hm));
BOOST_REQUIRE(dev::recover(seclibsig, hm) == key.pub());
// sign with cryptopp (w/hash filter?), verify with cryptopp
bytes sigppb(signer.MaxSignatureLength());
size_t ssz = signer.SignMessage(pp::PRNG, m.data(), m.size(), sigppb.data());
size_t ssz = signer.SignMessage(s_rng, m.data(), m.size(), sigppb.data());
Signature sigpp;
memcpy(sigpp.data(), sigppb.data(), 64);
BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppb.data(), ssz));
BOOST_REQUIRE(crypto::verify(key.pub(), sigpp, bytesConstRef(&m)));
// BOOST_REQUIRE(crypto::verify(key.pub(), sigpp, bytesConstRef(&m)));
BOOST_REQUIRE(dev::verify(key.pub(), sigpp, hm));
// sign with cryptopp and stringsource hash filter
string sigstr;
StringSource ssrc(asString(m), true, new SignerFilter(pp::PRNG, signer, new StringSink(sigstr)));
StringSource ssrc(asString(m), true, new SignerFilter(s_rng, signer, new StringSink(sigstr)));
FixedHash<sizeof(Signature)> retsig((byte const*)sigstr.data(), Signature::ConstructFromPointer);
BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), retsig.data(), 64));
BOOST_REQUIRE(crypto::verify(key.pub(), retsig, bytesConstRef(&m)));
// BOOST_REQUIRE(crypto::verify(key.pub(), retsig, bytesConstRef(&m)));
BOOST_REQUIRE(dev::verify(key.pub(), retsig, hm));
/// verification w/sec256lib
@ -248,22 +211,6 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
}
}
BOOST_AUTO_TEST_CASE(cryptopp_public_export_import)
{
ECIES<ECP>::Decryptor d(pp::PRNG, pp::secp256k1Curve);
ECIES<ECP>::Encryptor e(d.GetKey());
Secret s;
pp::exportPrivateKey(d.GetKey(), s);
Public p;
pp::exportPublicKey(e.GetKey(), p);
Address addr = right160(dev::sha3(p.ref()));
BOOST_REQUIRE(toAddress(s) == addr);
KeyPair l(s);
BOOST_REQUIRE(l.address() == addr);
}
BOOST_AUTO_TEST_CASE(ecies_eckeypair)
{
KeyPair k = KeyPair::create();
@ -272,10 +219,10 @@ BOOST_AUTO_TEST_CASE(ecies_eckeypair)
string original = message;
bytes b = asBytes(message);
encrypt(k.pub(), b);
s_secp256k1.encrypt(k.pub(), b);
BOOST_REQUIRE(b != asBytes(original));
decrypt(k.sec(), b);
s_secp256k1.decrypt(k.sec(), b);
BOOST_REQUIRE(b == asBytes(original));
}
@ -283,15 +230,15 @@ BOOST_AUTO_TEST_CASE(ecdh)
{
cnote << "Testing ecdh...";
ECDH<ECP>::Domain dhLocal(pp::secp256k1Curve);
ECDH<ECP>::Domain dhLocal(s_curveOID);
SecByteBlock privLocal(dhLocal.PrivateKeyLength());
SecByteBlock pubLocal(dhLocal.PublicKeyLength());
dhLocal.GenerateKeyPair(pp::PRNG, privLocal, pubLocal);
dhLocal.GenerateKeyPair(s_rng, privLocal, pubLocal);
ECDH<ECP>::Domain dhRemote(pp::secp256k1Curve);
ECDH<ECP>::Domain dhRemote(s_curveOID);
SecByteBlock privRemote(dhRemote.PrivateKeyLength());
SecByteBlock pubRemote(dhRemote.PublicKeyLength());
dhRemote.GenerateKeyPair(pp::PRNG, privRemote, pubRemote);
dhRemote.GenerateKeyPair(s_rng, privRemote, pubRemote);
assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength());
@ -323,7 +270,7 @@ BOOST_AUTO_TEST_CASE(ecdh)
byte pubb[65] = {0x04};
memcpy(&pubb[1], b.pub().data(), 64);
ECDH<ECP>::Domain dhA(pp::secp256k1Curve);
ECDH<ECP>::Domain dhA(s_curveOID);
Secret shared;
BOOST_REQUIRE(dhA.Agree(shared.data(), a.sec().data(), pubb));
BOOST_REQUIRE(shared);

Loading…
Cancel
Save