Reformatting using AStyle

This commit is contained in:
Vinnie Falco
2013-06-14 08:45:13 -07:00
parent 36bd8f7173
commit 521e812fc4
294 changed files with 54609 additions and 47598 deletions

View File

@@ -1,18 +1,18 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
@@ -25,161 +25,176 @@ char const* Base58::s_currentAlphabet = Base58::getRippleAlphabet ();
char const* Base58::getCurrentAlphabet ()
{
return s_currentAlphabet;
return s_currentAlphabet;
}
void Base58::setCurrentAlphabet (char const* alphabet)
{
s_currentAlphabet = alphabet;
s_currentAlphabet = alphabet;
}
char const* Base58::getBitcoinAlphabet ()
{
return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
}
char const* Base58::getRippleAlphabet ()
{
return "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz";
return "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz";
}
char const* Base58::getTestnetAlphabet ()
{
return "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz";
return "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz";
}
std::string Base58::encode (const unsigned char* pbegin, const unsigned char* pend)
{
char const* alphabet = getCurrentAlphabet ();
char const* alphabet = getCurrentAlphabet ();
CAutoBN_CTX pctx;
CBigNum bn58 = 58;
CBigNum bn0 = 0;
CAutoBN_CTX pctx;
CBigNum bn58 = 58;
CBigNum bn0 = 0;
// Convert big endian data to little endian
// Extra zero at the end make sure bignum will interpret as a positive number
Blob vchTmp(pend-pbegin+1, 0);
std::reverse_copy(pbegin, pend, vchTmp.begin());
// Convert big endian data to little endian
// Extra zero at the end make sure bignum will interpret as a positive number
Blob vchTmp (pend - pbegin + 1, 0);
std::reverse_copy (pbegin, pend, vchTmp.begin ());
// Convert little endian data to bignum
CBigNum bn(vchTmp);
// Convert little endian data to bignum
CBigNum bn (vchTmp);
// Convert bignum to std::string
std::string str;
// Expected size increase from base58 conversion is approximately 137%
// use 138% to be safe
str.reserve((pend - pbegin) * 138 / 100 + 1);
CBigNum dv;
CBigNum rem;
while (bn > bn0)
{
if (!BN_div(&dv, &rem, &bn, &bn58, pctx))
throw bignum_error("EncodeBase58 : BN_div failed");
bn = dv;
unsigned int c = rem.getuint();
str += alphabet [c];
}
// Convert bignum to std::string
std::string str;
// Expected size increase from base58 conversion is approximately 137%
// use 138% to be safe
str.reserve ((pend - pbegin) * 138 / 100 + 1);
CBigNum dv;
CBigNum rem;
// Leading zeroes encoded as base58 zeros
for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)
str += alphabet [0];
while (bn > bn0)
{
if (!BN_div (&dv, &rem, &bn, &bn58, pctx))
throw bignum_error ("EncodeBase58 : BN_div failed");
// Convert little endian std::string to big endian
reverse(str.begin(), str.end());
return str;
bn = dv;
unsigned int c = rem.getuint ();
str += alphabet [c];
}
// Leading zeroes encoded as base58 zeros
for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)
str += alphabet [0];
// Convert little endian std::string to big endian
reverse (str.begin (), str.end ());
return str;
}
std::string Base58::encode (Blob const& vch)
{
return encode (&vch[0], &vch[0] + vch.size());
return encode (&vch[0], &vch[0] + vch.size ());
}
std::string Base58::encodeWithCheck (Blob const& vchIn)
{
// add 4-byte hash check to the end
Blob vch(vchIn);
uint256 hash = SHA256Hash(vch.begin(), vch.end());
vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
return encode (vch);
// add 4-byte hash check to the end
Blob vch (vchIn);
uint256 hash = SHA256Hash (vch.begin (), vch.end ());
vch.insert (vch.end (), (unsigned char*)&hash, (unsigned char*)&hash + 4);
return encode (vch);
}
bool Base58::decode (const char* psz, Blob& vchRet, const char* pAlpha)
{
assert (pAlpha != 0);
assert (pAlpha != 0);
CAutoBN_CTX pctx;
vchRet.clear();
CBigNum bn58 = 58;
CBigNum bn = 0;
CBigNum bnChar;
while (isspace(*psz))
psz++;
CAutoBN_CTX pctx;
vchRet.clear ();
CBigNum bn58 = 58;
CBigNum bn = 0;
CBigNum bnChar;
// Convert big endian string to bignum
for (const char* p = psz; *p; p++)
{
const char* p1 = strchr(pAlpha, *p);
if (p1 == NULL)
{
while (isspace(*p))
p++;
if (*p != '\0')
return false;
break;
}
bnChar.setuint(p1 - pAlpha);
if (!BN_mul(&bn, &bn, &bn58, pctx))
throw bignum_error("DecodeBase58 : BN_mul failed");
bn += bnChar;
}
while (isspace (*psz))
psz++;
// Get bignum as little endian data
Blob vchTmp = bn.getvch();
// Convert big endian string to bignum
for (const char* p = psz; *p; p++)
{
const char* p1 = strchr (pAlpha, *p);
// Trim off sign byte if present
if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80)
vchTmp.erase(vchTmp.end()-1);
if (p1 == NULL)
{
while (isspace (*p))
p++;
// Restore leading zeros
int nLeadingZeros = 0;
for (const char* p = psz; *p == pAlpha[0]; p++)
nLeadingZeros++;
vchRet.assign(nLeadingZeros + vchTmp.size(), 0);
if (*p != '\0')
return false;
// Convert little endian data to big endian
std::reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size());
return true;
break;
}
bnChar.setuint (p1 - pAlpha);
if (!BN_mul (&bn, &bn, &bn58, pctx))
throw bignum_error ("DecodeBase58 : BN_mul failed");
bn += bnChar;
}
// Get bignum as little endian data
Blob vchTmp = bn.getvch ();
// Trim off sign byte if present
if (vchTmp.size () >= 2 && vchTmp.end ()[-1] == 0 && vchTmp.end ()[-2] >= 0x80)
vchTmp.erase (vchTmp.end () - 1);
// Restore leading zeros
int nLeadingZeros = 0;
for (const char* p = psz; *p == pAlpha[0]; p++)
nLeadingZeros++;
vchRet.assign (nLeadingZeros + vchTmp.size (), 0);
// Convert little endian data to big endian
std::reverse_copy (vchTmp.begin (), vchTmp.end (), vchRet.end () - vchTmp.size ());
return true;
}
bool Base58::decode (const std::string& str, Blob& vchRet)
{
return decode (str.c_str(), vchRet);
return decode (str.c_str (), vchRet);
}
bool Base58::decodeWithCheck (const char* psz, Blob& vchRet, const char* pAlphabet)
{
assert (pAlphabet != NULL);
assert (pAlphabet != NULL);
if (!decode (psz, vchRet, pAlphabet))
return false;
if (vchRet.size() < 4)
{
vchRet.clear();
return false;
}
uint256 hash = SHA256Hash(vchRet.begin(), vchRet.end()-4);
if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
{
vchRet.clear();
return false;
}
vchRet.resize(vchRet.size()-4);
return true;
if (!decode (psz, vchRet, pAlphabet))
return false;
if (vchRet.size () < 4)
{
vchRet.clear ();
return false;
}
uint256 hash = SHA256Hash (vchRet.begin (), vchRet.end () - 4);
if (memcmp (&hash, &vchRet.end ()[-4], 4) != 0)
{
vchRet.clear ();
return false;
}
vchRet.resize (vchRet.size () - 4);
return true;
}
bool Base58::decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet)
{
return decodeWithCheck (str.c_str(), vchRet, pAlphabet);
return decodeWithCheck (str.c_str (), vchRet, pAlphabet);
}
// vim:ts=4

View File

@@ -1,18 +1,18 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
@@ -36,25 +36,25 @@
class Base58
{
public:
// VFALCO TODO clean up this poor API
static char const* getCurrentAlphabet ();
static void setCurrentAlphabet (char const* alphabet);
// VFALCO TODO clean up this poor API
static char const* getCurrentAlphabet ();
static void setCurrentAlphabet (char const* alphabet);
static char const* getBitcoinAlphabet ();
static char const* getRippleAlphabet ();
static char const* getTestnetAlphabet ();
static char const* getBitcoinAlphabet ();
static char const* getRippleAlphabet ();
static char const* getTestnetAlphabet ();
static std::string encode (const unsigned char* pbegin, const unsigned char* pend);
static std::string encode (Blob const& vch);
static std::string encodeWithCheck (Blob const& vchIn);
static std::string encode (const unsigned char* pbegin, const unsigned char* pend);
static std::string encode (Blob const& vch);
static std::string encodeWithCheck (Blob const& vchIn);
static bool decode (const char* psz, Blob& vchRet, const char* pAlphabet=getCurrentAlphabet ());
static bool decode (const std::string& str, Blob& vchRet);
static bool decodeWithCheck (const char* psz, Blob& vchRet, const char* pAlphabet=getCurrentAlphabet ());
static bool decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet);
static bool decode (const char* psz, Blob& vchRet, const char* pAlphabet = getCurrentAlphabet ());
static bool decode (const std::string& str, Blob& vchRet);
static bool decodeWithCheck (const char* psz, Blob& vchRet, const char* pAlphabet = getCurrentAlphabet ());
static bool decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet);
private:
static char const* s_currentAlphabet;
static char const* s_currentAlphabet;
};
#endif

View File

@@ -1,18 +1,18 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
@@ -29,91 +29,118 @@
// - Doubleclicking selects the whole number as one word if it's all alphanumeric.
//
CBase58Data::CBase58Data()
: nVersion(1)
CBase58Data::CBase58Data ()
: nVersion (1)
{
}
CBase58Data::~CBase58Data()
CBase58Data::~CBase58Data ()
{
if (!vchData.empty())
memset(&vchData[0], 0, vchData.size());
if (!vchData.empty ())
memset (&vchData[0], 0, vchData.size ());
}
void CBase58Data::SetData(int nVersionIn, Blob const& vchDataIn)
void CBase58Data::SetData (int nVersionIn, Blob const& vchDataIn)
{
nVersion = nVersionIn;
vchData = vchDataIn;
nVersion = nVersionIn;
vchData = vchDataIn;
}
void CBase58Data::SetData(int nVersionIn, const void* pdata, size_t nSize)
void CBase58Data::SetData (int nVersionIn, const void* pdata, size_t nSize)
{
nVersion = nVersionIn;
vchData.resize(nSize);
vchData.resize (nSize);
if (nSize)
memcpy(&vchData[0], pdata, nSize);
memcpy (&vchData[0], pdata, nSize);
}
void CBase58Data::SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
void CBase58Data::SetData (int nVersionIn, const unsigned char* pbegin, const unsigned char* pend)
{
SetData(nVersionIn, (void*)pbegin, pend - pbegin);
SetData (nVersionIn, (void*)pbegin, pend - pbegin);
}
bool CBase58Data::SetString(const char* psz, unsigned char version, const char* pAlphabet)
bool CBase58Data::SetString (const char* psz, unsigned char version, const char* pAlphabet)
{
Blob vchTemp;
Base58::decodeWithCheck (psz, vchTemp, pAlphabet);
if (vchTemp.empty() || vchTemp[0] != version)
if (vchTemp.empty () || vchTemp[0] != version)
{
vchData.clear();
vchData.clear ();
nVersion = 1;
return false;
}
nVersion = vchTemp[0];
vchData.resize(vchTemp.size() - 1);
if (!vchData.empty())
memcpy(&vchData[0], &vchTemp[1], vchData.size());
memset(&vchTemp[0], 0, vchTemp.size());
vchData.resize (vchTemp.size () - 1);
if (!vchData.empty ())
memcpy (&vchData[0], &vchTemp[1], vchData.size ());
memset (&vchTemp[0], 0, vchTemp.size ());
return true;
}
bool CBase58Data::SetString(const std::string& str, unsigned char version)
bool CBase58Data::SetString (const std::string& str, unsigned char version)
{
return SetString(str.c_str(), version);
return SetString (str.c_str (), version);
}
std::string CBase58Data::ToString() const
std::string CBase58Data::ToString () const
{
Blob vch(1, nVersion);
Blob vch (1, nVersion);
vch.insert(vch.end(), vchData.begin(), vchData.end());
vch.insert (vch.end (), vchData.begin (), vchData.end ());
return Base58::encodeWithCheck (vch);
}
int CBase58Data::CompareTo(const CBase58Data& b58) const
int CBase58Data::CompareTo (const CBase58Data& b58) const
{
if (nVersion < b58.nVersion) return -1;
if (nVersion > b58.nVersion) return 1;
if (vchData < b58.vchData) return -1;
if (vchData > b58.vchData) return 1;
return 0;
}
bool CBase58Data::operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
bool CBase58Data::operator!=(const CBase58Data& b58) const { return CompareTo(b58) != 0; }
bool CBase58Data::operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
bool CBase58Data::operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
bool CBase58Data::operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; }
bool CBase58Data::operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
bool CBase58Data::operator== (const CBase58Data& b58) const
{
return CompareTo (b58) == 0;
}
bool CBase58Data::operator!= (const CBase58Data& b58) const
{
return CompareTo (b58) != 0;
}
bool CBase58Data::operator<= (const CBase58Data& b58) const
{
return CompareTo (b58) <= 0;
}
bool CBase58Data::operator>= (const CBase58Data& b58) const
{
return CompareTo (b58) >= 0;
}
bool CBase58Data::operator< (const CBase58Data& b58) const
{
return CompareTo (b58) < 0;
}
bool CBase58Data::operator> (const CBase58Data& b58) const
{
return CompareTo (b58) > 0;
}
std::size_t hash_value(const CBase58Data& b58)
std::size_t hash_value (const CBase58Data& b58)
{
std::size_t seed = HashMaps::getInstance ().getNonce <size_t> ()
+ (b58.nVersion * HashMaps::goldenRatio);
boost::hash_combine (seed, b58.vchData);
return seed;
}

View File

@@ -1,18 +1,18 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
@@ -37,28 +37,28 @@ protected:
unsigned char nVersion;
Blob vchData;
CBase58Data();
~CBase58Data();
CBase58Data ();
~CBase58Data ();
void SetData(int nVersionIn, Blob const& vchDataIn);
void SetData(int nVersionIn, const void* pdata, size_t nSize);
void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend);
void SetData (int nVersionIn, Blob const& vchDataIn);
void SetData (int nVersionIn, const void* pdata, size_t nSize);
void SetData (int nVersionIn, const unsigned char* pbegin, const unsigned char* pend);
public:
bool SetString(const char* psz, unsigned char version, const char* pAlphabet = Base58::getCurrentAlphabet());
bool SetString(const std::string& str, unsigned char version);
bool SetString (const char* psz, unsigned char version, const char* pAlphabet = Base58::getCurrentAlphabet ());
bool SetString (const std::string& str, unsigned char version);
std::string ToString() const;
int CompareTo(const CBase58Data& b58) const;
std::string ToString () const;
int CompareTo (const CBase58Data& b58) const;
bool operator==(const CBase58Data& b58) const;
bool operator!=(const CBase58Data& b58) const;
bool operator<=(const CBase58Data& b58) const;
bool operator>=(const CBase58Data& b58) const;
bool operator== (const CBase58Data& b58) const;
bool operator!= (const CBase58Data& b58) const;
bool operator<= (const CBase58Data& b58) const;
bool operator>= (const CBase58Data& b58) const;
bool operator< (const CBase58Data& b58) const;
bool operator> (const CBase58Data& b58) const;
friend std::size_t hash_value(const CBase58Data& b58);
friend std::size_t hash_value (const CBase58Data& b58);
};
extern std::size_t hash_value (const CBase58Data& b58);

