Browse Source

Placeholder kdf. More cleanup and tests.

cl-refactor
subtly 10 years ago
parent
commit
67747f8cc5
  1. 141
      libdevcrypto/Common.cpp
  2. 17
      libdevcrypto/Common.h
  3. 80
      libdevcrypto/CryptoPP.cpp
  4. 34
      libdevcrypto/CryptoPP.h
  5. 130
      libdevcrypto/EC.cpp
  6. 23
      libdevcrypto/EC.h
  7. 1
      libdevcrypto/FileSystem.h
  8. 34
      test/crypto.cpp

141
libdevcrypto/Common.cpp

@ -14,51 +14,30 @@
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 CommonEth.cpp
/** @file Common.cpp
* @author Gav Wood <i@gavwood.com>
* @author Alex Leverington <nessence@gmail.com>
* @date 2014
*/
#include "Common.h"
#include <random>
#include <secp256k1/secp256k1.h>
#include "EC.h"
#include "SHA3.h"
#include "FileSystem.h"
#include "Common.h"
using namespace std;
using namespace dev;
//#define ETH_ADDRESS_DEBUG 1
Address dev::toAddress(Secret _private)
Address dev::toAddress(Secret _secret)
{
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);
if (asserts(pubkeylen == 65))
return Address();
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;
return KeyPair(_secret).address();
}
KeyPair KeyPair::create()
{
secp256k1_start();
static std::mt19937_64 s_eng(time(0));
std::uniform_int_distribution<uint16_t> d(0, 255);
@ -78,25 +57,10 @@ KeyPair KeyPair::create()
KeyPair::KeyPair(h256 _sec):
m_secret(_sec)
{
secp256k1_start();
int ok = secp256k1_ecdsa_seckey_verify(m_secret.data());
if (!ok)
return;
byte pubkey[65];
int pubkeylen = 65;
ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, m_secret.data(), 0);
if (!ok || pubkeylen != 65)
return;
ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
if (!ok)
return;
m_secret = m_secret;
memcpy(m_public.data(), &(pubkey[1]), 64);
m_address = right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64)));
crypto::toPublic(m_secret, m_public);
if (crypto::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;
@ -129,54 +93,12 @@ bool dev::decrypt(Secret _k, bytesConstRef _cipher, bytes& o_plaintext)
Public dev::recover(Signature _sig, h256 _message)
{
secp256k1_start();
byte pubkey[65];
int pubkeylen = 65;
if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _sig.data(), pubkey, &pubkeylen, 0, (int)_sig[64]))
return Public();
// right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64)));
#if ETH_CRYPTO_TRACE
h256* sig = (h256 const*)_sig.data();
cout << "---- RECOVER -------------------------------" << endl;
cout << "MSG: " << _message << endl;
cout << "R S V: " << sig[0] << " " << sig[1] << " " << (int)(_sig[64] - 27) << "+27" << endl;
cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
#endif
Public ret;
memcpy(&ret, &(pubkey[1]), sizeof(Public));
return ret;
}
inline h256 kFromMessage(h256 _msg, h256 _priv)
{
return _msg ^ _priv;
return crypto::recover(_sig, _message.ref());
}
Signature dev::sign(Secret _k, h256 _hash)
{
int v = 0;
secp256k1_start();
SignatureStruct ret;
h256 nonce = kFromMessage(_hash, _k);
if (!secp256k1_ecdsa_sign_compact(_hash.data(), 32, ret.r.data(), _k.data(), nonce.data(), &v))
return Signature();
#if ETH_ADDRESS_DEBUG
cout << "---- SIGN -------------------------------" << endl;
cout << "MSG: " << _message << endl;
cout << "SEC: " << _k << endl;
cout << "NON: " << nonce << endl;
cout << "R S V: " << ret.r << " " << ret.s << " " << v << "+27" << endl;
#endif
ret.v = v;
return *(Signature const*)&ret;
return crypto::sign(_k, _hash);
}
bool dev::verify(Public _p, Signature _s, h256 _hash)
@ -184,3 +106,40 @@ bool dev::verify(Public _p, Signature _s, h256 _hash)
return crypto::verify(_p, _s, bytesConstRef(_hash.data(), 32), true);
}
h256 Sec::getNonce(bool _commit)
{
// todo: atomic efface bit, periodic save, kdf, rr, rng
static h256 seed;
static string seedFile(getDataDir() + "/seed");
static mutex x;
lock_guard<mutex> l(x);
{
if (!seed)
{
static Sec sec;
bytes b = contents(seedFile);
if (b.size() == 32)
memcpy(seed.data(), b.data(), 32);
else
{
std::mt19937_64 s_eng(time(0));
std::uniform_int_distribution<uint16_t> d(0, 255);
for (unsigned i = 0; i < 32; ++i)
seed[i] = (byte)d(s_eng);
}
writeFile(seedFile, bytes());
}
assert(seed);
h256 prev(seed);
sha3(prev.ref(), seed.ref());
if (_commit)
writeFile(seedFile, seed.asBytes());
}
return seed;
}
Sec::~Sec()
{
Sec::getNonce(true);
}

