Files
xahaud/modules/ripple_data/crypto/ripple_CKey.h
2013-06-15 18:20:59 -07:00

305 lines
7.9 KiB
C++

//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2011 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#ifndef RIPPLE_CKEY_H
#define RIPPLE_CKEY_H
// secp256k1:
// const unsigned int PRIVATE_KEY_SIZE = 279;
// const unsigned int PUBLIC_KEY_SIZE = 65; // but we don't use full keys
// const unsigned int COMPUB_KEY_SIZE = 33;
// const unsigned int SIGNATURE_SIZE = 72;
//
// see www.keylength.com
// script supports up to 75 for single byte push
// VFALCO NOTE this is unused
/*
int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
{
int okay = 0;
BN_CTX *ctx = NULL;
EC_POINT *pub_key = NULL;
if (!eckey) return 0;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL)
goto err;
pub_key = EC_POINT_new(group);
if (pub_key == NULL)
goto err;
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
goto err;
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
EC_KEY_set_private_key(eckey, priv_key);
EC_KEY_set_public_key(eckey, pub_key);
okay = 1;
err:
if (pub_key)
EC_POINT_free(pub_key);
if (ctx != NULL)
BN_CTX_free(ctx);
return (okay);
}
*/
class key_error : public std::runtime_error
{
public:
explicit key_error (const std::string& str) : std::runtime_error (str) {}
};
class CKey
{
protected:
EC_KEY* pkey;
bool fSet;
public:
typedef boost::shared_ptr<CKey> pointer;
CKey ()
{
pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
if (pkey == NULL)
throw key_error ("CKey::CKey() : EC_KEY_new_by_curve_name failed");
fSet = false;
}
CKey (const CKey& b)
{
pkey = EC_KEY_dup (b.pkey);
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
if (pkey == NULL)
throw key_error ("CKey::CKey(const CKey&) : EC_KEY_dup failed");
fSet = b.fSet;
}
CKey& operator= (const CKey& b)
{
if (!EC_KEY_copy (pkey, b.pkey))
throw key_error ("CKey::operator=(const CKey&) : EC_KEY_copy failed");
fSet = b.fSet;
return (*this);
}
~CKey ()
{
EC_KEY_free (pkey);
}
static uint128 PassPhraseToKey (const std::string& passPhrase);
static EC_KEY* GenerateRootDeterministicKey (const uint128& passPhrase);
static EC_KEY* GenerateRootPubKey (BIGNUM* pubGenerator);
static EC_KEY* GeneratePublicDeterministicKey (const RippleAddress& generator, int n);
static EC_KEY* GeneratePrivateDeterministicKey (const RippleAddress& family, const BIGNUM* rootPriv, int n);
static EC_KEY* GeneratePrivateDeterministicKey (const RippleAddress& family, uint256 const& rootPriv, int n);
CKey (const uint128& passPhrase) : fSet (false)
{
pkey = GenerateRootDeterministicKey (passPhrase);
fSet = true;
assert (pkey);
}
CKey (const RippleAddress& generator, int n) : fSet (false)
{
// public deterministic key
pkey = GeneratePublicDeterministicKey (generator, n);
fSet = true;
assert (pkey);
}
CKey (const RippleAddress& base, const BIGNUM* rootPrivKey, int n) : fSet (false)
{
// private deterministic key
pkey = GeneratePrivateDeterministicKey (base, rootPrivKey, n);
fSet = true;
assert (pkey);
}
CKey (uint256 const& privateKey) : pkey (NULL), fSet (false)
{
// XXX Broken pkey is null.
SetPrivateKeyU (privateKey);
}
#if 0
CKey (const RippleAddress& masterKey, int keyNum, bool isPublic) : pkey (NULL), fSet (false)
{
if (isPublic)
SetPubSeq (masterKey, keyNum);
else
SetPrivSeq (masterKey, keyNum); // broken, need seed
fSet = true;
}
#endif
bool IsNull () const
{
return !fSet;
}
void MakeNewKey ()
{
if (!EC_KEY_generate_key (pkey))
throw key_error ("CKey::MakeNewKey() : EC_KEY_generate_key failed");
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
fSet = true;
}
// XXX Still used!
BIGNUM* GetSecretBN () const
{
// DEPRECATED
return BN_dup (EC_KEY_get0_private_key (pkey));
}
void GetPrivateKeyU (uint256& privKey)
{
const BIGNUM* bn = EC_KEY_get0_private_key (pkey);
if (bn == NULL)
throw key_error ("CKey::GetPrivateKeyU: EC_KEY_get0_private_key failed");
privKey.zero ();
BN_bn2bin (bn, privKey.begin () + (privKey.size () - BN_num_bytes (bn)));
}
bool SetPrivateKeyU (uint256 const& key, bool bThrow = false)
{
// XXX Broken if pkey is not set.
BIGNUM* bn = BN_bin2bn (key.begin (), key.size (), NULL);
bool bSuccess = !!EC_KEY_set_private_key (pkey, bn);
BN_clear_free (bn);
if (bSuccess)
{
fSet = true;
}
else if (bThrow)
{
throw key_error ("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
}
return bSuccess;
}
bool SetPubKey (const void* ptr, size_t len)
{
const unsigned char* pbegin = static_cast<const unsigned char*> (ptr);
if (!o2i_ECPublicKey (&pkey, &pbegin, len))
return false;
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
fSet = true;
return true;
}
bool SetPubKey (Blob const& vchPubKey)
{
return SetPubKey (&vchPubKey[0], vchPubKey.size ());
}
bool SetPubKey (const std::string& pubKey)
{
return SetPubKey (pubKey.data (), pubKey.size ());
}
Blob GetPubKey () const
{
unsigned int nSize = i2o_ECPublicKey (pkey, NULL);
assert (nSize <= 33);
if (!nSize)
throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey failed");
Blob vchPubKey (33, 0);
unsigned char* pbegin = &vchPubKey[0];
if (i2o_ECPublicKey (pkey, &pbegin) != nSize)
throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
assert (vchPubKey.size () <= 33);
return vchPubKey;
}
bool Sign (uint256 const& hash, Blob& vchSig)
{
unsigned char pchSig[10000];
unsigned int nSize = 0;
vchSig.clear ();
if (!ECDSA_sign (0, (unsigned char*)hash.begin (), hash.size (), pchSig, &nSize, pkey))
return false;
vchSig.resize (nSize);
memcpy (&vchSig[0], pchSig, nSize);
return true;
}
bool Verify (uint256 const& hash, const void* sig, size_t sigLen) const
{
// -1 = error, 0 = bad sig, 1 = good
if (ECDSA_verify (0, hash.begin (), hash.size (), (const unsigned char*) sig, sigLen, pkey) != 1)
return false;
return true;
}
bool Verify (uint256 const& hash, Blob const& vchSig) const
{
return Verify (hash, &vchSig[0], vchSig.size ());
}
bool Verify (uint256 const& hash, const std::string& sig) const
{
return Verify (hash, sig.data (), sig.size ());
}
// ECIES functions. These throw on failure
// returns a 32-byte secret unique to these two keys. At least one private key must be known.
void getECIESSecret (CKey& otherKey, uint256& enc_key, uint256& hmac_key);
// encrypt/decrypt functions with integrity checking.
// Note that the other side must somehow know what keys to use
Blob encryptECIES (CKey& otherKey, Blob const& plaintext);
Blob decryptECIES (CKey& otherKey, Blob const& ciphertext);
};
#endif
// vim:ts=4