View File

@@ -3,528 +3,635 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
CBigNum::CBigNum()
CBigNum::CBigNum ()
{
BN_init(this);
BN_init (this);
}
CBigNum::CBigNum(const CBigNum& b)
CBigNum::CBigNum (const CBigNum& b)
{
BN_init(this);
if (!BN_copy(this, &b))
{
BN_clear_free(this);
throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
}
BN_init (this);
if (!BN_copy (this, &b))
{
BN_clear_free (this);
throw bignum_error ("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
}
}
CBigNum& CBigNum::operator=(const CBigNum& b)
CBigNum& CBigNum::operator= (const CBigNum& b)
{
if (!BN_copy(this, &b))
throw bignum_error("CBigNum::operator= : BN_copy failed");
return (*this);
if (!BN_copy (this, &b))
throw bignum_error ("CBigNum::operator= : BN_copy failed");
return (*this);
}
CBigNum::~CBigNum()
CBigNum::~CBigNum ()
{
BN_clear_free(this);
BN_clear_free (this);
}
CBigNum::CBigNum(char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(int64 n) { BN_init(this); setint64(n); }
CBigNum::CBigNum(unsigned char n) { BN_init(this); setulong(n); }
CBigNum::CBigNum(unsigned short n) { BN_init(this); setulong(n); }
CBigNum::CBigNum(unsigned int n) { BN_init(this); setulong(n); }
CBigNum::CBigNum(uint64 n) { BN_init(this); setuint64(n); }
CBigNum::CBigNum(uint256 n) { BN_init(this); setuint256(n); }
CBigNum::CBigNum(Blob const& vch)
CBigNum::CBigNum (char n)
{
BN_init(this);
setvch(vch);
BN_init (this);
if (n >= 0) setulong (n);
else setint64 (n);
}
CBigNum::CBigNum (short n)
{
BN_init (this);
if (n >= 0) setulong (n);
else setint64 (n);
}
CBigNum::CBigNum (int n)
{
BN_init (this);
if (n >= 0) setulong (n);
else setint64 (n);
}
CBigNum::CBigNum (long n)
{
BN_init (this);
if (n >= 0) setulong (n);
else setint64 (n);
}
CBigNum::CBigNum (int64 n)
{
BN_init (this);
setint64 (n);
}
CBigNum::CBigNum (unsigned char n)
{
BN_init (this);
setulong (n);
}
CBigNum::CBigNum (unsigned short n)
{
BN_init (this);
setulong (n);
}
CBigNum::CBigNum (unsigned int n)
{
BN_init (this);
setulong (n);
}
CBigNum::CBigNum (uint64 n)
{
BN_init (this);
setuint64 (n);
}
CBigNum::CBigNum (uint256 n)
{
BN_init (this);
setuint256 (n);
}
void CBigNum::setuint(unsigned int n)
CBigNum::CBigNum (Blob const& vch)
{
setulong(static_cast<unsigned long>(n));
BN_init (this);
setvch (vch);
}
unsigned int CBigNum::getuint() const
void CBigNum::setuint (unsigned int n)
{
return BN_get_word(this);
setulong (static_cast<unsigned long> (n));
}
int CBigNum::getint() const
unsigned int CBigNum::getuint () const
{
unsigned long n = BN_get_word(this);
if (!BN_is_negative(this))
return (n > INT_MAX ? INT_MAX : n);
else
return (n > INT_MAX ? INT_MIN : -(int)n);
return BN_get_word (this);
}
void CBigNum::setint64(int64 n)
int CBigNum::getint () const
{
unsigned char pch[sizeof(n) + 6];
unsigned char* p = pch + 4;
bool fNegative = false;
if (n < (int64)0)
{
n = -n;
fNegative = true;
}
bool fLeadingZeroes = true;
for (int i = 0; i < 8; i++)
{
unsigned char c = (n >> 56) & 0xff;
n <<= 8;
if (fLeadingZeroes)
{
if (c == 0)
continue;
if (c & 0x80)
*p++ = (fNegative ? 0x80 : 0);
else if (fNegative)
c |= 0x80;
fLeadingZeroes = false;
}
*p++ = c;
}
unsigned int nSize = p - (pch + 4);
pch[0] = (nSize >> 24) & 0xff;
pch[1] = (nSize >> 16) & 0xff;
pch[2] = (nSize >> 8) & 0xff;
pch[3] = (nSize) & 0xff;
BN_mpi2bn(pch, p - pch, this);
unsigned long n = BN_get_word (this);
if (!BN_is_negative (this))
return (n > INT_MAX ? INT_MAX : n);
else
return (n > INT_MAX ? INT_MIN : - (int)n);
}
uint64 CBigNum::getuint64() const
void CBigNum::setint64 (int64 n)
{
unsigned char pch[sizeof (n) + 6];
unsigned char* p = pch + 4;
bool fNegative = false;
if (n < (int64)0)
{
n = -n;
fNegative = true;
}
bool fLeadingZeroes = true;
for (int i = 0; i < 8; i++)
{
unsigned char c = (n >> 56) & 0xff;
n <<= 8;
if (fLeadingZeroes)
{
if (c == 0)
continue;
if (c & 0x80)
*p++ = (fNegative ? 0x80 : 0);
else if (fNegative)
c |= 0x80;
fLeadingZeroes = false;
}
*p++ = c;
}
unsigned int nSize = p - (pch + 4);
pch[0] = (nSize >> 24) & 0xff;
pch[1] = (nSize >> 16) & 0xff;
pch[2] = (nSize >> 8) & 0xff;
pch[3] = (nSize) & 0xff;
BN_mpi2bn (pch, p - pch, this);
}
uint64 CBigNum::getuint64 () const
{
#if (ULONG_MAX > UINT_MAX)
return static_cast<uint64>(getulong());
return static_cast<uint64> (getulong ());
#else
int len = BN_num_bytes(this);
if (len > 8)
throw std::runtime_error("BN getuint64 overflow");
int len = BN_num_bytes (this);
unsigned char buf[8];
memset(buf, 0, sizeof(buf));
BN_bn2bin(this, buf + 8 - len);
return
static_cast<uint64>(buf[0]) << 56 | static_cast<uint64>(buf[1]) << 48 |
static_cast<uint64>(buf[2]) << 40 | static_cast<uint64>(buf[3]) << 32 |
static_cast<uint64>(buf[4]) << 24 | static_cast<uint64>(buf[5]) << 16 |
static_cast<uint64>(buf[6]) << 8 | static_cast<uint64>(buf[7]);
if (len > 8)
throw std::runtime_error ("BN getuint64 overflow");
unsigned char buf[8];
memset (buf, 0, sizeof (buf));
BN_bn2bin (this, buf + 8 - len);
return
static_cast<uint64> (buf[0]) << 56 | static_cast<uint64> (buf[1]) << 48 |
static_cast<uint64> (buf[2]) << 40 | static_cast<uint64> (buf[3]) << 32 |
static_cast<uint64> (buf[4]) << 24 | static_cast<uint64> (buf[5]) << 16 |
static_cast<uint64> (buf[6]) << 8 | static_cast<uint64> (buf[7]);
#endif
}
void CBigNum::setuint64(uint64 n)
void CBigNum::setuint64 (uint64 n)
{
#if (ULONG_MAX > UINT_MAX)
setulong(static_cast<unsigned long>(n));
setulong (static_cast<unsigned long> (n));
#else
unsigned char buf[8];
buf[0] = static_cast<unsigned char>((n >> 56) & 0xff);
buf[1] = static_cast<unsigned char>((n >> 48) & 0xff);
buf[2] = static_cast<unsigned char>((n >> 40) & 0xff);
buf[3] = static_cast<unsigned char>((n >> 32) & 0xff);
buf[4] = static_cast<unsigned char>((n >> 24) & 0xff);
buf[5] = static_cast<unsigned char>((n >> 16) & 0xff);
buf[6] = static_cast<unsigned char>((n >> 8) & 0xff);
buf[7] = static_cast<unsigned char>((n) & 0xff);
BN_bin2bn(buf, 8, this);
unsigned char buf[8];
buf[0] = static_cast<unsigned char> ((n >> 56) & 0xff);
buf[1] = static_cast<unsigned char> ((n >> 48) & 0xff);
buf[2] = static_cast<unsigned char> ((n >> 40) & 0xff);
buf[3] = static_cast<unsigned char> ((n >> 32) & 0xff);
buf[4] = static_cast<unsigned char> ((n >> 24) & 0xff);
buf[5] = static_cast<unsigned char> ((n >> 16) & 0xff);
buf[6] = static_cast<unsigned char> ((n >> 8) & 0xff);
buf[7] = static_cast<unsigned char> ((n) & 0xff);
BN_bin2bn (buf, 8, this);
#endif
}
void CBigNum::setuint256(uint256 const& n)
void CBigNum::setuint256 (uint256 const& n)
{
BN_bin2bn(n.begin(), n.size(), NULL);
BN_bin2bn (n.begin (), n.size (), NULL);
}
uint256 CBigNum::getuint256()
uint256 CBigNum::getuint256 ()
{
uint256 ret;
unsigned int size = BN_num_bytes(this);
if (size > ret.size())
return ret;
BN_bn2bin(this, ret.begin() + (ret.size() - BN_num_bytes(this)));
return ret;
uint256 ret;
unsigned int size = BN_num_bytes (this);
if (size > ret.size ())
return ret;
BN_bn2bin (this, ret.begin () + (ret.size () - BN_num_bytes (this)));
return ret;
}
void CBigNum::setvch(Blob const& vch)
void CBigNum::setvch (Blob const& vch)
{
Blob vch2(vch.size() + 4);
unsigned int nSize = vch.size();
// BIGNUM's byte stream format expects 4 bytes of
// big endian size data info at the front
vch2[0] = (nSize >> 24) & 0xff;
vch2[1] = (nSize >> 16) & 0xff;
vch2[2] = (nSize >> 8) & 0xff;
vch2[3] = (nSize >> 0) & 0xff;
// swap data to big endian
std::reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
BN_mpi2bn(&vch2[0], vch2.size(), this);
Blob vch2 (vch.size () + 4);
unsigned int nSize = vch.size ();
// BIGNUM's byte stream format expects 4 bytes of
// big endian size data info at the front
vch2[0] = (nSize >> 24) & 0xff;
vch2[1] = (nSize >> 16) & 0xff;
vch2[2] = (nSize >> 8) & 0xff;
vch2[3] = (nSize >> 0) & 0xff;
// swap data to big endian
std::reverse_copy (vch.begin (), vch.end (), vch2.begin () + 4);
BN_mpi2bn (&vch2[0], vch2.size (), this);
}
Blob CBigNum::getvch() const
Blob CBigNum::getvch () const
{
unsigned int nSize = BN_bn2mpi(this, NULL);
if (nSize < 4)
return Blob ();
Blob vch(nSize);
BN_bn2mpi(this, &vch[0]);
vch.erase(vch.begin(), vch.begin() + 4);
reverse(vch.begin(), vch.end());
return vch;
unsigned int nSize = BN_bn2mpi (this, NULL);
if (nSize < 4)
return Blob ();
Blob vch (nSize);
BN_bn2mpi (this, &vch[0]);
vch.erase (vch.begin (), vch.begin () + 4);
reverse (vch.begin (), vch.end ());
return vch;
}
CBigNum& CBigNum::SetCompact(unsigned int nCompact)
CBigNum& CBigNum::SetCompact (unsigned int nCompact)
{
unsigned int nSize = nCompact >> 24;
Blob vch(4 + nSize);
vch[3] = nSize;
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
BN_mpi2bn(&vch[0], vch.size(), this);
return *this;
unsigned int nSize = nCompact >> 24;
Blob vch (4 + nSize);
vch[3] = nSize;
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
BN_mpi2bn (&vch[0], vch.size (), this);
return *this;
}
unsigned int CBigNum::GetCompact() const
unsigned int CBigNum::GetCompact () const
{
unsigned int nSize = BN_bn2mpi(this, NULL);
Blob vch(nSize);
nSize -= 4;
BN_bn2mpi(this, &vch[0]);
unsigned int nCompact = nSize << 24;
if (nSize >= 1) nCompact |= (vch[4] << 16);
if (nSize >= 2) nCompact |= (vch[5] << 8);
if (nSize >= 3) nCompact |= (vch[6] << 0);
return nCompact;
unsigned int nSize = BN_bn2mpi (this, NULL);
Blob vch (nSize);
nSize -= 4;
BN_bn2mpi (this, &vch[0]);
unsigned int nCompact = nSize << 24;
if (nSize >= 1) nCompact |= (vch[4] << 16);
if (nSize >= 2) nCompact |= (vch[5] << 8);
if (nSize >= 3) nCompact |= (vch[6] << 0);
return nCompact;
}
void CBigNum::SetHex(const std::string& str)
void CBigNum::SetHex (const std::string& str)
{
// skip 0x
const char* psz = str.c_str();
while (isspace(*psz))
psz++;
bool fNegative = false;
if (*psz == '-')
{
fNegative = true;
psz++;
}
if (psz[0] == '0' && tolower(psz[1]) == 'x')
psz += 2;
while (isspace(*psz))
psz++;
// skip 0x
const char* psz = str.c_str ();
// hex string to bignum
static char phexdigit[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,
0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
*this = 0;
while (isxdigit(*psz))
{
*this <<= 4;
int n = phexdigit[(int) *psz++];
*this += n;
}
if (fNegative)
*this = 0 - *this;
while (isspace (*psz))
psz++;
bool fNegative = false;
if (*psz == '-')
{
fNegative = true;
psz++;
}
if (psz[0] == '0' && tolower (psz[1]) == 'x')
psz += 2;
while (isspace (*psz))
psz++;
// hex string to bignum
static char phexdigit[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
*this = 0;
while (isxdigit (*psz))
{
*this <<= 4;
int n = phexdigit[ (int) * psz++];
*this += n;
}
if (fNegative)
*this = 0 - *this;
}
std::string CBigNum::ToString(int nBase) const
std::string CBigNum::ToString (int nBase) const
{
CAutoBN_CTX pctx;
CBigNum bnBase = nBase;
CBigNum bn0 = 0;
std::string str;
CBigNum bn = *this;
BN_set_negative(&bn, false);
CBigNum dv;
CBigNum rem;
if (BN_cmp(&bn, &bn0) == 0)
return "0";
while (BN_cmp(&bn, &bn0) > 0)
{
if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
throw bignum_error("CBigNum::ToString() : BN_div failed");
bn = dv;
unsigned int c = rem.getuint();
str += "0123456789abcdef"[c];
}
if (BN_is_negative(this))
str += "-";
reverse(str.begin(), str.end());
return str;
CAutoBN_CTX pctx;
CBigNum bnBase = nBase;
CBigNum bn0 = 0;
std::string str;
CBigNum bn = *this;
BN_set_negative (&bn, false);
CBigNum dv;
CBigNum rem;
if (BN_cmp (&bn, &bn0) == 0)
return "0";
while (BN_cmp (&bn, &bn0) > 0)
{
if (!BN_div (&dv, &rem, &bn, &bnBase, pctx))
throw bignum_error ("CBigNum::ToString() : BN_div failed");
bn = dv;
unsigned int c = rem.getuint ();
str += "0123456789abcdef"[c];
}
if (BN_is_negative (this))
str += "-";
reverse (str.begin (), str.end ());
return str;
}
std::string CBigNum::GetHex() const
std::string CBigNum::GetHex () const
{
return ToString(16);
return ToString (16);
}
bool CBigNum::operator!() const
bool CBigNum::operator! () const
{
return BN_is_zero(this);
return BN_is_zero (this);
}
CBigNum& CBigNum::operator+=(const CBigNum& b)
CBigNum& CBigNum::operator+= (const CBigNum& b)
{
if (!BN_add(this, this, &b))
throw bignum_error("CBigNum::operator+= : BN_add failed");
return *this;
if (!BN_add (this, this, &b))
throw bignum_error ("CBigNum::operator+= : BN_add failed");
return *this;
}
CBigNum& CBigNum::operator-=(const CBigNum& b)
CBigNum& CBigNum::operator-= (const CBigNum& b)
{
*this = *this - b;
return *this;
*this = *this - b;
return *this;
}
CBigNum& CBigNum::operator*=(const CBigNum& b)
CBigNum& CBigNum::operator*= (const CBigNum& b)
{
CAutoBN_CTX pctx;
if (!BN_mul(this, this, &b, pctx))
throw bignum_error("CBigNum::operator*= : BN_mul failed");
return *this;
CAutoBN_CTX pctx;
if (!BN_mul (this, this, &b, pctx))
throw bignum_error ("CBigNum::operator*= : BN_mul failed");
return *this;
}
CBigNum& CBigNum::operator/=(const CBigNum& b)
CBigNum& CBigNum::operator/= (const CBigNum& b)
{
*this = *this / b;
return *this;
*this = *this / b;
return *this;
}
CBigNum& CBigNum::operator%=(const CBigNum& b)
CBigNum& CBigNum::operator%= (const CBigNum& b)
{
*this = *this % b;
return *this;
*this = *this % b;
return *this;
}
CBigNum& CBigNum::operator<<=(unsigned int shift)
CBigNum& CBigNum::operator<<= (unsigned int shift)
{
if (!BN_lshift(this, this, shift))
throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
return *this;
if (!BN_lshift (this, this, shift))
throw bignum_error ("CBigNum:operator<<= : BN_lshift failed");
return *this;
}
CBigNum& CBigNum::operator>>=(unsigned int shift)
CBigNum& CBigNum::operator>>= (unsigned int shift)
{
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
// if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
CBigNum a = 1;
a <<= shift;
if (BN_cmp(&a, this) > 0)
{
*this = 0;
return *this;
}
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
// if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
CBigNum a = 1;
a <<= shift;
if (!BN_rshift(this, this, shift))
throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
return *this;
if (BN_cmp (&a, this) > 0)
{
*this = 0;
return *this;
}
if (!BN_rshift (this, this, shift))
throw bignum_error ("CBigNum:operator>>= : BN_rshift failed");
return *this;
}
CBigNum& CBigNum::operator++()
CBigNum& CBigNum::operator++ ()
{
// prefix operator
if (!BN_add(this, this, BN_value_one()))
throw bignum_error("CBigNum::operator++ : BN_add failed");
return *this;
// prefix operator
if (!BN_add (this, this, BN_value_one ()))
throw bignum_error ("CBigNum::operator++ : BN_add failed");
return *this;
}
const CBigNum CBigNum::operator++(int)
const CBigNum CBigNum::operator++ (int)
{
// postfix operator
const CBigNum ret = *this;
++(*this);
return ret;
// postfix operator
const CBigNum ret = *this;
++ (*this);
return ret;
}
CBigNum& CBigNum::operator--()
CBigNum& CBigNum::operator-- ()
{
// prefix operator
CBigNum r;
if (!BN_sub(&r, this, BN_value_one()))
throw bignum_error("CBigNum::operator-- : BN_sub failed");
*this = r;
return *this;
// prefix operator
CBigNum r;
if (!BN_sub (&r, this, BN_value_one ()))
throw bignum_error ("CBigNum::operator-- : BN_sub failed");
*this = r;
return *this;
}
const CBigNum CBigNum::operator--(int)
const CBigNum CBigNum::operator-- (int)
{
// postfix operator
const CBigNum ret = *this;
--(*this);
return ret;
// postfix operator
const CBigNum ret = *this;
-- (*this);
return ret;
}
void CBigNum::setulong(unsigned long n)
void CBigNum::setulong (unsigned long n)
{
if (!BN_set_word(this, n))
throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
if (!BN_set_word (this, n))
throw bignum_error ("CBigNum conversion from unsigned long : BN_set_word failed");
}
unsigned long CBigNum::getulong() const
unsigned long CBigNum::getulong () const
{
return BN_get_word(this);
return BN_get_word (this);
}
const CBigNum operator+(const CBigNum& a, const CBigNum& b)
const CBigNum operator+ (const CBigNum& a, const CBigNum& b)
{
CBigNum r;
if (!BN_add(&r, &a, &b))
throw bignum_error("CBigNum::operator+ : BN_add failed");
return r;
CBigNum r;
if (!BN_add (&r, &a, &b))
throw bignum_error ("CBigNum::operator+ : BN_add failed");
return r;
}
const CBigNum operator-(const CBigNum& a, const CBigNum& b)
const CBigNum operator- (const CBigNum& a, const CBigNum& b)
{
CBigNum r;
if (!BN_sub(&r, &a, &b))
throw bignum_error("CBigNum::operator- : BN_sub failed");
return r;
CBigNum r;
if (!BN_sub (&r, &a, &b))
throw bignum_error ("CBigNum::operator- : BN_sub failed");
return r;
}
const CBigNum operator-(const CBigNum& a)
const CBigNum operator- (const CBigNum& a)
{
CBigNum r(a);
BN_set_negative(&r, !BN_is_negative(&r));
return r;
CBigNum r (a);
BN_set_negative (&r, !BN_is_negative (&r));
return r;
}
const CBigNum operator*(const CBigNum& a, const CBigNum& b)
const CBigNum operator* (const CBigNum& a, const CBigNum& b)
{
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_mul(&r, &a, &b, pctx))
throw bignum_error("CBigNum::operator* : BN_mul failed");
return r;
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_mul (&r, &a, &b, pctx))
throw bignum_error ("CBigNum::operator* : BN_mul failed");
return r;
}
const CBigNum operator/(const CBigNum& a, const CBigNum& b)
const CBigNum operator/ (const CBigNum& a, const CBigNum& b)
{
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_div(&r, NULL, &a, &b, pctx))
throw bignum_error("CBigNum::operator/ : BN_div failed");
return r;
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_div (&r, NULL, &a, &b, pctx))
throw bignum_error ("CBigNum::operator/ : BN_div failed");
return r;
}
const CBigNum operator%(const CBigNum& a, const CBigNum& b)
const CBigNum operator% (const CBigNum& a, const CBigNum& b)
{
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_mod(&r, &a, &b, pctx))
throw bignum_error("CBigNum::operator% : BN_div failed");
return r;
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_mod (&r, &a, &b, pctx))
throw bignum_error ("CBigNum::operator% : BN_div failed");
return r;
}
const CBigNum operator<<(const CBigNum& a, unsigned int shift)
const CBigNum operator<< (const CBigNum& a, unsigned int shift)
{
CBigNum r;
if (!BN_lshift(&r, &a, shift))
throw bignum_error("CBigNum:operator<< : BN_lshift failed");
return r;
CBigNum r;
if (!BN_lshift (&r, &a, shift))
throw bignum_error ("CBigNum:operator<< : BN_lshift failed");
return r;
}
const CBigNum operator>>(const CBigNum& a, unsigned int shift)
const CBigNum operator>> (const CBigNum& a, unsigned int shift)
{
CBigNum r = a;
r >>= shift;
return r;
CBigNum r = a;
r >>= shift;
return r;
}
bool operator== (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) == 0);
return (BN_cmp (&a, &b) == 0);
}
bool operator!= (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) != 0);
return (BN_cmp (&a, &b) != 0);
}
bool operator<= (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) <= 0);
return (BN_cmp (&a, &b) <= 0);
}
bool operator>= (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) >= 0);
return (BN_cmp (&a, &b) >= 0);
}
bool operator< (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) < 0);
return (BN_cmp (&a, &b) < 0);
}
bool operator> (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) > 0);
return (BN_cmp (&a, &b) > 0);
}
#if (ULONG_MAX > UINT_MAX)
int BN_add_word64 (BIGNUM* bn, uint64 word)
{
return BN_add_word(bn, word);
return BN_add_word (bn, word);
}
int BN_sub_word64 (BIGNUM* bn, uint64 word)
{
return BN_sub_word(bn, word);
return BN_sub_word (bn, word);
}
int BN_mul_word64 (BIGNUM* bn, uint64 word)
{
return BN_mul_word(bn, word);
return BN_mul_word (bn, word);
}
uint64 BN_div_word64 (BIGNUM* bn, uint64 word)
{
return BN_div_word(bn, word);
return BN_div_word (bn, word);
}
#else
int BN_add_word64 (BIGNUM *a, uint64 w)
int BN_add_word64 (BIGNUM* a, uint64 w)
{
CBigNum bn(w);
return BN_add(a, &bn, a);
CBigNum bn (w);
return BN_add (a, &bn, a);
}
int BN_sub_word64 (BIGNUM *a, uint64 w)
int BN_sub_word64 (BIGNUM* a, uint64 w)
{
CBigNum bn(w);
return BN_sub(a, &bn, a);
CBigNum bn (w);
return BN_sub (a, &bn, a);
}
int BN_mul_word64 (BIGNUM *a, uint64 w)
int BN_mul_word64 (BIGNUM* a, uint64 w)
{
CBigNum bn(w);
CAutoBN_CTX ctx;
return BN_mul(a, &bn, a, ctx);
CBigNum bn (w);
CAutoBN_CTX ctx;
return BN_mul (a, &bn, a, ctx);
}
uint64 BN_div_word64 (BIGNUM *a, uint64 w)
uint64 BN_div_word64 (BIGNUM* a, uint64 w)
{
CBigNum bn(w);
CAutoBN_CTX ctx;
return (BN_div(a, NULL, a, &bn, ctx) == 1) ? 0 : ((uint64)-1);
CBigNum bn (w);
CAutoBN_CTX ctx;
return (BN_div (a, NULL, a, &bn, ctx) == 1) ? 0 : ((uint64) - 1);
}
#endif