17
libdevcrypto/Common.h

@ -14,8 +14,9 @@
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 CommonEth.h
/** @file Common.h
* @author Gav Wood <i@gavwood.com>
* @author Alex Leverington <nessence@gmail.com>
* @date 2014
*
* Ethereum-specific data structures & algorithms.
@ -63,8 +64,8 @@ void encrypt(Public _k, bytesConstRef _plain, bytes& o_cipher);
/// 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);
/// Recovers Public key from signed message hash.
Public recover(Signature _sig, h256 _hash);
/// Returns siganture of message hash.
Signature sign(Secret _k, h256 _hash);
@ -109,5 +110,13 @@ private:
Public m_public;
Address m_address;
};
struct Sec
{
static h256 getNonce(bool _commit = false);
private:
Sec() {}
~Sec();
};
}
}

80
libdevcrypto/CryptoPP.cpp

@ -25,85 +25,21 @@ using namespace dev;
using namespace dev::crypto;
using namespace CryptoPP;
/// Conversion from bytes to cryptopp point
inline ECP::Point publicToPoint(Public const& _p);
/// Conversion from bytes to cryptopp exponent
inline Integer secretToExponent(Secret const& _s);
/// Conversion from cryptopp exponent Integer to bytes
inline void exponentToPublic(Integer const& _e, Public& _p);
void pp::initializeSigner(Secret const& _s, ECDSA<ECP, CryptoPP::SHA3_256>::Signer& _signer)
{
_signer.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1Curve);
_signer.AccessKey().SetPrivateExponent(secretToExponent(_s));
}
void pp::initializeVerifier(Public const& _p, ECDSA<ECP, CryptoPP::SHA3_256>::Verifier& _verifier)
{
_verifier.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1Curve);
_verifier.AccessKey().SetPublicElement(publicToPoint(_p));
}
void pp::initializeEncryptor(Public const& _p, CryptoPP::ECIES<CryptoPP::ECP>::Encryptor& _encryptor)
{
_encryptor.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1Curve);
_encryptor.AccessKey().SetPublicElement(publicToPoint(_p));
}
void pp::initializeDecryptor(Secret const& _s, CryptoPP::ECIES<CryptoPP::ECP>::Decryptor& _decryptor)
{
_decryptor.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1Curve);
_decryptor.AccessKey().SetPrivateExponent(secretToExponent(_s));
}
/// Integer and Point Conversion:
void pp::exportPublicKey(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.");
secp256k1Params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
memcpy(_p.data(), &prefixedKey[1], Public::size);
}
void pp::exportPrivateKey(CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> const& _k, Secret& _s)
void pp::exponentToPublic(Integer const& _e, Public& _p)
{
_k.GetPrivateExponent().Encode(_s.data(), Secret::size);
}
/// Integer and Point Conversion:
inline ECP::Point publicToPoint(Public const& _p)
{
ECP::Point p;
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pub;
pub.AccessGroupParameters().Initialize(pp::secp256k1Curve);
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);
}
inline Integer secretToExponent(Secret const& _s)
{
static_assert(Secret::size == 32, "Secret key must be 32 bytes.");
return std::move(Integer(_s.data(), Secret::size));
}
inline void exponentToPublic(Integer const& _e, Public& _p)
{
CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> k;
k.AccessGroupParameters().Initialize(pp::secp256k1Curve);
k.SetPrivateExponent(_e);
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> p;
p.AccessGroupParameters().Initialize(pp::secp256k1Curve);
k.MakePublicKey(p);
pp::exportPublicKey(p, _p);
}
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pk;
pk.Initialize(secp256k1Params, secp256k1Params.ExponentiateBase(_e));
pp::exportPublicKey(pk, _p);
}

34
libdevcrypto/CryptoPP.h

@ -18,7 +18,7 @@
* @author Alex Leverington <nessence@gmail.com>
* @date 2014
*
* CryptoPP headers and helper methods
* CryptoPP headers and primitive helper methods
*/
#pragma once
@ -45,7 +45,6 @@
#include <files.h>
#include <osrng.h>
#include <oids.h>
#include <secp256k1/secp256k1.h>
#include <dsa.h>
#pragma warning(pop)
#pragma GCC diagnostic pop
@ -55,34 +54,35 @@ namespace dev
{
namespace crypto
{
namespace pp
{
using namespace CryptoPP;
/// CryptoPP random number pool
static CryptoPP::AutoSeededRandomPool PRNG;
/// CryptoPP EC Cruve
static const CryptoPP::OID secp256k1Curve = CryptoPP::ASN1::secp256k1();
/// Initialize signer with Secret
void initializeSigner(Secret const& _s, CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA3_256>::Signer& out_signer);
/// Initialize verifier with Public
void initializeVerifier(Public const& _p, CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA3_256>::Verifier& _verifier);
static const CryptoPP::DL_GroupParameters_EC<CryptoPP::ECP> secp256k1Params(secp256k1Curve);
/// Initialize cryptopp encryptor with Public
void initializeEncryptor(Public const& _p, CryptoPP::ECIES<CryptoPP::ECP>::Encryptor& out_encryptor);
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)); }
/// Initialize cryptopp decryptor with Secret
void initializeDecryptor(Secret const& _s, CryptoPP::ECIES<CryptoPP::ECP>::Decryptor& out_decryptor);
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);
/// Conversion from cryptopp public key to bytes
void exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const& _k, Public& out_p);
static void exportPrivateKey(CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> const& _k, Secret& _s) { _k.GetPrivateExponent().Encode(_s.data(), Secret::size); }
/// Conversion from cryptopp private key to bytes
void exportPrivateKey(CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> const& _k, Secret& out_s);
void exponentToPublic(Integer const& _e, Public& _p);
template <class T>
void initializeDLScheme(Secret const& _s, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, secretToExponent(_s)); }
template <class T>
void initializeDLScheme(Public const& _p, T& io_operator) { io_operator.AccessKey().Initialize(pp::secp256k1Params, publicToPoint(_p)); }
}
}
}

