Files
xahaud/modules/ripple_data/protocol/ripple_RippleAddress.cpp
2013-06-15 18:20:59 -07:00

936 lines
23 KiB
C++

//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
SETUP_LOG (RippleAddress)
RippleAddress::RippleAddress ()
: mIsValid (false)
{
nVersion = VER_NONE;
}
void RippleAddress::clear ()
{
nVersion = VER_NONE;
vchData.clear ();
}
bool RippleAddress::isSet () const
{
return nVersion != VER_NONE;
}
std::string RippleAddress::humanAddressType () const
{
switch (nVersion)
{
case VER_NONE:
return "VER_NONE";
case VER_NODE_PUBLIC:
return "VER_NODE_PUBLIC";
case VER_NODE_PRIVATE:
return "VER_NODE_PRIVATE";
case VER_ACCOUNT_ID:
return "VER_ACCOUNT_ID";
case VER_ACCOUNT_PUBLIC:
return "VER_ACCOUNT_PUBLIC";
case VER_ACCOUNT_PRIVATE:
return "VER_ACCOUNT_PRIVATE";
case VER_FAMILY_GENERATOR:
return "VER_FAMILY_GENERATOR";
case VER_FAMILY_SEED:
return "VER_FAMILY_SEED";
}
return "unknown";
}
//
// NodePublic
//
RippleAddress RippleAddress::createNodePublic (const RippleAddress& naSeed)
{
CKey ckSeed (naSeed.getSeed ());
RippleAddress naNew;
// YYY Should there be a GetPubKey() equiv that returns a uint256?
naNew.setNodePublic (ckSeed.GetPubKey ());
return naNew;
}
RippleAddress RippleAddress::createNodePublic (Blob const& vPublic)
{
RippleAddress naNew;
naNew.setNodePublic (vPublic);
return naNew;
}
RippleAddress RippleAddress::createNodePublic (const std::string& strPublic)
{
RippleAddress naNew;
naNew.setNodePublic (strPublic);
return naNew;
}
uint160 RippleAddress::getNodeID () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getNodeID");
case VER_NODE_PUBLIC:
// Note, we are encoding the left.
return Hash160 (vchData);
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
Blob const& RippleAddress::getNodePublic () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getNodePublic");
case VER_NODE_PUBLIC:
return vchData;
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanNodePublic () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanNodePublic");
case VER_NODE_PUBLIC:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setNodePublic (const std::string& strPublic)
{
mIsValid = SetString (strPublic.c_str (), VER_NODE_PUBLIC);
return mIsValid;
}
void RippleAddress::setNodePublic (Blob const& vPublic)
{
mIsValid = true;
SetData (VER_NODE_PUBLIC, vPublic);
}
bool RippleAddress::verifyNodePublic (uint256 const& hash, Blob const& vchSig) const
{
CKey pubkey = CKey ();
bool bVerified;
if (!pubkey.SetPubKey (getNodePublic ()))
{
// Failed to set public key.
bVerified = false;
}
else
{
bVerified = pubkey.Verify (hash, vchSig);
}
return bVerified;
}
bool RippleAddress::verifyNodePublic (uint256 const& hash, const std::string& strSig) const
{
Blob vchSig (strSig.begin (), strSig.end ());
return verifyNodePublic (hash, vchSig);
}
//
// NodePrivate
//
RippleAddress RippleAddress::createNodePrivate (const RippleAddress& naSeed)
{
uint256 uPrivKey;
RippleAddress naNew;
CKey ckSeed (naSeed.getSeed ());
ckSeed.GetPrivateKeyU (uPrivKey);
naNew.setNodePrivate (uPrivKey);
return naNew;
}
Blob const& RippleAddress::getNodePrivateData () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getNodePrivateData");
case VER_NODE_PRIVATE:
return vchData;
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
uint256 RippleAddress::getNodePrivate () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source = getNodePrivate");
case VER_NODE_PRIVATE:
return uint256 (vchData);
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanNodePrivate () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanNodePrivate");
case VER_NODE_PRIVATE:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setNodePrivate (const std::string& strPrivate)
{
mIsValid = SetString (strPrivate.c_str (), VER_NODE_PRIVATE);
return mIsValid;
}
void RippleAddress::setNodePrivate (Blob const& vPrivate)
{
mIsValid = true;
SetData (VER_NODE_PRIVATE, vPrivate);
}
void RippleAddress::setNodePrivate (uint256 hash256)
{
mIsValid = true;
SetData (VER_NODE_PRIVATE, hash256.begin (), 32);
}
void RippleAddress::signNodePrivate (uint256 const& hash, Blob& vchSig) const
{
CKey ckPrivKey;
ckPrivKey.SetPrivateKeyU (getNodePrivate ());
if (!ckPrivKey.Sign (hash, vchSig))
throw std::runtime_error ("Signing failed.");
}
//
// AccountID
//
uint160 RippleAddress::getAccountID () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getAccountID");
case VER_ACCOUNT_ID:
return uint160 (vchData);
case VER_ACCOUNT_PUBLIC:
// Note, we are encoding the left.
return Hash160 (vchData);
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
static boost::mutex rncLock;
static boost::unordered_map< Blob , std::string > rncMap;
std::string RippleAddress::humanAccountID () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanAccountID");
case VER_ACCOUNT_ID:
{
boost::mutex::scoped_lock sl (rncLock);
boost::unordered_map< Blob , std::string >::iterator it = rncMap.find (vchData);
if (it != rncMap.end ())
return it->second;
if (rncMap.size () > 10000)
rncMap.clear ();
return rncMap[vchData] = ToString ();
}
case VER_ACCOUNT_PUBLIC:
{
RippleAddress accountID;
(void) accountID.setAccountID (getAccountID ());
return accountID.ToString ();
}
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setAccountID (const std::string& strAccountID, const char* pAlphabet)
{
if (strAccountID.empty ())
{
setAccountID (uint160 ());
mIsValid = true;
}
else
{
mIsValid = SetString (strAccountID.c_str (), VER_ACCOUNT_ID, pAlphabet);
}
return mIsValid;
}
void RippleAddress::setAccountID (const uint160& hash160)
{
mIsValid = true;
SetData (VER_ACCOUNT_ID, hash160.begin (), 20);
}
//
// AccountPublic
//
RippleAddress RippleAddress::createAccountPublic (const RippleAddress& naGenerator, int iSeq)
{
CKey ckPub (naGenerator, iSeq);
RippleAddress naNew;
naNew.setAccountPublic (ckPub.GetPubKey ());
return naNew;
}
Blob const& RippleAddress::getAccountPublic () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getAccountPublic");
case VER_ACCOUNT_ID:
throw std::runtime_error ("public not available from account id");
break;
case VER_ACCOUNT_PUBLIC:
return vchData;
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanAccountPublic () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanAccountPublic");
case VER_ACCOUNT_ID:
throw std::runtime_error ("public not available from account id");
case VER_ACCOUNT_PUBLIC:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setAccountPublic (const std::string& strPublic)
{
mIsValid = SetString (strPublic.c_str (), VER_ACCOUNT_PUBLIC);
return mIsValid;
}
void RippleAddress::setAccountPublic (Blob const& vPublic)
{
mIsValid = true;
SetData (VER_ACCOUNT_PUBLIC, vPublic);
}
void RippleAddress::setAccountPublic (const RippleAddress& generator, int seq)
{
CKey pubkey = CKey (generator, seq);
setAccountPublic (pubkey.GetPubKey ());
}
bool RippleAddress::accountPublicVerify (uint256 const& uHash, Blob const& vucSig) const
{
CKey ckPublic;
bool bVerified;
if (!ckPublic.SetPubKey (getAccountPublic ()))
{
// Bad private key.
WriteLog (lsWARNING, RippleAddress) << "accountPublicVerify: Bad private key.";
bVerified = false;
}
else
{
bVerified = ckPublic.Verify (uHash, vucSig);
}
return bVerified;
}
RippleAddress RippleAddress::createAccountID (const uint160& uiAccountID)
{
RippleAddress na;
na.setAccountID (uiAccountID);
return na;
}
//
// AccountPrivate
//
RippleAddress RippleAddress::createAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int iSeq)
{
RippleAddress naNew;
naNew.setAccountPrivate (naGenerator, naSeed, iSeq);
return naNew;
}
uint256 RippleAddress::getAccountPrivate () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getAccountPrivate");
case VER_ACCOUNT_PRIVATE:
return uint256 (vchData);
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanAccountPrivate () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanAccountPrivate");
case VER_ACCOUNT_PRIVATE:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setAccountPrivate (const std::string& strPrivate)
{
mIsValid = SetString (strPrivate.c_str (), VER_ACCOUNT_PRIVATE);
return mIsValid;
}
void RippleAddress::setAccountPrivate (Blob const& vPrivate)
{
mIsValid = true;
SetData (VER_ACCOUNT_PRIVATE, vPrivate);
}
void RippleAddress::setAccountPrivate (uint256 hash256)
{
mIsValid = true;
SetData (VER_ACCOUNT_PRIVATE, hash256.begin (), 32);
}
void RippleAddress::setAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int seq)
{
CKey ckPubkey = CKey (naSeed.getSeed ());
CKey ckPrivkey = CKey (naGenerator, ckPubkey.GetSecretBN (), seq);
uint256 uPrivKey;
ckPrivkey.GetPrivateKeyU (uPrivKey);
setAccountPrivate (uPrivKey);
}
bool RippleAddress::accountPrivateSign (uint256 const& uHash, Blob& vucSig) const
{
CKey ckPrivate;
bool bResult;
if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
{
// Bad private key.
WriteLog (lsWARNING, RippleAddress) << "accountPrivateSign: Bad private key.";
bResult = false;
}
else
{
bResult = ckPrivate.Sign (uHash, vucSig);
CondLog (!bResult, lsWARNING, RippleAddress) << "accountPrivateSign: Signing failed.";
}
return bResult;
}
#if 0
bool RippleAddress::accountPrivateVerify (uint256 const& uHash, Blob const& vucSig) const
{
CKey ckPrivate;
bool bVerified;
if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
{
// Bad private key.
WriteLog (lsWARNING, RippleAddress) << "accountPrivateVerify: Bad private key.";
bVerified = false;
}
else
{
bVerified = ckPrivate.Verify (uHash, vucSig);
}
return bVerified;
}
#endif
Blob RippleAddress::accountPrivateEncrypt (const RippleAddress& naPublicTo, Blob const& vucPlainText) const
{
CKey ckPrivate;
CKey ckPublic;
Blob vucCipherText;
if (!ckPublic.SetPubKey (naPublicTo.getAccountPublic ()))
{
// Bad public key.
WriteLog (lsWARNING, RippleAddress) << "accountPrivateEncrypt: Bad public key.";
}
else if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
{
// Bad private key.
WriteLog (lsWARNING, RippleAddress) << "accountPrivateEncrypt: Bad private key.";
}
else
{
try
{
vucCipherText = ckPrivate.encryptECIES (ckPublic, vucPlainText);
}
catch (...)
{
nothing ();
}
}
return vucCipherText;
}
Blob RippleAddress::accountPrivateDecrypt (const RippleAddress& naPublicFrom, Blob const& vucCipherText) const
{
CKey ckPrivate;
CKey ckPublic;
Blob vucPlainText;
if (!ckPublic.SetPubKey (naPublicFrom.getAccountPublic ()))
{
// Bad public key.
WriteLog (lsWARNING, RippleAddress) << "accountPrivateDecrypt: Bad public key.";
}
else if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
{
// Bad private key.
WriteLog (lsWARNING, RippleAddress) << "accountPrivateDecrypt: Bad private key.";
}
else
{
try
{
vucPlainText = ckPrivate.decryptECIES (ckPublic, vucCipherText);
}
catch (...)
{
nothing ();
}
}
return vucPlainText;
}
//
// Generators
//
BIGNUM* RippleAddress::getGeneratorBN () const
{
// returns the public generator
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getGeneratorBN");
case VER_FAMILY_GENERATOR:
// Do nothing.
break;
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
BIGNUM* ret = BN_bin2bn (&vchData[0], vchData.size (), NULL);
assert (ret);
return ret;
}
Blob const& RippleAddress::getGenerator () const
{
// returns the public generator
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getGenerator");
case VER_FAMILY_GENERATOR:
// Do nothing.
return vchData;
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanGenerator () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanGenerator");
case VER_FAMILY_GENERATOR:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setGenerator (const std::string& strGenerator)
{
mIsValid = SetString (strGenerator.c_str (), VER_FAMILY_GENERATOR);
return mIsValid;
}
void RippleAddress::setGenerator (Blob const& vPublic)
{
mIsValid = true;
SetData (VER_FAMILY_GENERATOR, vPublic);
}
RippleAddress RippleAddress::createGeneratorPublic (const RippleAddress& naSeed)
{
CKey ckSeed (naSeed.getSeed ());
RippleAddress naNew;
naNew.setGenerator (ckSeed.GetPubKey ());
return naNew;
}
//
// Seed
//
uint128 RippleAddress::getSeed () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getSeed");
case VER_FAMILY_SEED:
return uint128 (vchData);
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanSeed1751 () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanSeed1751");
case VER_FAMILY_SEED:
{
std::string strHuman;
std::string strLittle;
std::string strBig;
uint128 uSeed = getSeed ();
strLittle.assign (uSeed.begin (), uSeed.end ());
strBig.assign (strLittle.rbegin (), strLittle.rend ());
RFC1751::getEnglishFromKey (strHuman, strBig);
return strHuman;
}
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanSeed () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanSeed");
case VER_FAMILY_SEED:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
int RippleAddress::setSeed1751 (const std::string& strHuman1751)
{
std::string strKey;
int iResult = RFC1751::getKeyFromEnglish (strKey, strHuman1751);
if (1 == iResult)
{
Blob vchLittle (strKey.rbegin (), strKey.rend ());
uint128 uSeed (vchLittle);
setSeed (uSeed);
}
return iResult;
}
bool RippleAddress::setSeed (const std::string& strSeed)
{
mIsValid = SetString (strSeed.c_str (), VER_FAMILY_SEED);
return mIsValid;
}
bool RippleAddress::setSeedGeneric (const std::string& strText)
{
RippleAddress naTemp;
bool bResult = true;
uint128 uSeed;
if (strText.empty ()
|| naTemp.setAccountID (strText)
|| naTemp.setAccountPublic (strText)
|| naTemp.setAccountPrivate (strText)
|| naTemp.setNodePublic (strText)
|| naTemp.setNodePrivate (strText))
{
bResult = false;
}
else if (strText.length () == 32 && uSeed.SetHex (strText, true))
{
setSeed (uSeed);
}
else if (setSeed (strText))
{
// std::cerr << "Recognized seed." << std::endl;
nothing ();
}
else if (1 == setSeed1751 (strText))
{
// std::cerr << "Recognized 1751 seed." << std::endl;
nothing ();
}
else
{
// std::cerr << "Creating seed from pass phrase." << std::endl;
setSeed (CKey::PassPhraseToKey (strText));
}
return bResult;
}
void RippleAddress::setSeed (uint128 hash128)
{
mIsValid = true;
SetData (VER_FAMILY_SEED, hash128.begin (), 16);
}
void RippleAddress::setSeedRandom ()
{
// XXX Maybe we should call MakeNewKey
uint128 key;
RandomNumbers::getInstance ().fillBytes (key.begin (), key.size ());
RippleAddress::setSeed (key);
}
RippleAddress RippleAddress::createSeedRandom ()
{
RippleAddress naNew;
naNew.setSeedRandom ();
return naNew;
}
RippleAddress RippleAddress::createSeedGeneric (const std::string& strText)
{
RippleAddress naNew;
naNew.setSeedGeneric (strText);
return naNew;
}
BOOST_AUTO_TEST_SUITE (ripple_address)
BOOST_AUTO_TEST_CASE ( check_crypto )
{
// Construct a seed.
RippleAddress naSeed;
BOOST_CHECK (naSeed.setSeedGeneric ("masterpassphrase"));
BOOST_CHECK_MESSAGE (naSeed.humanSeed () == "snoPBrXtMeMyMHUVTgbuqAfg1SUTb", naSeed.humanSeed ());
// Create node public/private key pair
RippleAddress naNodePublic = RippleAddress::createNodePublic (naSeed);
RippleAddress naNodePrivate = RippleAddress::createNodePrivate (naSeed);
BOOST_CHECK_MESSAGE (naNodePublic.humanNodePublic () == "n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9", naNodePublic.humanNodePublic ());
BOOST_CHECK_MESSAGE (naNodePrivate.humanNodePrivate () == "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe", naNodePrivate.humanNodePrivate ());
// Check node signing.
Blob vucTextSrc = strCopy ("Hello, nurse!");
uint256 uHash = Serializer::getSHA512Half (vucTextSrc);
Blob vucTextSig;
naNodePrivate.signNodePrivate (uHash, vucTextSig);
BOOST_CHECK_MESSAGE (naNodePublic.verifyNodePublic (uHash, vucTextSig), "Verify failed.");
// Construct a public generator from the seed.
RippleAddress naGenerator = RippleAddress::createGeneratorPublic (naSeed);
BOOST_CHECK_MESSAGE (naGenerator.humanGenerator () == "fhuJKrhSDzV2SkjLn9qbwm5AaRmrxDPfFsHDCP6yfDZWcxDFz4mt", naGenerator.humanGenerator ());
// Create account #0 public/private key pair.
RippleAddress naAccountPublic0 = RippleAddress::createAccountPublic (naGenerator, 0);
RippleAddress naAccountPrivate0 = RippleAddress::createAccountPrivate (naGenerator, naSeed, 0);
BOOST_CHECK_MESSAGE (naAccountPublic0.humanAccountID () == "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", naAccountPublic0.humanAccountID ());
BOOST_CHECK_MESSAGE (naAccountPublic0.humanAccountPublic () == "aBQG8RQAzjs1eTKFEAQXr2gS4utcDiEC9wmi7pfUPTi27VCahwgw", naAccountPublic0.humanAccountPublic ());
BOOST_CHECK_MESSAGE (naAccountPrivate0.humanAccountPrivate () == "p9JfM6HHi64m6mvB6v5k7G2b1cXzGmYiCNJf6GHPKvFTWdeRVjh", naAccountPrivate0.humanAccountPrivate ());
// Create account #1 public/private key pair.
RippleAddress naAccountPublic1 = RippleAddress::createAccountPublic (naGenerator, 1);
RippleAddress naAccountPrivate1 = RippleAddress::createAccountPrivate (naGenerator, naSeed, 1);
BOOST_CHECK_MESSAGE (naAccountPublic1.humanAccountID () == "r4bYF7SLUMD7QgSLLpgJx38WJSY12ViRjP", naAccountPublic1.humanAccountID ());
BOOST_CHECK_MESSAGE (naAccountPublic1.humanAccountPublic () == "aBPXpTfuLy1Bhk3HnGTTAqnovpKWQ23NpFMNkAF6F1Atg5vDyPrw", naAccountPublic1.humanAccountPublic ());
BOOST_CHECK_MESSAGE (naAccountPrivate1.humanAccountPrivate () == "p9JEm822LMrzJii1k7TvdphfENTp6G5jr253Xa5rkzUWVr8ogQt", naAccountPrivate1.humanAccountPrivate ());
// Check account signing.
BOOST_CHECK_MESSAGE (naAccountPrivate0.accountPrivateSign (uHash, vucTextSig), "Signing failed.");
BOOST_CHECK_MESSAGE (naAccountPublic0.accountPublicVerify (uHash, vucTextSig), "Verify failed.");
BOOST_CHECK_MESSAGE (!naAccountPublic1.accountPublicVerify (uHash, vucTextSig), "Anti-verify failed.");
BOOST_CHECK_MESSAGE (naAccountPrivate1.accountPrivateSign (uHash, vucTextSig), "Signing failed.");
BOOST_CHECK_MESSAGE (naAccountPublic1.accountPublicVerify (uHash, vucTextSig), "Verify failed.");
BOOST_CHECK_MESSAGE (!naAccountPublic0.accountPublicVerify (uHash, vucTextSig), "Anti-verify failed.");
// Check account encryption.
Blob vucTextCipher
= naAccountPrivate0.accountPrivateEncrypt (naAccountPublic1, vucTextSrc);
Blob vucTextRecovered
= naAccountPrivate1.accountPrivateDecrypt (naAccountPublic0, vucTextCipher);
BOOST_CHECK_MESSAGE (vucTextSrc == vucTextRecovered, "Encrypt-decrypt failed.");
}
BOOST_AUTO_TEST_SUITE_END ()
// vim:ts=4