View File

@@ -14,7 +14,7 @@
class bignum_error : public std::runtime_error
{
public:
explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
explicit bignum_error (const std::string& str) : std::runtime_error (str) {}
};
//------------------------------------------------------------------------------
@@ -22,111 +22,128 @@ public:
class CAutoBN_CTX
{
private:
CAutoBN_CTX(const CAutoBN_CTX&); // no implementation
CAutoBN_CTX& operator=(const CAutoBN_CTX&); // no implementation
CAutoBN_CTX (const CAutoBN_CTX&); // no implementation
CAutoBN_CTX& operator= (const CAutoBN_CTX&); // no implementation
protected:
BN_CTX* pctx;
CAutoBN_CTX& operator=(BN_CTX* pnew) { pctx = pnew; return *this; }
BN_CTX* pctx;
CAutoBN_CTX& operator= (BN_CTX* pnew)
{
pctx = pnew;
return *this;
}
public:
CAutoBN_CTX()
{
pctx = BN_CTX_new();
if (pctx == NULL)
throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
}
CAutoBN_CTX ()
{
pctx = BN_CTX_new ();
~CAutoBN_CTX()
{
if (pctx != NULL)
BN_CTX_free(pctx);
}
if (pctx == NULL)
throw bignum_error ("CAutoBN_CTX : BN_CTX_new() returned NULL");
}
operator BN_CTX*() { return pctx; }
BN_CTX& operator*() { return *pctx; }
BN_CTX** operator&() { return &pctx; }
bool operator!() { return (pctx == NULL); }
~CAutoBN_CTX ()
{
if (pctx != NULL)
BN_CTX_free (pctx);
}
operator BN_CTX* ()
{
return pctx;
}
BN_CTX& operator* ()
{
return *pctx;
}
BN_CTX** operator& ()
{
return &pctx;
}
bool operator! ()
{
return (pctx == NULL);
}
};
//------------------------------------------------------------------------------
// VFALCO TODO figure out a way to remove the dependency on openssl in the
// header. Maybe rewrite this to use cryptopp.
// header. Maybe rewrite this to use cryptopp.
class CBigNum : public BIGNUM
{
public:
CBigNum();
CBigNum(const CBigNum& b);
CBigNum& operator=(const CBigNum& b);
CBigNum(char n);
CBigNum(short n);
CBigNum(int n);
CBigNum(long n);
CBigNum(int64 n);
CBigNum(unsigned char n);
CBigNum(unsigned short n);
CBigNum(unsigned int n);
CBigNum(uint64 n);
explicit CBigNum(uint256 n);
explicit CBigNum(Blob const& vch);
~CBigNum();
CBigNum ();
CBigNum (const CBigNum& b);
CBigNum& operator= (const CBigNum& b);
CBigNum (char n);
CBigNum (short n);
CBigNum (int n);
CBigNum (long n);
CBigNum (int64 n);
CBigNum (unsigned char n);
CBigNum (unsigned short n);
CBigNum (unsigned int n);
CBigNum (uint64 n);
explicit CBigNum (uint256 n);
explicit CBigNum (Blob const& vch);
~CBigNum ();
void setuint(unsigned int n);
unsigned int getuint() const;
int getint() const;
void setint64(int64 n);
uint64 getuint64() const;
void setuint64(uint64 n);
void setuint256(uint256 const& n);
uint256 getuint256();
void setvch(Blob const& vch);
Blob getvch() const;
CBigNum& SetCompact(unsigned int nCompact);
unsigned int GetCompact() const;
void SetHex(const std::string& str);
std::string ToString(int nBase=10) const;
std::string GetHex() const;
bool operator!() const;
CBigNum& operator+=(const CBigNum& b);
CBigNum& operator-=(const CBigNum& b);
CBigNum& operator*=(const CBigNum& b);
CBigNum& operator/=(const CBigNum& b);
CBigNum& operator%=(const CBigNum& b);
CBigNum& operator<<=(unsigned int shift);
CBigNum& operator>>=(unsigned int shift);
CBigNum& operator++();
CBigNum& operator--();
const CBigNum operator++(int);
const CBigNum operator--(int);
void setuint (unsigned int n);
unsigned int getuint () const;
int getint () const;
void setint64 (int64 n);
uint64 getuint64 () const;
void setuint64 (uint64 n);
void setuint256 (uint256 const& n);
uint256 getuint256 ();
void setvch (Blob const& vch);
Blob getvch () const;
CBigNum& SetCompact (unsigned int nCompact);
unsigned int GetCompact () const;
void SetHex (const std::string& str);
std::string ToString (int nBase = 10) const;
std::string GetHex () const;
bool operator! () const;
CBigNum& operator+= (const CBigNum& b);
CBigNum& operator-= (const CBigNum& b);
CBigNum& operator*= (const CBigNum& b);
CBigNum& operator/= (const CBigNum& b);
CBigNum& operator%= (const CBigNum& b);
CBigNum& operator<<= (unsigned int shift);
CBigNum& operator>>= (unsigned int shift);
CBigNum& operator++ ();
CBigNum& operator-- ();
const CBigNum operator++ (int);
const CBigNum operator-- (int);
friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator- (const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator/ (const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator% (const CBigNum& a, const CBigNum& b);
private:
// private because the size of an unsigned long varies by platform
// private because the size of an unsigned long varies by platform
void setulong(unsigned long n);
unsigned long getulong() const;
void setulong (unsigned long n);
unsigned long getulong () const;
};
const CBigNum operator+(const CBigNum& a, const CBigNum& b);
const CBigNum operator-(const CBigNum& a, const CBigNum& b);
const CBigNum operator-(const CBigNum& a);
const CBigNum operator*(const CBigNum& a, const CBigNum& b);
const CBigNum operator/(const CBigNum& a, const CBigNum& b);
const CBigNum operator%(const CBigNum& a, const CBigNum& b);
const CBigNum operator<<(const CBigNum& a, unsigned int shift);
const CBigNum operator>>(const CBigNum& a, unsigned int shift);
const CBigNum operator+ (const CBigNum& a, const CBigNum& b);
const CBigNum operator- (const CBigNum& a, const CBigNum& b);
const CBigNum operator- (const CBigNum& a);
const CBigNum operator* (const CBigNum& a, const CBigNum& b);
const CBigNum operator/ (const CBigNum& a, const CBigNum& b);
const CBigNum operator% (const CBigNum& a, const CBigNum& b);
const CBigNum operator<< (const CBigNum& a, unsigned int shift);
const CBigNum operator>> (const CBigNum& a, unsigned int shift);
bool operator==(const CBigNum& a, const CBigNum& b);
bool operator!=(const CBigNum& a, const CBigNum& b);
bool operator<=(const CBigNum& a, const CBigNum& b);
bool operator>=(const CBigNum& a, const CBigNum& b);
bool operator<(const CBigNum& a, const CBigNum& b);
bool operator>(const CBigNum& a, const CBigNum& b);
bool operator== (const CBigNum& a, const CBigNum& b);
bool operator!= (const CBigNum& a, const CBigNum& b);
bool operator<= (const CBigNum& a, const CBigNum& b);
bool operator>= (const CBigNum& a, const CBigNum& b);
bool operator< (const CBigNum& a, const CBigNum& b);
bool operator> (const CBigNum& a, const CBigNum& b);
//------------------------------------------------------------------------------
@@ -141,10 +158,10 @@ bool operator>(const CBigNum& a, const CBigNum& b);
//#endif
// VFALCO I believe only STAmount uses these
extern int BN_add_word64 (BIGNUM *a, uint64 w);
extern int BN_sub_word64 (BIGNUM *a, uint64 w);
extern int BN_mul_word64 (BIGNUM *a, uint64 w);
extern uint64 BN_div_word64 (BIGNUM *a, uint64 w);
extern int BN_add_word64 (BIGNUM* a, uint64 w);
extern int BN_sub_word64 (BIGNUM* a, uint64 w);
extern int BN_mul_word64 (BIGNUM* a, uint64 w);
extern uint64 BN_div_word64 (BIGNUM* a, uint64 w);
#endif

View File

@@ -1,18 +1,18 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
@@ -36,261 +36,280 @@
/*
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;
int okay = 0;
BN_CTX *ctx = NULL;
EC_POINT *pub_key = NULL;
if (!eckey) return 0;
if (!eckey) return 0;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL)
goto err;
if ((ctx = BN_CTX_new()) == NULL)
goto err;
pub_key = EC_POINT_new(group);
pub_key = EC_POINT_new(group);
if (pub_key == NULL)
goto err;
if (pub_key == NULL)
goto err;
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
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);
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;
okay = 1;
err:
if (pub_key)
EC_POINT_free(pub_key);
if (ctx != NULL)
BN_CTX_free(ctx);
if (pub_key)
EC_POINT_free(pub_key);
if (ctx != NULL)
BN_CTX_free(ctx);
return (okay);
return (okay);
}
*/
class key_error : public std::runtime_error
{
public:
explicit key_error(const std::string& str) : std::runtime_error(str) {}
explicit key_error (const std::string& str) : std::runtime_error (str) {}
};
class CKey
{
protected:
EC_KEY* pkey;
bool fSet;
EC_KEY* pkey;
bool fSet;
public:
typedef boost::shared_ptr<CKey> pointer;
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 ()
{
pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
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;
}
if (pkey == NULL)
throw key_error ("CKey::CKey() : EC_KEY_new_by_curve_name failed");
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);
}
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);
}
~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);
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 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& 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 (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);
}
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;
}
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;
}
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;
}
void MakeNewKey ()
{
if (!EC_KEY_generate_key (pkey))
throw key_error ("CKey::MakeNewKey() : EC_KEY_generate_key failed");
// XXX Still used!
BIGNUM* GetSecretBN() const
{ // DEPRECATED
return BN_dup(EC_KEY_get0_private_key(pkey));
}
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
fSet = true;
}
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)));
}
// XXX Still used!
BIGNUM* GetSecretBN () const
{
// DEPRECATED
return BN_dup (EC_KEY_get0_private_key (pkey));
}
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);
void GetPrivateKeyU (uint256& privKey)
{
const BIGNUM* bn = EC_KEY_get0_private_key (pkey);
BN_clear_free(bn);
if (bn == NULL)
throw key_error ("CKey::GetPrivateKeyU: EC_KEY_get0_private_key failed");
if (bSuccess)
{
fSet = true;
}
else if (bThrow)
{
throw key_error("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
}
privKey.zero ();
BN_bn2bin (bn, privKey.begin () + (privKey.size () - BN_num_bytes (bn)));
}
return bSuccess;
}
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);
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;
}
BN_clear_free (bn);
bool SetPubKey(Blob const& vchPubKey)
{
return SetPubKey(&vchPubKey[0], vchPubKey.size());
}
if (bSuccess)
{
fSet = true;
}
else if (bThrow)
{
throw key_error ("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
}
bool SetPubKey(const std::string& pubKey)
{
return SetPubKey(pubKey.data(), pubKey.size());
}
return bSuccess;
}
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 SetPubKey (const void* ptr, size_t len)
{
const unsigned char* pbegin = static_cast<const unsigned char*> (ptr);
bool Sign(uint256 const& hash, Blob& vchSig)
{
unsigned char pchSig[10000];
unsigned int nSize = 0;
if (!o2i_ECPublicKey (&pkey, &pbegin, len))
return false;
vchSig.clear();
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
fSet = true;
return true;
}
if (!ECDSA_sign(0, (unsigned char*)hash.begin(), hash.size(), pchSig, &nSize, pkey))
return false;
bool SetPubKey (Blob const& vchPubKey)
{
return SetPubKey (&vchPubKey[0], vchPubKey.size ());
}
vchSig.resize(nSize);
memcpy(&vchSig[0], pchSig, nSize);
bool SetPubKey (const std::string& pubKey)
{
return SetPubKey (pubKey.data (), pubKey.size ());
}
return true;
}
Blob GetPubKey () const
{
unsigned int nSize = i2o_ECPublicKey (pkey, NULL);
assert (nSize <= 33);
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;
}
if (!nSize)
throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey failed");
bool Verify(uint256 const& hash, Blob const& vchSig) const
{
return Verify(hash, &vchSig[0], vchSig.size());
}
Blob vchPubKey (33, 0);
unsigned char* pbegin = &vchPubKey[0];
bool Verify(uint256 const& hash, const std::string& sig) const
{
return Verify(hash, sig.data(), sig.size());
}
if (i2o_ECPublicKey (pkey, &pbegin) != nSize)
throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
// ECIES functions. These throw on failure
assert (vchPubKey.size () <= 33);
return vchPubKey;
}
// 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);
bool Sign (uint256 const& hash, Blob& vchSig)
{
unsigned char pchSig[10000];
unsigned int nSize = 0;
// 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);
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

View File

@@ -4,328 +4,375 @@
// Functions to add CKey support for deterministic EC keys
// <-- seed
uint128 CKey::PassPhraseToKey(const std::string& passPhrase)
uint128 CKey::PassPhraseToKey (const std::string& passPhrase)
{
Serializer s;
Serializer s;
s.addRaw(passPhrase);
uint256 hash256 = s.getSHA512Half();
uint128 ret(hash256);
s.addRaw (passPhrase);
uint256 hash256 = s.getSHA512Half ();
uint128 ret (hash256);
s.secureErase();
s.secureErase ();
return ret;
return ret;
}
// --> seed
// <-- private root generator + public root generator
EC_KEY* CKey::GenerateRootDeterministicKey(const uint128& seed)
EC_KEY* CKey::GenerateRootDeterministicKey (const uint128& seed)
{
BN_CTX* ctx=BN_CTX_new();
if(!ctx) return NULL;
BN_CTX* ctx = BN_CTX_new ();
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
if(!pkey)
{
BN_CTX_free(ctx);
return NULL;
}
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
if (!ctx) return NULL;
BIGNUM* order=BN_new();
if(!order)
{
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
}
if(!EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx))
{
assert(false);
BN_free(order);
EC_KEY_free(pkey);
BN_CTX_free(ctx);
return NULL;
}
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
BIGNUM *privKey=NULL;
int seq=0;
do
{ // private key must be non-zero and less than the curve's order
Serializer s((128+32)/8);
s.add128(seed);
s.add32(seq++);
uint256 root=s.getSHA512Half();
s.secureErase();
privKey=BN_bin2bn((const unsigned char *) &root, sizeof(root), privKey);
if(privKey==NULL)
{
EC_KEY_free(pkey);
BN_free(order);
BN_CTX_free(ctx);
}
root.zero();
} while(BN_is_zero(privKey) || (BN_cmp(privKey, order)>=0));
if (!pkey)
{
BN_CTX_free (ctx);
return NULL;
}
BN_free(order);
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
if(!EC_KEY_set_private_key(pkey, privKey))
{ // set the random point as the private key
assert(false);
EC_KEY_free(pkey);
BN_clear_free(privKey);
BN_CTX_free(ctx);
return NULL;
}
BIGNUM* order = BN_new ();
EC_POINT *pubKey=EC_POINT_new(EC_KEY_get0_group(pkey));
if(!EC_POINT_mul(EC_KEY_get0_group(pkey), pubKey, privKey, NULL, NULL, ctx))
{ // compute the corresponding public key point
assert(false);
BN_clear_free(privKey);
EC_POINT_free(pubKey);
EC_KEY_free(pkey);
BN_CTX_free(ctx);
return NULL;
}
BN_clear_free(privKey);
if(!EC_KEY_set_public_key(pkey, pubKey))
{
assert(false);
EC_POINT_free(pubKey);
EC_KEY_free(pkey);
BN_CTX_free(ctx);
return NULL;
}
EC_POINT_free(pubKey);
if (!order)
{
BN_CTX_free (ctx);
EC_KEY_free (pkey);
return NULL;
}
BN_CTX_free(ctx);
if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
{
assert (false);
BN_free (order);
EC_KEY_free (pkey);
BN_CTX_free (ctx);
return NULL;
}
BIGNUM* privKey = NULL;
int seq = 0;
do
{
// private key must be non-zero and less than the curve's order
Serializer s ((128 + 32) / 8);
s.add128 (seed);
s.add32 (seq++);
uint256 root = s.getSHA512Half ();
s.secureErase ();
privKey = BN_bin2bn ((const unsigned char*) &root, sizeof (root), privKey);
if (privKey == NULL)
{
EC_KEY_free (pkey);
BN_free (order);
BN_CTX_free (ctx);
}
root.zero ();
}
while (BN_is_zero (privKey) || (BN_cmp (privKey, order) >= 0));
BN_free (order);
if (!EC_KEY_set_private_key (pkey, privKey))
{
// set the random point as the private key
assert (false);
EC_KEY_free (pkey);
BN_clear_free (privKey);
BN_CTX_free (ctx);
return NULL;
}
EC_POINT* pubKey = EC_POINT_new (EC_KEY_get0_group (pkey));
if (!EC_POINT_mul (EC_KEY_get0_group (pkey), pubKey, privKey, NULL, NULL, ctx))
{
// compute the corresponding public key point
assert (false);
BN_clear_free (privKey);
EC_POINT_free (pubKey);
EC_KEY_free (pkey);
BN_CTX_free (ctx);
return NULL;
}
BN_clear_free (privKey);
if (!EC_KEY_set_public_key (pkey, pubKey))
{
assert (false);
EC_POINT_free (pubKey);
EC_KEY_free (pkey);
BN_CTX_free (ctx);
return NULL;
}
EC_POINT_free (pubKey);
BN_CTX_free (ctx);
#ifdef EC_DEBUG
assert(EC_KEY_check_key(pkey)==1); // CAUTION: This check is *very* expensive
assert (EC_KEY_check_key (pkey) == 1); // CAUTION: This check is *very* expensive
#endif
return pkey;
return pkey;
}
// Take ripple address.
// --> root public generator (consumes)
// <-- root public generator in EC format
EC_KEY* CKey::GenerateRootPubKey(BIGNUM* pubGenerator)
EC_KEY* CKey::GenerateRootPubKey (BIGNUM* pubGenerator)
{
if (pubGenerator == NULL)
{
assert(false);
return NULL;
}
if (pubGenerator == NULL)
{
assert (false);
return NULL;
}
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
if (!pkey)
{
BN_free(pubGenerator);
return NULL;
}
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
EC_POINT* pubPoint = EC_POINT_bn2point(EC_KEY_get0_group(pkey), pubGenerator, NULL, NULL);
BN_free(pubGenerator);
if(!pubPoint)
{
assert(false);
EC_KEY_free(pkey);
return NULL;
}
if (!pkey)
{
BN_free (pubGenerator);
return NULL;
}
if(!EC_KEY_set_public_key(pkey, pubPoint))
{
assert(false);
EC_POINT_free(pubPoint);
EC_KEY_free(pkey);
return NULL;
}
EC_POINT_free(pubPoint);
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
return pkey;
EC_POINT* pubPoint = EC_POINT_bn2point (EC_KEY_get0_group (pkey), pubGenerator, NULL, NULL);
BN_free (pubGenerator);
if (!pubPoint)
{
assert (false);
EC_KEY_free (pkey);
return NULL;
}
if (!EC_KEY_set_public_key (pkey, pubPoint))
{
assert (false);
EC_POINT_free (pubPoint);
EC_KEY_free (pkey);
return NULL;
}
EC_POINT_free (pubPoint);
return pkey;
}
// --> public generator
static BIGNUM* makeHash(const RippleAddress& pubGen, int seq, BIGNUM* order)
static BIGNUM* makeHash (const RippleAddress& pubGen, int seq, BIGNUM* order)
{
int subSeq=0;
BIGNUM* ret=NULL;
do
{
Serializer s((33*8+32+32)/8);
s.addRaw(pubGen.getGenerator());
s.add32(seq);
s.add32(subSeq++);
uint256 root=s.getSHA512Half();
s.secureErase();
ret=BN_bin2bn((const unsigned char *) &root, sizeof(root), ret);
if(!ret) return NULL;
} while (BN_is_zero(ret) || (BN_cmp(ret, order)>=0));
int subSeq = 0;
BIGNUM* ret = NULL;
return ret;
do
{
Serializer s ((33 * 8 + 32 + 32) / 8);
s.addRaw (pubGen.getGenerator ());
s.add32 (seq);
s.add32 (subSeq++);
uint256 root = s.getSHA512Half ();
s.secureErase ();
ret = BN_bin2bn ((const unsigned char*) &root, sizeof (root), ret);
if (!ret) return NULL;
}
while (BN_is_zero (ret) || (BN_cmp (ret, order) >= 0));
return ret;
}
// --> public generator
EC_KEY* CKey::GeneratePublicDeterministicKey(const RippleAddress& pubGen, int seq)
{ // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
EC_KEY* rootKey = CKey::GenerateRootPubKey(pubGen.getGeneratorBN());
const EC_POINT* rootPubKey = EC_KEY_get0_public_key(rootKey);
BN_CTX* ctx = BN_CTX_new();
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
EC_POINT* newPoint = 0;
BIGNUM* order = 0;
BIGNUM* hash = 0;
bool success = true;
EC_KEY* CKey::GeneratePublicDeterministicKey (const RippleAddress& pubGen, int seq)
{
// publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
EC_KEY* rootKey = CKey::GenerateRootPubKey (pubGen.getGeneratorBN ());
const EC_POINT* rootPubKey = EC_KEY_get0_public_key (rootKey);
BN_CTX* ctx = BN_CTX_new ();
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
EC_POINT* newPoint = 0;
BIGNUM* order = 0;
BIGNUM* hash = 0;
bool success = true;
if (!ctx || !pkey) success = false;
if (!ctx || !pkey) success = false;
if (success)
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
if (success)
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
if (success) {
newPoint = EC_POINT_new(EC_KEY_get0_group(pkey));
if(!newPoint) success = false;
}
if (success)
{
newPoint = EC_POINT_new (EC_KEY_get0_group (pkey));
if (success) {
order = BN_new();
if (!newPoint) success = false;
}
if(!order || !EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx))
success = false;
}
if (success)
{
order = BN_new ();
// Calculate the private additional key.
if (success) {
hash = makeHash(pubGen, seq, order);
if(!hash) success = false;
}
if (!order || !EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
success = false;
}
if (success) {
// Calculate the corresponding public key.
EC_POINT_mul(EC_KEY_get0_group(pkey), newPoint, hash, NULL, NULL, ctx);
// Calculate the private additional key.
if (success)
{
hash = makeHash (pubGen, seq, order);
// Add the master public key and set.
EC_POINT_add(EC_KEY_get0_group(pkey), newPoint, newPoint, rootPubKey, ctx);
EC_KEY_set_public_key(pkey, newPoint);
}
if (!hash) success = false;
}
if (order) BN_free(order);
if (hash) BN_free(hash);
if (newPoint) EC_POINT_free(newPoint);
if (ctx) BN_CTX_free(ctx);
if (rootKey) EC_KEY_free(rootKey);
if (pkey && !success) EC_KEY_free(pkey);
if (success)
{
// Calculate the corresponding public key.
EC_POINT_mul (EC_KEY_get0_group (pkey), newPoint, hash, NULL, NULL, ctx);
return success ? pkey : NULL;
// Add the master public key and set.
EC_POINT_add (EC_KEY_get0_group (pkey), newPoint, newPoint, rootPubKey, ctx);
EC_KEY_set_public_key (pkey, newPoint);
}
if (order) BN_free (order);
if (hash) BN_free (hash);
if (newPoint) EC_POINT_free (newPoint);
if (ctx) BN_CTX_free (ctx);
if (rootKey) EC_KEY_free (rootKey);
if (pkey && !success) EC_KEY_free (pkey);
return success ? pkey : NULL;
}
EC_KEY* CKey::GeneratePrivateDeterministicKey(const RippleAddress& pubGen, uint256 const& u, int seq)
EC_KEY* CKey::GeneratePrivateDeterministicKey (const RippleAddress& pubGen, uint256 const& u, int seq)
{
CBigNum bn(u);
return GeneratePrivateDeterministicKey(pubGen, static_cast<BIGNUM*>(&bn), seq);
CBigNum bn (u);
return GeneratePrivateDeterministicKey (pubGen, static_cast<BIGNUM*> (&bn), seq);
}
// --> root private key
EC_KEY* CKey::GeneratePrivateDeterministicKey(const RippleAddress& pubGen, const BIGNUM* rootPrivKey, int seq)
{ // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
BN_CTX* ctx=BN_CTX_new();
if(ctx==NULL) return NULL;
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
if(pkey==NULL)
{
BN_CTX_free(ctx);
return NULL;
}
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
BIGNUM* order=BN_new();
if(order==NULL)
{
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
}
if(!EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx))
{
BN_free(order);
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
}
// calculate the private additional key
BIGNUM* privKey=makeHash(pubGen, seq, order);
if(privKey==NULL)
{
BN_free(order);
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
}
// calculate the final private key
BN_mod_add(privKey, privKey, rootPrivKey, order, ctx);
BN_free(order);
EC_KEY_set_private_key(pkey, privKey);
// compute the corresponding public key
EC_POINT* pubKey=EC_POINT_new(EC_KEY_get0_group(pkey));
if(!pubKey)
{
BN_clear_free(privKey);
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
}
if(EC_POINT_mul(EC_KEY_get0_group(pkey), pubKey, privKey, NULL, NULL, ctx)==0)
{
BN_clear_free(privKey);
EC_POINT_free(pubKey);
EC_KEY_free(pkey);
BN_CTX_free(ctx);
return NULL;
}
BN_clear_free(privKey);
EC_KEY_set_public_key(pkey, pubKey);
EC_POINT_free(pubKey);
BN_CTX_free(ctx);
return pkey;
}
BOOST_AUTO_TEST_SUITE(DeterministicKeys_test)
BOOST_AUTO_TEST_CASE(DeterminsticKeys_test1)
EC_KEY* CKey::GeneratePrivateDeterministicKey (const RippleAddress& pubGen, const BIGNUM* rootPrivKey, int seq)
{
Log(lsDEBUG) << "Beginning deterministic key test";
// privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
BN_CTX* ctx = BN_CTX_new ();
uint128 seed1, seed2;
seed1.SetHex("71ED064155FFADFA38782C5E0158CB26");
seed2.SetHex("CF0C3BE4485961858C4198515AE5B965");
CKey root1(seed1), root2(seed2);
if (ctx == NULL) return NULL;
uint256 priv1, priv2;
root1.GetPrivateKeyU(priv1);
root2.GetPrivateKeyU(priv2);
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
if (priv1.GetHex() != "7CFBA64F771E93E817E15039215430B53F7401C34931D111EAB3510B22DBB0D8")
BOOST_FAIL("Incorrect private key for generator");
if (priv2.GetHex() != "98BC2EACB26EB021D1A6293C044D88BA2F0B6729A2772DEEBF2E21A263C1740B")
BOOST_FAIL("Incorrect private key for generator");
if (pkey == NULL)
{
BN_CTX_free (ctx);
return NULL;
}
RippleAddress nSeed;
nSeed.setSeed(seed1);
if (nSeed.humanSeed() != "shHM53KPZ87Gwdqarm1bAmPeXg8Tn")
BOOST_FAIL("Incorrect human seed");
if (nSeed.humanSeed1751() != "MAD BODY ACE MINT OKAY HUB WHAT DATA SACK FLAT DANA MATH")
BOOST_FAIL("Incorrect 1751 seed");
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
BIGNUM* order = BN_new ();
if (order == NULL)
{
BN_CTX_free (ctx);
EC_KEY_free (pkey);
return NULL;
}
if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
{
BN_free (order);
BN_CTX_free (ctx);
EC_KEY_free (pkey);
return NULL;
}
// calculate the private additional key
BIGNUM* privKey = makeHash (pubGen, seq, order);
if (privKey == NULL)
{
BN_free (order);
BN_CTX_free (ctx);
EC_KEY_free (pkey);
return NULL;
}
// calculate the final private key
BN_mod_add (privKey, privKey, rootPrivKey, order, ctx);
BN_free (order);
EC_KEY_set_private_key (pkey, privKey);
// compute the corresponding public key
EC_POINT* pubKey = EC_POINT_new (EC_KEY_get0_group (pkey));
if (!pubKey)
{
BN_clear_free (privKey);
BN_CTX_free (ctx);
EC_KEY_free (pkey);
return NULL;
}
if (EC_POINT_mul (EC_KEY_get0_group (pkey), pubKey, privKey, NULL, NULL, ctx) == 0)
{
BN_clear_free (privKey);
EC_POINT_free (pubKey);
EC_KEY_free (pkey);
BN_CTX_free (ctx);
return NULL;
}
BN_clear_free (privKey);
EC_KEY_set_public_key (pkey, pubKey);
EC_POINT_free (pubKey);
BN_CTX_free (ctx);
return pkey;
}
BOOST_AUTO_TEST_SUITE_END();
BOOST_AUTO_TEST_SUITE (DeterministicKeys_test)
BOOST_AUTO_TEST_CASE (DeterminsticKeys_test1)
{
Log (lsDEBUG) << "Beginning deterministic key test";
uint128 seed1, seed2;
seed1.SetHex ("71ED064155FFADFA38782C5E0158CB26");
seed2.SetHex ("CF0C3BE4485961858C4198515AE5B965");
CKey root1 (seed1), root2 (seed2);
uint256 priv1, priv2;
root1.GetPrivateKeyU (priv1);
root2.GetPrivateKeyU (priv2);
if (priv1.GetHex () != "7CFBA64F771E93E817E15039215430B53F7401C34931D111EAB3510B22DBB0D8")
BOOST_FAIL ("Incorrect private key for generator");
if (priv2.GetHex () != "98BC2EACB26EB021D1A6293C044D88BA2F0B6729A2772DEEBF2E21A263C1740B")
BOOST_FAIL ("Incorrect private key for generator");
RippleAddress nSeed;
nSeed.setSeed (seed1);
if (nSeed.humanSeed () != "shHM53KPZ87Gwdqarm1bAmPeXg8Tn")
BOOST_FAIL ("Incorrect human seed");
if (nSeed.humanSeed1751 () != "MAD BODY ACE MINT OKAY HUB WHAT DATA SACK FLAT DANA MATH")
BOOST_FAIL ("Incorrect 1751 seed");
}
BOOST_AUTO_TEST_SUITE_END ();
// vim:ts=4