130
libdevcrypto/EC.cpp

@ -18,7 +18,7 @@
* @author Alex Leverington <nessence@gmail.com>
* @date 2014
*
* Shared EC classes and functions.
* ECDSA, ECIES
*/
#pragma warning(push)
@ -32,25 +32,44 @@
#include <files.h>
#pragma warning(pop)
#pragma GCC diagnostic pop
#include <secp256k1/secp256k1.h>
#include "CryptoPP.h"
#include "SHA3.h"
#include "SHA3MAC.h"
#include "EC.h"
// CryptoPP and dev conflict so dev and pp namespace are used explicitly
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);
}
void crypto::encrypt(Public const& _key, bytes& io_cipher)
h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
{
h256 s;
sha3mac(Sec::getNonce().ref(), _priv.ref(), s.ref());
assert(s);
return sha3((_hash ^ s).asBytes());
}
void crypto::encrypt(Public const& _k, bytes& io_cipher)
{
ECIES<ECP>::Encryptor e;
pp::initializeEncryptor(_key, 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(pp::PRNG, io_cipher.data(), plen, c.data());
e.Encrypt(PRNG, io_cipher.data(), plen, c.data());
memset(io_cipher.data(), 0, io_cipher.size());
io_cipher = std::move(c);
}
@ -58,12 +77,12 @@ void crypto::encrypt(Public const& _key, bytes& io_cipher)
void crypto::decrypt(Secret const& _k, bytes& io_text)
{
CryptoPP::ECIES<CryptoPP::ECP>::Decryptor d;
pp::initializeDecryptor(_k, 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(pp::PRNG, io_text.data(), clen, p.data());
DecodingResult r = d.Decrypt(PRNG, io_text.data(), clen, p.data());
if (!r.isValidCoding)
{
io_text.clear();
@ -75,19 +94,51 @@ void crypto::decrypt(Secret const& _k, bytes& io_text)
Signature crypto::sign(Secret const& _k, bytesConstRef _message)
{
ECDSA<ECP, SHA3_256>::Signer signer;
pp::initializeSigner(_k, signer);
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 e(_hash.asBytes().data(), 32);
Integer k(kdf(_key, _hash).data(), 32);
k %= secp256k1Params.GetSubgroupOrder()-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 > secp256k1Params.GetSubgroupOrder())
{
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;
}
string sigstr;
StringSource s(_message.toString(), true, new SignerFilter(pp::PRNG, signer, new StringSink(sigstr)));
FixedHash<sizeof(Signature)> retsig((byte const*)sigstr.data(), Signature::ConstructFromPointer);
return std::move(retsig);
bool crypto::verify(Signature const& _signature, bytesConstRef _message)
{
return crypto::verify(crypto::recover(_signature, _message), _signature, _message);
}
bool crypto::verify(Public _p, Signature _sig, bytesConstRef _message, bool _raw)
bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed)
{
static size_t derMaxEncodingLength = 72;
if (_raw)
if (_hashed)
{
assert(_message.size() == 32);
byte encpub[65] = {0x04};
@ -99,10 +150,53 @@ bool crypto::verify(Public _p, Signature _sig, bytesConstRef _message, bool _raw
}
ECDSA<ECP, SHA3_256>::Verifier verifier;
pp::initializeVerifier(_p, verifier);
// cryptopp signatures are 64 bytes
static_assert(sizeof(Signature) == 65, "Expected 65-byte signature.");
initializeDLScheme(_p, verifier);
return verifier.VerifyMessage(_message.data(), _message.size(), _sig.data(), sizeof(Signature) - 1);
}
Public crypto::recover(Signature _signature, bytesConstRef _message)
{
secp256k1_start();
byte pubkey[65];
int pubkeylen = 65;
if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64]))
return Public();
#if ETH_CRYPTO_TRACE
h256* sig = (h256 const*)_signature.data();
cout << "---- RECOVER -------------------------------" << endl;
cout << "MSG: " << _message << endl;
cout << "R S V: " << sig[0] << " " << sig[1] << " " << (int)(_signature[64] - 27) << "+27" << endl;
cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
#endif
Public ret;
memcpy(&ret, &(pubkey[1]), sizeof(Public));
return ret;
}
bool crypto::verifySecret(Secret const& _s, Public const& _p)
{
secp256k1_start();
int ok = secp256k1_ecdsa_seckey_verify(_s.data());
if (!ok)
return false;
byte pubkey[65];
int pubkeylen = 65;
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;
}

23
libdevcrypto/EC.h

@ -18,7 +18,7 @@
* @author Alex Leverington <nessence@gmail.com>
* @date 2014
*
* Shared EC classes and functions.
* ECDSA, ECIES
*/
#pragma once
@ -30,18 +30,33 @@ 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 hash.
/// 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 signature
bool verify(Public _p, Signature _sig, bytesConstRef _message, bool _raw = false);
/// 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);
}
}