View File

@@ -24,267 +24,288 @@
// key. They *must* be called in try/catch blocks.
// Algorithmic choices:
#define ECIES_KEY_HASH SHA512 // Hash used to expand shared secret
#define ECIES_KEY_LENGTH (512/8) // Size of expanded shared secret
#define ECIES_MIN_SEC (128/8) // The minimum equivalent security
#define ECIES_ENC_ALGO EVP_aes_256_cbc() // Encryption algorithm
#define ECIES_ENC_KEY_TYPE uint256 // Type used to hold shared secret
#define ECIES_ENC_KEY_SIZE (256/8) // Encryption key size
#define ECIES_ENC_BLK_SIZE (128/8) // Encryption block size
#define ECIES_ENC_IV_TYPE uint128 // Type used to hold IV
#define ECIES_HMAC_ALGO EVP_sha256() // HMAC algorithm
#define ECIES_HMAC_KEY_TYPE uint256 // Type used to hold HMAC key
#define ECIES_HMAC_KEY_SIZE (256/8) // Size of HMAC key
#define ECIES_HMAC_TYPE uint256 // Type used to hold HMAC value
#define ECIES_HMAC_SIZE (256/8) // Size of HMAC value
#define ECIES_KEY_HASH SHA512 // Hash used to expand shared secret
#define ECIES_KEY_LENGTH (512/8) // Size of expanded shared secret
#define ECIES_MIN_SEC (128/8) // The minimum equivalent security
#define ECIES_ENC_ALGO EVP_aes_256_cbc() // Encryption algorithm
#define ECIES_ENC_KEY_TYPE uint256 // Type used to hold shared secret
#define ECIES_ENC_KEY_SIZE (256/8) // Encryption key size
#define ECIES_ENC_BLK_SIZE (128/8) // Encryption block size
#define ECIES_ENC_IV_TYPE uint128 // Type used to hold IV
#define ECIES_HMAC_ALGO EVP_sha256() // HMAC algorithm
#define ECIES_HMAC_KEY_TYPE uint256 // Type used to hold HMAC key
#define ECIES_HMAC_KEY_SIZE (256/8) // Size of HMAC key
#define ECIES_HMAC_TYPE uint256 // Type used to hold HMAC value
#define ECIES_HMAC_SIZE (256/8) // Size of HMAC value
void CKey::getECIESSecret(CKey& otherKey, ECIES_ENC_KEY_TYPE& enc_key, ECIES_HMAC_KEY_TYPE& hmac_key)
{ // Retrieve a secret generated from an EC key pair. At least one private key must be known.
if (!pkey || !otherKey.pkey)
throw std::runtime_error("missing key");
void CKey::getECIESSecret (CKey& otherKey, ECIES_ENC_KEY_TYPE& enc_key, ECIES_HMAC_KEY_TYPE& hmac_key)
{
// Retrieve a secret generated from an EC key pair. At least one private key must be known.
if (!pkey || !otherKey.pkey)
throw std::runtime_error ("missing key");
EC_KEY *pubkey, *privkey;
if (EC_KEY_get0_private_key(pkey))
{
privkey = pkey;
pubkey = otherKey.pkey;
}
else if (EC_KEY_get0_private_key(otherKey.pkey))
{
privkey = otherKey.pkey;
pubkey = pkey;
}
else throw std::runtime_error("no private key");
EC_KEY* pubkey, *privkey;
unsigned char rawbuf[512];
int buflen = ECDH_compute_key(rawbuf, 512, EC_KEY_get0_public_key(pubkey), privkey, NULL);
if (buflen < ECIES_MIN_SEC)
throw std::runtime_error("ecdh key failed");
if (EC_KEY_get0_private_key (pkey))
{
privkey = pkey;
pubkey = otherKey.pkey;
}
else if (EC_KEY_get0_private_key (otherKey.pkey))
{
privkey = otherKey.pkey;
pubkey = pkey;
}
else throw std::runtime_error ("no private key");
unsigned char hbuf[ECIES_KEY_LENGTH];
ECIES_KEY_HASH(rawbuf, buflen, hbuf);
memset(rawbuf, 0, ECIES_HMAC_KEY_SIZE);
unsigned char rawbuf[512];
int buflen = ECDH_compute_key (rawbuf, 512, EC_KEY_get0_public_key (pubkey), privkey, NULL);
assert((ECIES_ENC_KEY_SIZE + ECIES_HMAC_KEY_SIZE) >= ECIES_KEY_LENGTH);
memcpy(enc_key.begin(), hbuf, ECIES_ENC_KEY_SIZE);
memcpy(hmac_key.begin(), hbuf + ECIES_ENC_KEY_SIZE, ECIES_HMAC_KEY_SIZE);
memset(hbuf, 0, ECIES_KEY_LENGTH);
if (buflen < ECIES_MIN_SEC)
throw std::runtime_error ("ecdh key failed");
unsigned char hbuf[ECIES_KEY_LENGTH];
ECIES_KEY_HASH (rawbuf, buflen, hbuf);
memset (rawbuf, 0, ECIES_HMAC_KEY_SIZE);
assert ((ECIES_ENC_KEY_SIZE + ECIES_HMAC_KEY_SIZE) >= ECIES_KEY_LENGTH);
memcpy (enc_key.begin (), hbuf, ECIES_ENC_KEY_SIZE);
memcpy (hmac_key.begin (), hbuf + ECIES_ENC_KEY_SIZE, ECIES_HMAC_KEY_SIZE);
memset (hbuf, 0, ECIES_KEY_LENGTH);
}
static ECIES_HMAC_TYPE makeHMAC(const ECIES_HMAC_KEY_TYPE& secret, Blob const& data)
static ECIES_HMAC_TYPE makeHMAC (const ECIES_HMAC_KEY_TYPE& secret, Blob const& data)
{
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
if (HMAC_Init_ex(&ctx, secret.begin(), ECIES_HMAC_KEY_SIZE, ECIES_HMAC_ALGO, NULL) != 1)
{
HMAC_CTX_cleanup(&ctx);
throw std::runtime_error("init hmac");
}
HMAC_CTX ctx;
HMAC_CTX_init (&ctx);
if (HMAC_Update(&ctx, &(data.front()), data.size()) != 1)
{
HMAC_CTX_cleanup(&ctx);
throw std::runtime_error("update hmac");
}
if (HMAC_Init_ex (&ctx, secret.begin (), ECIES_HMAC_KEY_SIZE, ECIES_HMAC_ALGO, NULL) != 1)
{
HMAC_CTX_cleanup (&ctx);
throw std::runtime_error ("init hmac");
}
ECIES_HMAC_TYPE ret;
unsigned int ml = ECIES_HMAC_SIZE;
if (HMAC_Final(&ctx, ret.begin(), &ml) != 1)
{
HMAC_CTX_cleanup(&ctx);
throw std::runtime_error("finalize hmac");
}
assert(ml == ECIES_HMAC_SIZE);
HMAC_CTX_cleanup(&ctx);
if (HMAC_Update (&ctx, & (data.front ()), data.size ()) != 1)
{
HMAC_CTX_cleanup (&ctx);
throw std::runtime_error ("update hmac");
}
return ret;
ECIES_HMAC_TYPE ret;
unsigned int ml = ECIES_HMAC_SIZE;
if (HMAC_Final (&ctx, ret.begin (), &ml) != 1)
{
HMAC_CTX_cleanup (&ctx);
throw std::runtime_error ("finalize hmac");
}
assert (ml == ECIES_HMAC_SIZE);
HMAC_CTX_cleanup (&ctx);
return ret;
}
Blob CKey::encryptECIES(CKey& otherKey, Blob const& plaintext)
Blob CKey::encryptECIES (CKey& otherKey, Blob const& plaintext)
{
ECIES_ENC_IV_TYPE iv;
RandomNumbers::getInstance ().fillBytes (iv.begin (), ECIES_ENC_BLK_SIZE);
ECIES_ENC_IV_TYPE iv;
RandomNumbers::getInstance ().fillBytes (iv.begin (), ECIES_ENC_BLK_SIZE);
ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey;
ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey;
getECIESSecret(otherKey, secret, hmacKey);
ECIES_HMAC_TYPE hmac = makeHMAC(hmacKey, plaintext);
hmacKey.zero();
getECIESSecret (otherKey, secret, hmacKey);
ECIES_HMAC_TYPE hmac = makeHMAC (hmacKey, plaintext);
hmacKey.zero ();
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init (&ctx);
if (EVP_EncryptInit_ex(&ctx, ECIES_ENC_ALGO, NULL, secret.begin(), iv.begin()) != 1)
{
EVP_CIPHER_CTX_cleanup(&ctx);
secret.zero();
throw std::runtime_error("init cipher ctx");
}
secret.zero();
if (EVP_EncryptInit_ex (&ctx, ECIES_ENC_ALGO, NULL, secret.begin (), iv.begin ()) != 1)
{
EVP_CIPHER_CTX_cleanup (&ctx);
secret.zero ();
throw std::runtime_error ("init cipher ctx");
}
Blob out(plaintext.size() + ECIES_HMAC_SIZE + ECIES_ENC_KEY_SIZE + ECIES_ENC_BLK_SIZE, 0);
int len = 0, bytesWritten;
secret.zero ();
// output IV
memcpy(&(out.front()), iv.begin(), ECIES_ENC_BLK_SIZE);
len = ECIES_ENC_BLK_SIZE;
Blob out (plaintext.size () + ECIES_HMAC_SIZE + ECIES_ENC_KEY_SIZE + ECIES_ENC_BLK_SIZE, 0);
int len = 0, bytesWritten;
// Encrypt/output HMAC
bytesWritten = out.capacity() - len;
assert(bytesWritten>0);
if (EVP_EncryptUpdate(&ctx, &(out.front()) + len, &bytesWritten, hmac.begin(), ECIES_HMAC_SIZE) < 0)
{
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("");
}
len += bytesWritten;
// output IV
memcpy (& (out.front ()), iv.begin (), ECIES_ENC_BLK_SIZE);
len = ECIES_ENC_BLK_SIZE;
// encrypt/output plaintext
bytesWritten = out.capacity() - len;
assert(bytesWritten>0);
if (EVP_EncryptUpdate(&ctx, &(out.front()) + len, &bytesWritten, &(plaintext.front()), plaintext.size()) < 0)
{
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("");
}
len += bytesWritten;
// Encrypt/output HMAC
bytesWritten = out.capacity () - len;
assert (bytesWritten > 0);
// finalize
bytesWritten = out.capacity() - len;
if (EVP_EncryptFinal_ex(&ctx, &(out.front()) + len, &bytesWritten) < 0)
{
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("encryption error");
}
len += bytesWritten;
if (EVP_EncryptUpdate (&ctx, & (out.front ()) + len, &bytesWritten, hmac.begin (), ECIES_HMAC_SIZE) < 0)
{
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("");
}
// Output contains: IV, encrypted HMAC, encrypted data, encrypted padding
assert(len <= (plaintext.size() + ECIES_HMAC_SIZE + (2 * ECIES_ENC_BLK_SIZE)));
assert(len >= (plaintext.size() + ECIES_HMAC_SIZE + ECIES_ENC_BLK_SIZE)); // IV, HMAC, data
out.resize(len);
EVP_CIPHER_CTX_cleanup(&ctx);
return out;
len += bytesWritten;
// encrypt/output plaintext
bytesWritten = out.capacity () - len;
assert (bytesWritten > 0);
if (EVP_EncryptUpdate (&ctx, & (out.front ()) + len, &bytesWritten, & (plaintext.front ()), plaintext.size ()) < 0)
{
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("");
}
len += bytesWritten;
// finalize
bytesWritten = out.capacity () - len;
if (EVP_EncryptFinal_ex (&ctx, & (out.front ()) + len, &bytesWritten) < 0)
{
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("encryption error");
}
len += bytesWritten;
// Output contains: IV, encrypted HMAC, encrypted data, encrypted padding
assert (len <= (plaintext.size () + ECIES_HMAC_SIZE + (2 * ECIES_ENC_BLK_SIZE)));
assert (len >= (plaintext.size () + ECIES_HMAC_SIZE + ECIES_ENC_BLK_SIZE)); // IV, HMAC, data
out.resize (len);
EVP_CIPHER_CTX_cleanup (&ctx);
return out;
}
Blob CKey::decryptECIES(CKey& otherKey, Blob const& ciphertext)
Blob CKey::decryptECIES (CKey& otherKey, Blob const& ciphertext)
{
// minimum ciphertext = IV + HMAC + 1 block
if (ciphertext.size() < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) )
throw std::runtime_error("ciphertext too short");
// minimum ciphertext = IV + HMAC + 1 block
if (ciphertext.size () < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) )
throw std::runtime_error ("ciphertext too short");
// extract IV
ECIES_ENC_IV_TYPE iv;
memcpy(iv.begin(), &(ciphertext.front()), ECIES_ENC_BLK_SIZE);
// extract IV
ECIES_ENC_IV_TYPE iv;
memcpy (iv.begin (), & (ciphertext.front ()), ECIES_ENC_BLK_SIZE);
// begin decrypting
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
// begin decrypting
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init (&ctx);
ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey;
getECIESSecret(otherKey, secret, hmacKey);
ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey;
getECIESSecret (otherKey, secret, hmacKey);
if (EVP_DecryptInit_ex(&ctx, ECIES_ENC_ALGO, NULL, secret.begin(), iv.begin()) != 1)
{
secret.zero();
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("unable to init cipher");
}
// decrypt mac
ECIES_HMAC_TYPE hmac;
int outlen = ECIES_HMAC_SIZE;
if ( (EVP_DecryptUpdate(&ctx, hmac.begin(), &outlen,
&(ciphertext.front()) + ECIES_ENC_BLK_SIZE, ECIES_HMAC_SIZE + 1) != 1) || (outlen != ECIES_HMAC_SIZE) )
{
secret.zero();
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("unable to extract hmac");
}
// decrypt plaintext (after IV and encrypted mac)
Blob plaintext(ciphertext.size() - ECIES_HMAC_SIZE - ECIES_ENC_BLK_SIZE);
outlen = plaintext.size();
if (EVP_DecryptUpdate(&ctx, &(plaintext.front()), &outlen,
&(ciphertext.front()) + ECIES_ENC_BLK_SIZE + ECIES_HMAC_SIZE + 1,
ciphertext.size() - ECIES_ENC_BLK_SIZE - ECIES_HMAC_SIZE - 1) != 1)
{
secret.zero();
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("unable to extract plaintext");
}
if (EVP_DecryptInit_ex (&ctx, ECIES_ENC_ALGO, NULL, secret.begin (), iv.begin ()) != 1)
{
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("unable to init cipher");
}
// decrypt padding
int flen = 0;
if (EVP_DecryptFinal(&ctx, &(plaintext.front()) + outlen, &flen) != 1)
{
secret.zero();
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("plaintext had bad padding");
}
plaintext.resize(flen + outlen);
// decrypt mac
ECIES_HMAC_TYPE hmac;
int outlen = ECIES_HMAC_SIZE;
// verify integrity
if (hmac != makeHMAC(hmacKey, plaintext))
{
secret.zero();
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("plaintext had bad hmac");
}
secret.zero();
hmacKey.zero();
if ( (EVP_DecryptUpdate (&ctx, hmac.begin (), &outlen,
& (ciphertext.front ()) + ECIES_ENC_BLK_SIZE, ECIES_HMAC_SIZE + 1) != 1) || (outlen != ECIES_HMAC_SIZE) )
{
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("unable to extract hmac");
}
EVP_CIPHER_CTX_cleanup(&ctx);
return plaintext;
// decrypt plaintext (after IV and encrypted mac)
Blob plaintext (ciphertext.size () - ECIES_HMAC_SIZE - ECIES_ENC_BLK_SIZE);
outlen = plaintext.size ();
if (EVP_DecryptUpdate (&ctx, & (plaintext.front ()), &outlen,
& (ciphertext.front ()) + ECIES_ENC_BLK_SIZE + ECIES_HMAC_SIZE + 1,
ciphertext.size () - ECIES_ENC_BLK_SIZE - ECIES_HMAC_SIZE - 1) != 1)
{
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("unable to extract plaintext");
}
// decrypt padding
int flen = 0;
if (EVP_DecryptFinal (&ctx, & (plaintext.front ()) + outlen, &flen) != 1)
{
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("plaintext had bad padding");
}
plaintext.resize (flen + outlen);
// verify integrity
if (hmac != makeHMAC (hmacKey, plaintext))
{
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("plaintext had bad hmac");
}
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
return plaintext;
}
bool checkECIES(void)
bool checkECIES (void)
{
CKey senderPriv, recipientPriv, senderPub, recipientPub;
CKey senderPriv, recipientPriv, senderPub, recipientPub;
for (int i = 0; i < 30000; ++i)
{
if ((i % 100) == 0)
{ // generate new keys every 100 times
// std::cerr << "new keys" << std::endl;
senderPriv.MakeNewKey();
recipientPriv.MakeNewKey();
for (int i = 0; i < 30000; ++i)
{
if ((i % 100) == 0)
{
// generate new keys every 100 times
// std::cerr << "new keys" << std::endl;
senderPriv.MakeNewKey ();
recipientPriv.MakeNewKey ();
if (!senderPub.SetPubKey(senderPriv.GetPubKey()))
throw std::runtime_error("key error");
if (!recipientPub.SetPubKey(recipientPriv.GetPubKey()))
throw std::runtime_error("key error");
}
if (!senderPub.SetPubKey (senderPriv.GetPubKey ()))
throw std::runtime_error ("key error");
// generate message
Blob message(4096);
int msglen = i%3000;
if (!recipientPub.SetPubKey (recipientPriv.GetPubKey ()))
throw std::runtime_error ("key error");
}
RandomNumbers::getInstance ().fillBytes (&message.front(), msglen);
message.resize(msglen);
// generate message
Blob message (4096);
int msglen = i % 3000;
// encrypt message with sender's private key and recipient's public key
Blob ciphertext = senderPriv.encryptECIES(recipientPub, message);
RandomNumbers::getInstance ().fillBytes (&message.front (), msglen);
message.resize (msglen);
// decrypt message with recipient's private key and sender's public key
Blob decrypt = recipientPriv.decryptECIES(senderPub, ciphertext);
// encrypt message with sender's private key and recipient's public key
Blob ciphertext = senderPriv.encryptECIES (recipientPub, message);
if (decrypt != message)
{
assert(false);
return false;
}
// std::cerr << "Msg(" << msglen << ") ok " << ciphertext.size() << std::endl;
}
return true;
// decrypt message with recipient's private key and sender's public key
Blob decrypt = recipientPriv.decryptECIES (senderPub, ciphertext);
if (decrypt != message)
{
assert (false);
return false;
}
// std::cerr << "Msg(" << msglen << ") ok " << ciphertext.size() << std::endl;
}
return true;
}
// vim:ts=4

View File

@@ -12,363 +12,370 @@
#include <string>
#include <vector>
char const* RFC1751::s_dictionary [2048] = {
"A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
"AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA",
"AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK",
"ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE",
"AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
"BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET",
"BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO",
"BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT",
"BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
"CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY",
"CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN",
"DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG",
"DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
"DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO",
"ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE",
"EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW",
"FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
"FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP",
"GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO",
"GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD",
"HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
"HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT",
"HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE",
"HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL",
"INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", "ITS",
"IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", "JIG",
"JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", "KAY",
"KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC",
"LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", "LEG",
"LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", "LO",
"LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", "LYE",
"MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY",
"ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", "MOB",
"MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", "MUM",
"MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", "NEE",
"NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON",
"NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", "OAK",
"OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", "OK",
"OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", "OUR",
"OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", "PAL",
"PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", "PEN",
"PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", "PLY",
"PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", "PUG",
"PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", "RAW",
"RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", "RIO",
"RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", "RUE",
"RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", "SAN",
"SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", "SEW",
"SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", "SLY",
"SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", "SUB",
"SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", "TAP",
"TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM",
"TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", "TOW",
"TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", "US",
"USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", "WAY",
"WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK",
"WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", "YEA",
"YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", "ACHE",
"ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", "ADEN", "AFAR",
"AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", "AIDS", "AIRY", "AJAR",
"AKIN", "ALAN", "ALEC", "ALGA", "ALIA", "ALLY", "ALMA", "ALOE", "ALSO",
"ALTO", "ALUM", "ALVA", "AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS",
"AMRA", "ANDY", "ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB",
"ARCH", "AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS",
"ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW",
"AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", "BAIT",
"BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", "BAND", "BANE",
"BANG", "BANK", "BARB", "BARD", "BARE", "BARK", "BARN", "BARR", "BASE",
"BASH", "BASK", "BASS", "BATE", "BATH", "BAWD", "BAWL", "BEAD", "BEAK",
"BEAM", "BEAN", "BEAR", "BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER",
"BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT",
"BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", "BILE",
"BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", "BLAT",
"BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", "BLUM", "BLUR",
"BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", "BOGY", "BOHR", "BOIL",
"BOLD", "BOLO", "BOLT", "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN",
"BONY", "BOOK", "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE",
"BOSS", "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN",
"BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", "BUFF",
"BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", "BURL", "BURN",
"BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", "CADY",
"CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", "CAME", "CANE",
"CANT", "CARD", "CARE", "CARL", "CARR", "CART", "CASE", "CASH", "CASK",
"CAST", "CAVE", "CEIL", "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT",
"CHAW", "CHEF", "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB",
"CHUG", "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY",
"CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", "COCK",
"COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", "COKE", "COLA",
"COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", "COON", "COOT",
"CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", "CRAB", "CRAG",
"CRAM", "CRAY", "CREW", "CRIB", "CROW", "CRUD", "CUBA", "CUBE", "CUFF",
"CULL", "CULT", "CUNY", "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS",
"DADE", "DALE", "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK",
"DARN", "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS",
"DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", "DEEM",
"DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", "DICE",
"DIED", "DIET", "DIME", "DINE", "DING", "DINT", "DIRE", "DIRT", "DISC",
"DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", "DOLT", "DOME",
"DONE", "DOOM", "DOOR", "DORA", "DOSE", "DOTE", "DOUG", "DOUR", "DOVE",
"DOWN", "DRAB", "DRAG", "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM",
"DUAL", "DUCK", "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE",
"DUNK", "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST",
"EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", "EDNA",
"EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", "ENDS",
"ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", "FACE", "FACT", "FADE",
"FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", "FARM", "FAST",
"FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", "FEET", "FELL", "FELT",
"FEND", "FERN", "FEST", "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM",
"FIND", "FINE", "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS",
"FIVE", "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW",
"FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", "FOGY",
"FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", "FORD",
"FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", "FRAU",
"FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", "FROM", "FUEL", "FULL",
"FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", "GAFF", "GAGE", "GAIL",
"GAIN", "GAIT", "GALA", "GALE", "GALL", "GALT", "GAME", "GANG", "GARB",
"GARY", "GASH", "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD",
"GENE", "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT",
"GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", "GLIB",
"GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", "GOAT",
"GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", "GORE",
"GORY", "GOSH", "GOUT", "GOWN", "GRAB", "GRAD", "GRAY", "GREG", "GREW",
"GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", "GRUB", "GULF", "GULL",
"GUNK", "GURU", "GUSH", "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK",
"HAIL", "HAIR", "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG",
"HANK", "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE",
"HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", "HEAT",
"HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", "HELM", "HERB",
"HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", "HIGH",
"HIKE", "HILL", "HILT", "HIND", "HINT", "HIRE", "HISS", "HIVE", "HOBO",
"HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", "HOME", "HONE", "HONK",
"HOOD", "HOOF", "HOOK", "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE",
"HOWE", "HOWL", "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO",
"HULK", "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE",
"HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", "INTO",
"IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", "ITCH", "ITEM",
"IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", "JEFF",
"JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", "JOAN", "JOBS",
"JOCK", "JOEL", "JOEY", "JOHN", "JOIN", "JOKE", "JOLT", "JOVE", "JUDD",
"JUDE", "JUDO", "JUDY", "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO",
"JURY", "JUST", "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE",
"KEEL", "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL",
"KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", "KNIT",
"KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", "KYLE",
"LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", "LAKE", "LAMB",
"LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", "LAST", "LATE",
"LAUD", "LAVA", "LAWN", "LAWS", "LAYS", "LEAD", "LEAF", "LEAK", "LEAN",
"LEAR", "LEEK", "LEER", "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK",
"LESS", "LEST", "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES",
"LIEU", "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB",
"LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", "LIVE",
"LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", "LOLA",
"LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", "LORE", "LOSE", "LOSS",
"LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", "LUKE", "LULU",
"LUND", "LUNG", "LURA", "LURE", "LURK", "LUSH", "LUST", "LYLE", "LYNN",
"LYON", "LYRA", "MACE", "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE",
"MALE", "MALI", "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE",
"MARK", "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE",
"MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", "MEET",
"MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", "MICE",
"MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", "MIMI", "MIND", "MINE",
"MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", "MITT", "MOAN",
"MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", "MOLT", "MONA", "MONK",
"MONT", "MOOD", "MOON", "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS",
"MOST", "MOTH", "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL",
"MURK", "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL",
"NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", "NEAT",
"NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", "NEWS",
"NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", "NODE",
"NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", "NOSE", "NOTE", "NOUN",
"NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", "OBOE", "ODIN", "OHIO",
"OILY", "OINT", "OKAY", "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN",
"OMIT", "ONCE", "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO",
"OTIS", "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY",
"OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", "RAGE",
"RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", "RATE",
"RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", "REEF",
"REEK", "REEL", "REID", "REIN", "RENA", "REND", "RENT", "REST", "RICE",
"RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", "RING", "RINK", "RISE",
"RISK", "RITE", "ROAD", "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL",
"ROLL", "ROME", "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE",
"ROSS", "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY",
"RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", "RUSH",
"RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", "SAID", "SAIL",
"SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", "SARA",
"SAUL", "SAVE", "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", "SEAL", "SEAM",
"SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", "SEES", "SELF", "SELL",
"SEND", "SENT", "SETS", "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED",
"SHIM", "SHIN", "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK",
"SIDE", "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE",
"SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", "SKID",
"SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", "SLED", "SLEW",
"SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", "SLUM",
"SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", "SNUG", "SOAK",
"SOAR", "SOCK", "SODA", "SOFA", "SOFT", "SOIL", "SOLD", "SOME", "SONG",
"SOON", "SOOT", "SORE", "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG",
"STAN", "STAR", "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN",
"SUCH", "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF",
"SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", "TACK",
"TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", "TATE",
"TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", "TEET", "TELL",
"TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", "THAT", "THEE",
"THEM", "THEN", "THEY", "THIN", "THIS", "THUD", "THUG", "TICK", "TIDE",
"TIDY", "TIED", "TIER", "TILE", "TILL", "TILT", "TIME", "TINA", "TINE",
"TINT", "TINY", "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE",
"TONG", "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR",
"TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", "TRIM",
"TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", "TUFT",
"TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", "TWIG", "TWIN", "TWIT",
"ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", "VAIL", "VAIN",
"VALE", "VARY", "VASE", "VAST", "VEAL", "VEDA", "VEIL", "VEIN", "VEND",
"VENT", "VERB", "VERY", "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID",
"VOLT", "VOTE", "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE",
"WALK", "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM",
"WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", "WAYS",
"WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", "WELL",
"WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", "WHAT", "WHEE", "WHEN",
"WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", "WIND", "WINE",
"WING", "WINK", "WINO", "WIRE", "WISE", "WISH", "WITH", "WOLF", "WONT",
"WOOD", "WOOL", "WORD", "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT",
"WYNN", "YALE", "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH",
"YEAR", "YELL", "YOGA", "YOKE"
char const* RFC1751::s_dictionary [2048] =
{
"A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
"AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA",
"AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK",
"ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE",
"AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
"BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET",
"BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO",
"BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT",
"BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
"CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY",
"CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN",
"DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG",
"DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
"DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO",
"ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE",
"EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW",
"FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
"FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP",
"GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO",
"GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD",
"HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
"HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT",
"HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE",
"HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL",
"INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", "ITS",
"IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", "JIG",
"JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", "KAY",
"KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC",
"LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", "LEG",
"LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", "LO",
"LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", "LYE",
"MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY",
"ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", "MOB",
"MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", "MUM",
"MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", "NEE",
"NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON",
"NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", "OAK",
"OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", "OK",
"OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", "OUR",
"OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", "PAL",
"PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", "PEN",
"PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", "PLY",
"PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", "PUG",
"PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", "RAW",
"RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", "RIO",
"RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", "RUE",
"RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", "SAN",
"SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", "SEW",
"SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", "SLY",
"SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", "SUB",
"SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", "TAP",
"TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM",
"TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", "TOW",
"TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", "US",
"USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", "WAY",
"WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK",
"WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", "YEA",
"YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", "ACHE",
"ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", "ADEN", "AFAR",
"AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", "AIDS", "AIRY", "AJAR",
"AKIN", "ALAN", "ALEC", "ALGA", "ALIA", "ALLY", "ALMA", "ALOE", "ALSO",
"ALTO", "ALUM", "ALVA", "AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS",
"AMRA", "ANDY", "ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB",
"ARCH", "AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS",
"ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW",
"AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", "BAIT",
"BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", "BAND", "BANE",
"BANG", "BANK", "BARB", "BARD", "BARE", "BARK", "BARN", "BARR", "BASE",
"BASH", "BASK", "BASS", "BATE", "BATH", "BAWD", "BAWL", "BEAD", "BEAK",
"BEAM", "BEAN", "BEAR", "BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER",
"BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT",
"BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", "BILE",
"BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", "BLAT",
"BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", "BLUM", "BLUR",
"BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", "BOGY", "BOHR", "BOIL",
"BOLD", "BOLO", "BOLT", "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN",
"BONY", "BOOK", "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE",
"BOSS", "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN",
"BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", "BUFF",
"BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", "BURL", "BURN",
"BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", "CADY",
"CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", "CAME", "CANE",
"CANT", "CARD", "CARE", "CARL", "CARR", "CART", "CASE", "CASH", "CASK",
"CAST", "CAVE", "CEIL", "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT",
"CHAW", "CHEF", "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB",
"CHUG", "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY",
"CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", "COCK",
"COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", "COKE", "COLA",
"COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", "COON", "COOT",
"CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", "CRAB", "CRAG",
"CRAM", "CRAY", "CREW", "CRIB", "CROW", "CRUD", "CUBA", "CUBE", "CUFF",
"CULL", "CULT", "CUNY", "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS",
"DADE", "DALE", "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK",
"DARN", "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS",
"DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", "DEEM",
"DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", "DICE",
"DIED", "DIET", "DIME", "DINE", "DING", "DINT", "DIRE", "DIRT", "DISC",
"DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", "DOLT", "DOME",
"DONE", "DOOM", "DOOR", "DORA", "DOSE", "DOTE", "DOUG", "DOUR", "DOVE",
"DOWN", "DRAB", "DRAG", "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM",
"DUAL", "DUCK", "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE",
"DUNK", "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST",
"EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", "EDNA",
"EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", "ENDS",
"ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", "FACE", "FACT", "FADE",
"FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", "FARM", "FAST",
"FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", "FEET", "FELL", "FELT",
"FEND", "FERN", "FEST", "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM",
"FIND", "FINE", "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS",
"FIVE", "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW",
"FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", "FOGY",
"FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", "FORD",
"FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", "FRAU",
"FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", "FROM", "FUEL", "FULL",
"FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", "GAFF", "GAGE", "GAIL",
"GAIN", "GAIT", "GALA", "GALE", "GALL", "GALT", "GAME", "GANG", "GARB",
"GARY", "GASH", "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD",
"GENE", "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT",
"GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", "GLIB",
"GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", "GOAT",
"GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", "GORE",
"GORY", "GOSH", "GOUT", "GOWN", "GRAB", "GRAD", "GRAY", "GREG", "GREW",
"GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", "GRUB", "GULF", "GULL",
"GUNK", "GURU", "GUSH", "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK",
"HAIL", "HAIR", "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG",
"HANK", "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE",
"HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", "HEAT",
"HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", "HELM", "HERB",
"HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", "HIGH",
"HIKE", "HILL", "HILT", "HIND", "HINT", "HIRE", "HISS", "HIVE", "HOBO",
"HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", "HOME", "HONE", "HONK",
"HOOD", "HOOF", "HOOK", "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE",
"HOWE", "HOWL", "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO",
"HULK", "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE",
"HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", "INTO",
"IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", "ITCH", "ITEM",
"IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", "JEFF",
"JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", "JOAN", "JOBS",
"JOCK", "JOEL", "JOEY", "JOHN", "JOIN", "JOKE", "JOLT", "JOVE", "JUDD",
"JUDE", "JUDO", "JUDY", "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO",
"JURY", "JUST", "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE",
"KEEL", "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL",
"KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", "KNIT",
"KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", "KYLE",
"LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", "LAKE", "LAMB",
"LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", "LAST", "LATE",
"LAUD", "LAVA", "LAWN", "LAWS", "LAYS", "LEAD", "LEAF", "LEAK", "LEAN",
"LEAR", "LEEK", "LEER", "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK",
"LESS", "LEST", "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES",
"LIEU", "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB",
"LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", "LIVE",
"LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", "LOLA",
"LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", "LORE", "LOSE", "LOSS",
"LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", "LUKE", "LULU",
"LUND", "LUNG", "LURA", "LURE", "LURK", "LUSH", "LUST", "LYLE", "LYNN",
"LYON", "LYRA", "MACE", "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE",
"MALE", "MALI", "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE",
"MARK", "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE",
"MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", "MEET",
"MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", "MICE",
"MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", "MIMI", "MIND", "MINE",
"MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", "MITT", "MOAN",
"MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", "MOLT", "MONA", "MONK",
"MONT", "MOOD", "MOON", "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS",
"MOST", "MOTH", "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL",
"MURK", "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL",
"NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", "NEAT",
"NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", "NEWS",
"NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", "NODE",
"NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", "NOSE", "NOTE", "NOUN",
"NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", "OBOE", "ODIN", "OHIO",
"OILY", "OINT", "OKAY", "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN",
"OMIT", "ONCE", "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO",
"OTIS", "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY",
"OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", "RAGE",
"RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", "RATE",
"RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", "REEF",
"REEK", "REEL", "REID", "REIN", "RENA", "REND", "RENT", "REST", "RICE",
"RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", "RING", "RINK", "RISE",
"RISK", "RITE", "ROAD", "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL",
"ROLL", "ROME", "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE",
"ROSS", "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY",
"RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", "RUSH",
"RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", "SAID", "SAIL",
"SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", "SARA",
"SAUL", "SAVE", "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", "SEAL", "SEAM",
"SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", "SEES", "SELF", "SELL",
"SEND", "SENT", "SETS", "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED",
"SHIM", "SHIN", "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK",
"SIDE", "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE",
"SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", "SKID",
"SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", "SLED", "SLEW",
"SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", "SLUM",
"SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", "SNUG", "SOAK",
"SOAR", "SOCK", "SODA", "SOFA", "SOFT", "SOIL", "SOLD", "SOME", "SONG",
"SOON", "SOOT", "SORE", "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG",
"STAN", "STAR", "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN",
"SUCH", "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF",
"SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", "TACK",
"TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", "TATE",
"TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", "TEET", "TELL",
"TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", "THAT", "THEE",
"THEM", "THEN", "THEY", "THIN", "THIS", "THUD", "THUG", "TICK", "TIDE",
"TIDY", "TIED", "TIER", "TILE", "TILL", "TILT", "TIME", "TINA", "TINE",
"TINT", "TINY", "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE",
"TONG", "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR",
"TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", "TRIM",
"TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", "TUFT",
"TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", "TWIG", "TWIN", "TWIT",
"ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", "VAIL", "VAIN",
"VALE", "VARY", "VASE", "VAST", "VEAL", "VEDA", "VEIL", "VEIN", "VEND",
"VENT", "VERB", "VERY", "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID",
"VOLT", "VOTE", "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE",
"WALK", "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM",
"WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", "WAYS",
"WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", "WELL",
"WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", "WHAT", "WHEE", "WHEN",
"WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", "WIND", "WINE",
"WING", "WINK", "WINO", "WIRE", "WISE", "WISH", "WITH", "WOLF", "WONT",
"WOOD", "WOOL", "WORD", "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT",
"WYNN", "YALE", "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH",
"YEAR", "YELL", "YOGA", "YOKE"
};
/* Extract 'length' bits from the char array 's'
starting with bit 'start' */
unsigned long RFC1751::extract(char *s, int start, int length)
unsigned long RFC1751::extract (char* s, int start, int length)
{
unsigned char cl;
unsigned char cc;
unsigned char cr;
unsigned long x;
unsigned char cl;
unsigned char cc;
unsigned char cr;
unsigned long x;
assert(length <= 11);
assert(start >= 0);
assert(length >= 0);
assert(start+length <= 66);
assert (length <= 11);
assert (start >= 0);
assert (length >= 0);
assert (start + length <= 66);
cl = s[start/8]; // get components
cc = s[start/8 +1];
cr = s[start/8 +2];
cl = s[start / 8]; // get components
cc = s[start / 8 + 1];
cr = s[start / 8 + 2];
x = ((long)(cl<<8 | cc) <<8 | cr) ; // Put bits together
x = x >> (24 - (length + (start%8))); // Right justify number
x = ( x & (0xffff >> (16-length) ) ); // Trim extra bits.
x = ((long) (cl << 8 | cc) << 8 | cr) ; // Put bits together
x = x >> (24 - (length + (start % 8))); // Right justify number
x = ( x & (0xffff >> (16 - length) ) ); // Trim extra bits.
return x;
return x;
}
// Encode 8 bytes in 'c' as a string of English words.
// Returns a pointer to a static buffer
void RFC1751::btoe(std::string& strHuman, const std::string& strData)
void RFC1751::btoe (std::string& strHuman, const std::string& strData)
{
char caBuffer[9]; /* add in room for the parity 2 bits*/
int p, i;
char caBuffer[9]; /* add in room for the parity 2 bits*/
int p, i;
memcpy(caBuffer, strData.c_str(), 8);
memcpy (caBuffer, strData.c_str (), 8);
// compute parity: merely add groups of two bits.
for(p = 0, i = 0; i < 64; i += 2)
p += extract(caBuffer, i, 2);
// compute parity: merely add groups of two bits.
for (p = 0, i = 0; i < 64; i += 2)
p += extract (caBuffer, i, 2);
caBuffer[8] = char(p) << 6;
caBuffer[8] = char (p) << 6;
strHuman = std::string()
+ s_dictionary[extract(caBuffer, 0, 11)] + " "
+ s_dictionary[extract(caBuffer, 11, 11)] + " "
+ s_dictionary[extract(caBuffer, 22, 11)] + " "
+ s_dictionary[extract(caBuffer, 33, 11)] + " "
+ s_dictionary[extract(caBuffer, 44, 11)] + " "
+ s_dictionary[extract(caBuffer, 55, 11)];
strHuman = std::string ()
+ s_dictionary[extract (caBuffer, 0, 11)] + " "
+ s_dictionary[extract (caBuffer, 11, 11)] + " "
+ s_dictionary[extract (caBuffer, 22, 11)] + " "
+ s_dictionary[extract (caBuffer, 33, 11)] + " "
+ s_dictionary[extract (caBuffer, 44, 11)] + " "
+ s_dictionary[extract (caBuffer, 55, 11)];
}
void RFC1751::insert(char *s, int x, int start, int length)
void RFC1751::insert (char* s, int x, int start, int length)
{
unsigned char cl;
unsigned char cc;
unsigned char cr;
unsigned long y;
int shift;
unsigned char cl;
unsigned char cc;
unsigned char cr;
unsigned long y;
int shift;
assert(length <= 11);
assert(start >= 0);
assert(length >= 0);
assert(start+length <= 66);
assert (length <= 11);
assert (start >= 0);
assert (length >= 0);
assert (start + length <= 66);
shift = ((8 -(( start + length) % 8))%8);
y = (long) x << shift;
cl = (y >> 16) & 0xff;
cc = (y >> 8) & 0xff;
cr = y & 0xff;
if(shift + length > 16){
s[start /8] |= cl;
s[start/8 +1] |= cc;
s[start/8 +2] |= cr;
} else if(shift +length > 8){
s[start/8] |= cc;
s[start/8 + 1] |= cr;
} else {
s[start/8] |= cr;
}
shift = ((8 - (( start + length) % 8)) % 8);
y = (long) x << shift;
cl = (y >> 16) & 0xff;
cc = (y >> 8) & 0xff;
cr = y & 0xff;
if (shift + length > 16)
{
s[start / 8] |= cl;
s[start / 8 + 1] |= cc;
s[start / 8 + 2] |= cr;
}
else if (shift + length > 8)
{
s[start / 8] |= cc;
s[start / 8 + 1] |= cr;
}
else
{
s[start / 8] |= cr;
}
}
void RFC1751::standard(std::string& strWord)
void RFC1751::standard (std::string& strWord)
{
BOOST_FOREACH(char cLetter, strWord)
{
if(!isascii(cLetter))
{
; // nothing
}
else if(islower(cLetter))
{
cLetter = toupper(cLetter);
}
else if(cLetter == '1')
{
cLetter = 'L';
}
else if(cLetter == '0')
{
cLetter = 'O';
}
else if(cLetter == '5')
{
cLetter = 'S';
}
}
BOOST_FOREACH (char cLetter, strWord)
{
if (!isascii (cLetter))
{
; // nothing
}
else if (islower (cLetter))
{
cLetter = toupper (cLetter);
}
else if (cLetter == '1')
{
cLetter = 'L';
}
else if (cLetter == '0')
{
cLetter = 'O';
}
else if (cLetter == '5')
{
cLetter = 'S';
}
}
}
// Binary search of dictionary.
int RFC1751::wsrch (const std::string& strWord, int iMin, int iMax)
{
int iResult = -1;
int iResult = -1;
while (iResult < 0 && iMin != iMax)
{
// Have a range to search.
int iMid = iMin+(iMax-iMin)/2;
int iDir = strWord.compare(s_dictionary[iMid]);
while (iResult < 0 && iMin != iMax)
{
// Have a range to search.
int iMid = iMin + (iMax - iMin) / 2;
int iDir = strWord.compare (s_dictionary[iMid]);
if (!iDir)
{
iResult = iMid; // Found it.
}
else if (iDir < 0)
{
iMax = iMid; // key < middle, middle is new max.
}
else
{
iMin = iMid+1; // key > middle, new min is past the middle.
}
}
if (!iDir)
{
iResult = iMid; // Found it.
}
else if (iDir < 0)
{
iMax = iMid; // key < middle, middle is new max.
}
else
{
iMin = iMid + 1; // key > middle, new min is past the middle.
}
}
return iResult;
return iResult;
}
// Convert 6 words to binary.
@@ -379,91 +386,92 @@ int RFC1751::wsrch (const std::string& strWord, int iMin, int iMax)
// -2 words OK but parity is wrong
int RFC1751::etob (std::string& strData, std::vector<std::string> vsHuman)
{
int i, p, v,l;
char b[9];
int i, p, v, l;
char b[9];
if (6 != vsHuman.size())
return -1;
if (6 != vsHuman.size ())
return -1;
memset(b, 0, sizeof(b));
memset (b, 0, sizeof (b));
p=0;
BOOST_FOREACH(std::string& strWord, vsHuman)
{
l = strWord.length();
if(l > 4 || l < 1)
return -1;
p = 0;
BOOST_FOREACH (std::string & strWord, vsHuman)
{
l = strWord.length ();
standard (strWord);
if (l > 4 || l < 1)
return -1;
v = wsrch(strWord,
l < 4 ? 0 : 571,
l < 4 ? 570 : 2048);
standard (strWord);
if(v < 0 )
return 0;
v = wsrch (strWord,
l < 4 ? 0 : 571,
l < 4 ? 570 : 2048);
insert(b, v, p, 11);
p +=11;
}
if (v < 0 )
return 0;
/* now check the parity of what we got */
for(p = 0, i = 0; i < 64; i +=2)
p += extract(b, i, 2);
insert (b, v, p, 11);
p += 11;
}
if( (p & 3) != extract(b, 64,2) )
return -2;
/* now check the parity of what we got */
for (p = 0, i = 0; i < 64; i += 2)
p += extract (b, i, 2);
strData.assign(b, 8);
if ( (p & 3) != extract (b, 64, 2) )
return -2;
return 1;
strData.assign (b, 8);
return 1;
}
/** Convert words seperated by spaces into a 128 bit key in big-endian format.
/** Convert words seperated by spaces into a 128 bit key in big-endian format.
@return
1 if succeeded
0 if word not in dictionary
-1 if badly formed string
-2 if words are okay but parity is wrong.
@return
1 if succeeded
0 if word not in dictionary
-1 if badly formed string
-2 if words are okay but parity is wrong.
*/
int RFC1751::getKeyFromEnglish (std::string& strKey, const std::string& strHuman)
{
std::vector<std::string> vWords;
std::string strFirst, strSecond;
int rc=0;
std::string strFirst, strSecond;
int rc = 0;
std::string strTrimmed(strHuman);
std::string strTrimmed (strHuman);
boost::algorithm::trim(strTrimmed);
boost::algorithm::trim (strTrimmed);
boost::algorithm::split(vWords, strTrimmed,
boost::algorithm::is_space(), boost::algorithm::token_compress_on);
boost::algorithm::split (vWords, strTrimmed,
boost::algorithm::is_space (), boost::algorithm::token_compress_on);
rc = 12 == vWords.size() ? 1 : -1;
if (1 == rc)
rc = etob(strFirst, vWords | boost::adaptors::copied(0, 6));
if (1 == rc)
rc = etob(strSecond, vWords | boost::adaptors::copied(6, 12));
rc = 12 == vWords.size () ? 1 : -1;
if (1 == rc)
strKey = strFirst + strSecond;
rc = etob (strFirst, vWords | boost::adaptors::copied (0, 6));
return rc;
if (1 == rc)
rc = etob (strSecond, vWords | boost::adaptors::copied (6, 12));
if (1 == rc)
strKey = strFirst + strSecond;
return rc;
}
/** Convert to human from a 128 bit key in big-endian format
*/
void RFC1751::getEnglishFromKey (std::string& strHuman, const std::string& strKey)
{
std::string strFirst, strSecond;
std::string strFirst, strSecond;
btoe(strFirst, strKey.substr(0, 8));
btoe(strSecond, strKey.substr(8, 8));
btoe (strFirst, strKey.substr (0, 8));
btoe (strSecond, strKey.substr (8, 8));
strHuman = strFirst + " " + strSecond;
strHuman = strFirst + " " + strSecond;
}
// vim:ts=4

View File

@@ -4,19 +4,19 @@
class RFC1751
{
public:
static int getKeyFromEnglish (std::string& strKey, const std::string& strHuman);
static int getKeyFromEnglish (std::string& strKey, const std::string& strHuman);
static void getEnglishFromKey (std::string& strHuman, const std::string& strKey);
static void getEnglishFromKey (std::string& strHuman, const std::string& strKey);
private:
static unsigned long extract (char *s, int start, int length);
static void btoe (std::string& strHuman, const std::string& strData);
static void insert (char *s, int x, int start, int length);
static void standard (std::string& strWord);
static int wsrch (const std::string& strWord, int iMin, int iMax);
static int etob (std::string& strData, std::vector<std::string> vsHuman);
static unsigned long extract (char* s, int start, int length);
static void btoe (std::string& strHuman, const std::string& strData);
static void insert (char* s, int x, int start, int length);
static void standard (std::string& strWord);
static int wsrch (const std::string& strWord, int iMin, int iMax);
static int etob (std::string& strData, std::vector<std::string> vsHuman);
static char const* s_dictionary [];
static char const* s_dictionary [];
};
#endif