1
libdevcrypto/FileSystem.h

@ -24,6 +24,7 @@
#pragma once
#include <string>
#include <libdevcore/CommonIO.h>
namespace dev
{

34
test/crypto.cpp

@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1)
BOOST_REQUIRE(dev::toAddress(s) == right160(dev::sha3(p.ref())));
Secret previous = s;
for (auto i = 0; i < 30; i++)
for (auto i = 0; i < 2; i++)
{
ECIES<ECP>::Decryptor d(pp::PRNG, pp::secp256k1Curve);
ECIES<ECP>::Encryptor e(d.GetKey());
@ -82,7 +82,13 @@ BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1)
Public p;
pp::exportPublicKey(e.GetKey(), p);
BOOST_REQUIRE(dev::toAddress(s) == right160(dev::sha3(p.ref())));
h160 secp256k1Addr = dev::toAddress(s);
h160 cryptoppAddr = right160(dev::sha3(p.ref()));
if (secp256k1Addr != cryptoppAddr)
{
BOOST_REQUIRE(secp256k1Addr == cryptoppAddr);
break;
}
}
}
@ -94,30 +100,29 @@ BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_ecdsav)
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 = 15; // Oct 29: successful @ 1500
int tests = 2; // Oct 29: successful @ 1500
while (sha3(&e, &e), secret = sha3(secret.asBytes()), tests--)
{
KeyPair key(secret);
Public pkey = key.pub();
pp::initializeSigner(secret, signer);
pp::initializeDLScheme(secret, signer);
h256 he(sha3(e));
Integer heInt(he.asBytes().data(), 32);
h256 k(he ^ secret);
h256 k(crypto::kdf(secret, he));
Integer kInt(k.asBytes().data(), 32);
const DL_GroupParameters<ECP::Point> &params = signer.GetKey().GetAbstractGroupParameters();
kInt %= 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);
BOOST_REQUIRE(!(r >= q));
Integer kInv = kInt.InverseMod(q);
Integer s = (kInv * (Integer(secret.asBytes().data(), 32)*r + heInt)) % q;
@ -164,7 +169,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
KeyPair key(secret);
bytes m(fromHex("0x01"));
int tests = 5;
int tests = 2;
while (m[0]++, tests--)
{
h256 hm(sha3(m));
@ -174,27 +179,26 @@ 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::initializeSigner(key.sec(), signer);
pp::initializeDLScheme(key.sec(), signer);
Integer r, s;
signer.RawSign(kInt, hInt, r, s);
// verify cryptopp raw-signature w/cryptopp
ECDSA<ECP, SHA3_256>::Verifier verifier;
pp::initializeVerifier(key.pub(), verifier);
pp::initializeDLScheme(key.pub(), verifier);
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(dev::verify(key.pub(), sigppraw, hm));
BOOST_CHECK(dev::recover(sigppraw, hm) == key.pub());
// sign with sec256lib, verify with cryptopp
// 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(dev::verify(key.pub(), seclibsig, hm));
BOOST_CHECK(dev::recover(seclibsig, hm) == key.pub());
BOOST_REQUIRE(dev::recover(seclibsig, hm) == key.pub());
// sign with cryptopp (w/hash filter?), verify with cryptopp
bytes sigppb(signer.MaxSignatureLength());
@ -204,7 +208,6 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppb.data(), ssz));
BOOST_REQUIRE(crypto::verify(key.pub(), sigpp, bytesConstRef(&m)));
BOOST_REQUIRE(dev::verify(key.pub(), sigpp, hm));
BOOST_CHECK(dev::recover(sigpp, hm) == key.pub());
// sign with cryptopp and stringsource hash filter
string sigstr;
@ -213,7 +216,6 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1)
BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), retsig.data(), 64));
BOOST_REQUIRE(crypto::verify(key.pub(), retsig, bytesConstRef(&m)));
BOOST_REQUIRE(dev::verify(key.pub(), retsig, hm));
BOOST_CHECK(dev::recover(retsig, hm) == key.pub());
/// verification w/sec256lib
// requires public key and sig in standard format

Loading…
Cancel
Save