Ejemplo n.º 1
0
/////////////////////////////////////////////////////////////////////////////
// Same as above, but only changing the AES mode of operation (CBC, not CFB)
SecureBinaryData CryptoAES::DecryptCBC(SecureBinaryData & data, 
                                       SecureBinaryData & key,
                                       SecureBinaryData   iv  )
{
   if(CRYPTO_DEBUG)
   {
      cout << "AES Decrypt" << endl;
      cout << "   BinData: " << data.toHexStr() << endl;
      cout << "   BinKey : " << key.toHexStr() << endl;
      cout << "   BinIV  : " << iv.toHexStr() << endl;
   }

   if(data.getSize() == 0)
      return SecureBinaryData(0);

   SecureBinaryData unencrData(data.getSize());

   BTC_CBC_MODE<BTC_AES>::Decryption aes_enc( (byte*)key.getPtr(), 
                                                     key.getSize(), 
                                              (byte*)iv.getPtr());

   aes_enc.ProcessData( (byte*)unencrData.getPtr(), 
                        (byte*)data.getPtr(), 
                               data.getSize());
   return unencrData;
}
Ejemplo n.º 2
0
/////////////////////////////////////////////////////////////////////////////
// Same as above, but only changing the AES mode of operation (CBC, not CFB)
SecureBinaryData CryptoAES::EncryptCBC(SecureBinaryData & data, 
                                       SecureBinaryData & key,
                                       SecureBinaryData & iv)
{
   if(CRYPTO_DEBUG)
   {
      cout << "AES Decrypt" << endl;
      cout << "   BinData: " << data.toHexStr() << endl;
      cout << "   BinKey : " << key.toHexStr() << endl;
      cout << "   BinIV  : " << iv.toHexStr() << endl;
   }

   if(data.getSize() == 0)
      return SecureBinaryData(0);

   SecureBinaryData encrData(data.getSize());

   // Caller can supply their own IV/entropy, or let it be generated here
   // (variable "iv" is a reference, so check it on the way out)
   if(iv.getSize() == 0)
      iv = SecureBinaryData().GenerateRandom(BTC_AES::BLOCKSIZE);


   BTC_CBC_MODE<BTC_AES>::Encryption aes_enc( (byte*)key.getPtr(), 
                                                     key.getSize(), 
                                              (byte*)iv.getPtr());

   aes_enc.ProcessData( (byte*)encrData.getPtr(), 
                        (byte*)data.getPtr(), 
                               data.getSize());

   return encrData;
}
Ejemplo n.º 3
0
SecureBinaryData CryptoECDSA::SignData(SecureBinaryData const & binToSign, 
                                       SecureBinaryData const & binPrivKey)
{
   if(CRYPTO_DEBUG)
   {
      cout << "SignData:" << endl;
      cout << "   BinSgn: " << binToSign.getSize() << " " << binToSign.toHexStr() << endl;
      cout << "   BinPrv: " << binPrivKey.getSize() << " " << binPrivKey.toHexStr() << endl;
   }
   BTC_PRIVKEY cppPrivKey = ParsePrivateKey(binPrivKey);
   return SignData(binToSign, cppPrivKey);
}
Ejemplo n.º 4
0
bool CryptoECDSA::CheckPubPrivKeyMatch(SecureBinaryData const & privKey32,
                                       SecureBinaryData const & pubKey65)
{
   if(CRYPTO_DEBUG)
   {
      cout << "CheckPubPrivKeyMatch:" << endl;
      cout << "   BinPrv: " << privKey32.toHexStr() << endl;
      cout << "   BinPub: " << pubKey65.toHexStr() << endl;
   }

   BTC_PRIVKEY privKey = ParsePrivateKey(privKey32);
   BTC_PUBKEY  pubKey  = ParsePublicKey(pubKey65);
   return CheckPubPrivKeyMatch(privKey, pubKey);
}
Ejemplo n.º 5
0
/////////////////////////////////////////////////////////////////////////////
// Deterministically generate new public key using a chaincode
SecureBinaryData CryptoECDSA::ComputeChainedPublicKey(
                                SecureBinaryData const & binPubKey,
                                SecureBinaryData const & chainCode,
                                SecureBinaryData* multiplierOut)
{
   if(CRYPTO_DEBUG)
   {
      cout << "ComputeChainedPUBLICKey:" << endl;
      cout << "   BinPub: " << binPubKey.toHexStr() << endl;
      cout << "   BinChn: " << chainCode.toHexStr() << endl;
   }
   static SecureBinaryData SECP256K1_ORDER_BE = SecureBinaryData::CreateFromHex(
           "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");

   // Added extra entropy to chaincode by xor'ing with hash256 of pubkey
   BinaryData chainMod  = binPubKey.getHash256();
   BinaryData chainOrig = chainCode.getRawCopy();
   BinaryData chainXor(32);
      
   for(uint8_t i=0; i<8; i++)
   {
      uint8_t offset = 4*i;
      *(uint32_t*)(chainXor.getPtr()+offset) =
                           *(uint32_t*)( chainMod.getPtr()+offset) ^ 
                           *(uint32_t*)(chainOrig.getPtr()+offset);
   }

   // Parse the chaincode as a big-endian integer
   CryptoPP::Integer mult;
   mult.Decode(chainXor.getPtr(), chainXor.getSize(), UNSIGNED);

   // "new" init as "old", to make sure it's initialized on the correct curve
   BTC_PUBKEY oldPubKey = ParsePublicKey(binPubKey); 
   BTC_PUBKEY newPubKey = ParsePublicKey(binPubKey);

   // Let Crypto++ do the EC math for us, serialize the new public key
   newPubKey.SetPublicElement( oldPubKey.ExponentiatePublicElement(mult) );

   if(multiplierOut != NULL)
      (*multiplierOut) = SecureBinaryData(chainXor);

   //LOGINFO << "Computed new chained public key using:";
   //LOGINFO << "   Public key: " << binPubKey.toHexStr().c_str();
   //LOGINFO << "   PubKeyHash: " << chainMod.toHexStr().c_str();
   //LOGINFO << "   Chaincode:  " << chainOrig.toHexStr().c_str();
   //LOGINFO << "   Multiplier: " << chainXor.toHexStr().c_str();

   return CryptoECDSA::SerializePublicKey(newPubKey);
}
Ejemplo n.º 6
0
bool CryptoECDSA::VerifyData(SecureBinaryData const & binMessage, 
                             SecureBinaryData const & binSignature,
                             SecureBinaryData const & pubkey65B)
{
   if(CRYPTO_DEBUG)
   {
      cout << "VerifyData:" << endl;
      cout << "   BinMsg: " << binMessage.toHexStr() << endl;
      cout << "   BinSig: " << binSignature.toHexStr() << endl;
      cout << "   BinPub: " << pubkey65B.toHexStr() << endl;
   }

   BTC_PUBKEY cppPubKey = ParsePublicKey(pubkey65B);
   return VerifyData(binMessage, binSignature, cppPubKey);
}
Ejemplo n.º 7
0
bool CryptoECDSA::VerifyPublicKeyValid(SecureBinaryData const & pubKey65)
{
   if(CRYPTO_DEBUG)
   {
      cout << "BinPub: " << pubKey65.toHexStr() << endl;
   }

   // Basically just copying the ParsePublicKey method, but without
   // the assert that would throw an error from C++
   SecureBinaryData pubXbin(pubKey65.getSliceRef( 1,32));
   SecureBinaryData pubYbin(pubKey65.getSliceRef(33,32));
   CryptoPP::Integer pubX;
   CryptoPP::Integer pubY;
   pubX.Decode(pubXbin.getPtr(), pubXbin.getSize(), UNSIGNED);
   pubY.Decode(pubYbin.getPtr(), pubYbin.getSize(), UNSIGNED);
   BTC_ECPOINT publicPoint(pubX, pubY);

   // Initialize the public key with the ECP point just created
   BTC_PUBKEY cppPubKey;
   cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), publicPoint);

   // Validate the public key -- not sure why this needs a PRNG
   static BTC_PRNG prng;
   return cppPubKey.Validate(prng, 3);
}
Ejemplo n.º 8
0
SecureBinaryData CryptoAES::Encrypt(SecureBinaryData & data, 
                                    SecureBinaryData & key,
                                    SecureBinaryData & iv)
{
   if(CRYPTO_DEBUG)
   {
      cout << "AES Decrypt" << endl;
      cout << "   BinData: " << data.toHexStr() << endl;
      cout << "   BinKey : " << key.toHexStr() << endl;
      cout << "   BinIV  : " << iv.toHexStr() << endl;
   }


   if(data.getSize() == 0)
      return SecureBinaryData(0);

   SecureBinaryData encrData(data.getSize());
   //cout << "   StartPlain: " << data.toHexStr() << endl;
   //cout << "   Key Data  : " << key.toHexStr() << endl;

   // Caller can supply their own IV/entropy, or let it be generated here
   if(iv.getSize() == 0)
      iv = SecureBinaryData().GenerateRandom(BTC_AES::BLOCKSIZE);


   BTC_AES_MODE<BTC_AES>::Encryption aes_enc( (byte*)key.getPtr(), 
                                                     key.getSize(), 
                                              (byte*)iv.getPtr());

   aes_enc.ProcessData( (byte*)encrData.getPtr(), 
                        (byte*)data.getPtr(), 
                               data.getSize());

   //cout << "   IV Data   : " << iv.toHexStr() << endl;
   //cout << "   Ciphertext: " << encrData.toHexStr() << endl;
   return encrData;
}
Ejemplo n.º 9
0
bool CryptoECDSA::VerifyPublicKeyValid(SecureBinaryData const & pubKey)
{
   if(CRYPTO_DEBUG)
   {
      cout << "BinPub: " << pubKey.toHexStr() << endl;
   }

   SecureBinaryData keyToCheck(65);

   // To support compressed keys, we'll just check to see if a key is compressed
   // and then decompress it.
   if(pubKey.getSize() == 33) {
      keyToCheck = UncompressPoint(pubKey);
   }
   else {
      keyToCheck = pubKey;
   }

   // Basically just copying the ParsePublicKey method, but without
   // the assert that would throw an error from C++
   SecureBinaryData pubXbin(keyToCheck.getSliceRef( 1,32));
   SecureBinaryData pubYbin(keyToCheck.getSliceRef(33,32));
   CryptoPP::Integer pubX;
   CryptoPP::Integer pubY;
   pubX.Decode(pubXbin.getPtr(), pubXbin.getSize(), UNSIGNED);
   pubY.Decode(pubYbin.getPtr(), pubYbin.getSize(), UNSIGNED);
   BTC_ECPOINT publicPoint(pubX, pubY);

   // Initialize the public key with the ECP point just created
   BTC_PUBKEY cppPubKey;
   cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), publicPoint);

   // Validate the public key -- not sure why this needs a PRNG
   BTC_PRNG prng;
   return cppPubKey.Validate(prng, 3);
}
Ejemplo n.º 10
0
void TestECDSA(void)
{

   SecureBinaryData msgToSign("This message came from me!");
   SecureBinaryData privData = SecureBinaryData().GenerateRandom(32);
   BTC_PRIVKEY privKey = CryptoECDSA().ParsePrivateKey(privData);
   BTC_PUBKEY  pubKey  = CryptoECDSA().ComputePublicKey(privKey);

   // Test key-match check
   cout << "Do the pub-priv keypair we just created match? ";
   cout << (CryptoECDSA().CheckPubPrivKeyMatch(privKey, pubKey) ? 1 : 0) << endl;
   cout << endl;
   
   SecureBinaryData signature = CryptoECDSA().SignData(msgToSign, privKey);
   cout << "Signature = " << signature.toHexStr() << endl;
   cout << endl;

   bool isValid = CryptoECDSA().VerifyData(msgToSign, signature, pubKey);
   cout << "SigValid? = " << (isValid ? 1 : 0) << endl;
   cout << endl;

   // Test signature from blockchain:
   SecureBinaryData msg = SecureBinaryData::CreateFromHex("0100000001bb664ff716b9dfc831bcc666c1767f362ad467fcfbaf4961de92e45547daab870100000062537a7652a269537a829178a91480677c5392220db736455533477d0bc2fba65502879b69537a829178a91402d7aa2e76d9066fb2b3c41ff8839a5c81bdca19879b69537a829178a91410039ce4fdb5d4ee56148fe3935b9bfbbe4ecc89879b6953aeffffffff0280969800000000001976a9140817482d2e97e4be877efe59f4bae108564549f188ac7015a7000000000062537a7652a269537a829178a91480677c5392220db736455533477d0bc2fba65502879b69537a829178a91402d7aa2e76d9066fb2b3c41ff8839a5c81bdca19879b69537a829178a91410039ce4fdb5d4ee56148fe3935b9bfbbe4ecc89879b6953ae0000000001000000");
   SecureBinaryData px  = SecureBinaryData::CreateFromHex("8c006ff0d2cfde86455086af5a25b88c2b81858aab67f6a3132c885a2cb9ec38");
   SecureBinaryData py  = SecureBinaryData::CreateFromHex("e700576fd46c7d72d7d22555eee3a14e2876c643cd70b1b0a77fbf46e62331ac");
   SecureBinaryData pub65  = SecureBinaryData::CreateFromHex("048c006ff0d2cfde86455086af5a25b88c2b81858aab67f6a3132c885a2cb9ec38e700576fd46c7d72d7d22555eee3a14e2876c643cd70b1b0a77fbf46e62331ac");
   //SecureBinaryData sig = SecureBinaryData::CreateFromHex("3046022100d73f633f114e0e0b324d87d38d34f22966a03b072803afa99c9408201f6d6dc6022100900e85be52ad2278d24e7edbb7269367f5f2d6f1bd338d017ca4600087766144");
   SecureBinaryData sig = SecureBinaryData::CreateFromHex("d73f633f114e0e0b324d87d38d34f22966a03b072803afa99c9408201f6d6dc6900e85be52ad2278d24e7edbb7269367f5f2d6f1bd338d017ca4600087766144");
   pubKey = CryptoECDSA().ParsePublicKey(px,py);
   isValid = CryptoECDSA().VerifyData(msg, sig, pubKey);
   cout << "SigValid? = " << (isValid ? 1 : 0) << endl;


   // Test speed on signature:
   uint32_t nTest = 50;
   cout << "Test signature and verification speeds"  << endl;
   cout << "\nTiming Signing";
   TIMER_START("SigningTime");
   for(uint32_t i=0; i<nTest; i++)
   {
      // This timing includes key parsing
      CryptoECDSA().SignData(msgToSign, privData);
   }
   TIMER_STOP("SigningTime");

   // Test speed of verification
   TIMER_START("VerifyTime");
   cout << "\nTiming Verify";
   for(uint32_t i=0; i<nTest; i++)
   {
      // This timing includes key parsing
      CryptoECDSA().VerifyData(msg, sig, pub65);
   }
   TIMER_STOP("VerifyTime");

   cout << endl;
   cout << "Timing (Signing): " << 1/(TIMER_READ_SEC("SigningTime")/nTest)
        << " signatures/sec" << endl;
   cout << "Timing (Verify):  " << 1/(TIMER_READ_SEC("VerifyTime")/nTest)
        << " verifies/sec" << endl;


   // Test deterministic key generation
   SecureBinaryData privDataOrig = SecureBinaryData().GenerateRandom(32);
   BTC_PRIVKEY privOrig = CryptoECDSA().ParsePrivateKey(privDataOrig);
   BTC_PUBKEY  pubOrig  = CryptoECDSA().ComputePublicKey(privOrig);
   cout << "Testing deterministic key generation" << endl;
   cout << "   Verify again that pub/priv objects pair match : ";
   cout << (CryptoECDSA().CheckPubPrivKeyMatch(privOrig, pubOrig) ? 1 : 0) << endl;

   SecureBinaryData binPriv = CryptoECDSA().SerializePrivateKey(privOrig);
   SecureBinaryData binPub  = CryptoECDSA().SerializePublicKey(pubOrig);
   cout << "   Verify again that binary pub/priv pair match  : ";
   cout << (CryptoECDSA().CheckPubPrivKeyMatch(binPriv, binPub) ? 1 : 0) << endl;
   cout << endl;

   SecureBinaryData chaincode = SecureBinaryData().GenerateRandom(32);
   cout << "   Starting privKey:" << binPriv.toHexStr() << endl;
   cout << "   Starting pubKey :" << binPub.toHexStr() << endl;
   cout << "   Chaincode       :" << chaincode.toHexStr() << endl;
   cout << endl;
   
   SecureBinaryData newBinPriv = CryptoECDSA().ComputeChainedPrivateKey(binPriv, chaincode);
   SecureBinaryData newBinPubA = CryptoECDSA().ComputePublicKey(newBinPriv);
   SecureBinaryData newBinPubB = CryptoECDSA().ComputeChainedPublicKey(binPub, chaincode);
   cout << "   Verify new binary pub/priv pair match: ";
   cout << (CryptoECDSA().CheckPubPrivKeyMatch(newBinPriv, newBinPubA) ? 1 : 0) << endl;
   cout << "   Verify new binary pub/priv pair match: ";
   cout << (CryptoECDSA().CheckPubPrivKeyMatch(newBinPriv, newBinPubB) ? 1 : 0) << endl;
   cout << "   New privKey:" << newBinPriv.toHexStr() << endl;
   cout << "   New pubKeyA:" << newBinPubA.getSliceCopy(0,30).toHexStr() << "..." << endl;
   cout << "   New pubKeyB:" << newBinPubB.getSliceCopy(0,30).toHexStr() << "..." << endl;
   cout << endl;


   // Test arbitrary scalar/point operations
   BinaryData a = BinaryData::CreateFromHex("8c006ff0d2cfde86455086af5a25b88c2b81858aab67f6a3132c885a2cb9ec38");
   BinaryData b = BinaryData::CreateFromHex("e700576fd46c7d72d7d22555eee3a14e2876c643cd70b1b0a77fbf46e62331ac");
   BinaryData c = BinaryData::CreateFromHex("f700576fd46c7d72d7d22555eee3a14e2876c643cd70b1b0a77fbf46e62331ac");
   BinaryData d = BinaryData::CreateFromHex("8130904787384d72d7d22555eee3a14e2876c643cd70b1b0a77fbf46e62331ac");
   BinaryData e = CryptoECDSA().ECMultiplyScalars(a,b);
   BinaryData f = CryptoECDSA().ECMultiplyPoint(a, b, c);
   BinaryData g = CryptoECDSA().ECAddPoints(a, b, c, d);
}
Ejemplo n.º 11
0
void TestCrypto(void)
{

   SecureBinaryData a("aaaaaaaaaa");
   SecureBinaryData b; b.resize(5);
   SecureBinaryData c; c.resize(0);

   a.copyFrom(b);
   b.copyFrom(c);
   c.copyFrom(a);

   a.resize(0);
   b = a;
   SecureBinaryData d(a); 

   cout << "a=" << a.toHexStr() << endl;
   cout << "b=" << b.toHexStr() << endl;
   cout << "c=" << c.toHexStr() << endl;
   cout << "d=" << d.toHexStr() << endl;

   SecureBinaryData e("eeeeeeeeeeeeeeee");
   SecureBinaryData f("ffffffff");
   SecureBinaryData g(0);

   e = g.copy();
   e = f.copy();

   cout << "e=" << e.toHexStr() << endl;
   cout << "f=" << f.toHexStr() << endl;
   cout << "g=" << g.toHexStr() << endl;
   
   

   /////////////////////////////////////////////////////////////////////////////
   // Start Key-Derivation-Function (KDF) Tests.  
   // ROMIX is the provably memory-hard (GPU-resistent) algorithm proposed by 
   // Colin Percival, who is the creator of Scrypt.  
   cout << endl << endl;
   cout << "Executing Key-Derivation-Function (KDF) tests" << endl;
   KdfRomix kdf;  
   kdf.computeKdfParams();
   kdf.printKdfParams();

   SecureBinaryData passwd1("This is my first password");
   SecureBinaryData passwd2("This is my first password.");
   SecureBinaryData passwd3("This is my first password");
   SecureBinaryData key;

   cout << "   Password1: '" << passwd1.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd1);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   cout << "   Password2: '" << passwd2.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd2);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   cout << "   Password1: '" << passwd3.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd3);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   /////////////////////////////////////////////////////////////////////////////
   cout << "Executing KDF tests with longer compute time" << endl;
   kdf.computeKdfParams(1.0);
   kdf.printKdfParams();

   cout << "   Password1: '" << passwd1.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd1);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   cout << "   Password2: '" << passwd2.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd2);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   cout << "   Password1: '" << passwd3.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd3);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   /////////////////////////////////////////////////////////////////////////////
   cout << "Executing KDF tests with limited memory target" << endl;
   kdf.computeKdfParams(1.0, 256*1024);
   kdf.printKdfParams();

   cout << "   Password1: '" << passwd1.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd1);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   cout << "   Password2: '" << passwd2.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd2);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   cout << "   Password1: '" << passwd3.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd3);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   /////////////////////////////////////////////////////////////////////////////
   cout << "KDF with min memory requirement (1 kB)" << endl;
   kdf.computeKdfParams(1.0, 0);
   kdf.printKdfParams();

   cout << "   Password1: '" << passwd1.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd1);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   cout << "   Password2: '" << passwd2.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd2);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   cout << "   Password1: '" << passwd3.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd3);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   /////////////////////////////////////////////////////////////////////////////
   cout << "KDF with 0 compute time" << endl;
   kdf.computeKdfParams(0, 0);
   kdf.printKdfParams();

   cout << "   Password1: '" << passwd1.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd1);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   cout << "   Password2: '" << passwd2.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd2);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   cout << "   Password1: '" << passwd3.toBinStr() << "'" << endl;
   key = kdf.DeriveKey(passwd3);
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;

   // Test AES code using NIST test vectors
   /// *** Test 1 *** ///
   cout << endl << endl;
   SecureBinaryData testIV, plaintext, cipherTarg, cipherComp, testKey, rtPlain;
   testKey.createFromHex   ("0000000000000000000000000000000000000000000000000000000000000000");
   testIV.createFromHex    ("80000000000000000000000000000000");
   plaintext.createFromHex ("00000000000000000000000000000000");
   cipherTarg.createFromHex("ddc6bf790c15760d8d9aeb6f9a75fd4e");

   cout << "   Plain        : " << plaintext.toHexStr() << endl;
   cipherComp = CryptoAES().EncryptCFB(plaintext, testKey, testIV);
   cout << "   CipherTarget : " << cipherComp.toHexStr() << endl;
   cout << "   CipherCompute: " << cipherComp.toHexStr() << endl;
   rtPlain = CryptoAES().DecryptCFB(cipherComp, testKey, testIV);
   cout << "   Plain        : " << rtPlain.toHexStr() << endl;


   /// *** Test 2 *** ///
   cout << endl << endl;
   testKey.createFromHex   ("0000000000000000000000000000000000000000000000000000000000000000");
   testIV.createFromHex    ("014730f80ac625fe84f026c60bfd547d");
   plaintext.createFromHex ("00000000000000000000000000000000");
   cipherTarg.createFromHex("5c9d844ed46f9885085e5d6a4f94c7d7");

   cout << "   Plain        : " << plaintext.toHexStr() << endl;
   cipherComp = CryptoAES().EncryptCFB(plaintext, testKey, testIV);
   cout << "   CipherTarget : " << cipherComp.toHexStr() << endl;
   cout << "   CipherCompute: " << cipherComp.toHexStr() << endl;
   rtPlain = CryptoAES().DecryptCFB(cipherComp, testKey, testIV);
   cout << "   Plain        : " << rtPlain.toHexStr() << endl;

   /// *** Test 3 *** ///
   cout << endl << endl;
   testKey.createFromHex   ("ffffffffffff0000000000000000000000000000000000000000000000000000");
   testIV.createFromHex    ("00000000000000000000000000000000");
   plaintext.createFromHex ("00000000000000000000000000000000");
   cipherTarg.createFromHex("225f068c28476605735ad671bb8f39f3");

   cout << "   Plain        : " << plaintext.toHexStr() << endl;
   cipherComp = CryptoAES().EncryptCFB(plaintext, testKey, testIV);
   cout << "   CipherTarget : " << cipherComp.toHexStr() << endl;
   cout << "   CipherCompute: " << cipherComp.toHexStr() << endl;
   rtPlain = CryptoAES().DecryptCFB(cipherComp, testKey, testIV);
   cout << "   Plain        : " << rtPlain.toHexStr() << endl;


   /// My own test, for sanity (can only check the roundtrip values)
   // This test is a lot more exciting with the couts uncommented in Encrypt/Decrypt
   cout << endl << endl;
   cout << "Starting some kdf-aes-combined tests..." << endl;
   kdf.printKdfParams();
   testKey = kdf.DeriveKey(SecureBinaryData("This passphrase is tough to guess"));
   SecureBinaryData secret, cipher;
   secret.createFromHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
   SecureBinaryData randIV(0);  // tell the crypto to generate a random IV for me.

   cout << "Encrypting:" << endl;
   cipher = CryptoAES().EncryptCFB(secret, testKey, randIV);
   cout << endl << endl;
   cout << "Decrypting:" << endl;
   secret = CryptoAES().DecryptCFB(cipher, testKey, randIV);
   cout << endl << endl;

   // Now encrypting so I can store the encrypted data in file
   cout << "Encrypting again:" << endl;
   cipher = CryptoAES().EncryptCFB(secret, testKey, randIV);

   ofstream testfile("safefile.txt", ios::out);
   testfile << "KdfParams " << endl;
   testfile << "   MemReqts " << kdf.getMemoryReqtBytes() << endl;
   testfile << "   NumIters " << kdf.getNumIterations() << endl;
   testfile << "   HexSalt  " << kdf.getSalt().toHexStr() << endl;
   testfile << "EncryptedData" << endl;
   testfile << "   HexIV    " << randIV.toHexStr() << endl;
   testfile << "   Cipher   " << cipher.toHexStr() << endl;
   testfile.close();
   
   ifstream infile("safefile.txt", ios::in);
   uint32_t mem, nIters;
   SecureBinaryData salt, iv;
   char deadstr[256];
   char hexstr[256];

   infile >> deadstr;
   infile >> deadstr >> mem;
   infile >> deadstr >> nIters;
   infile >> deadstr >> hexstr;
   salt.copyFrom( SecureBinaryData::CreateFromHex(string(hexstr, 64)));
   infile >> deadstr;
   infile >> deadstr >> hexstr;
   iv.copyFrom( SecureBinaryData::CreateFromHex(string(hexstr, 64)));
   infile >> deadstr >> hexstr;
   cipher.copyFrom( SecureBinaryData::CreateFromHex(string(hexstr, 64)));
   infile.close();
   cout << endl << endl;

   // Will try this twice, once with correct passphrase, once without
   SecureBinaryData cipherTry1 = cipher;
   SecureBinaryData cipherTry2 = cipher;
   SecureBinaryData newKey;

   KdfRomix newKdf(mem, nIters, salt);
   newKdf.printKdfParams();

   // First test with the wrong passphrase
   cout << "Attempting to decrypt with wrong passphrase" << endl;
   SecureBinaryData passphrase = SecureBinaryData("This is the wrong passphrase");
   newKey = newKdf.DeriveKey( passphrase );
   CryptoAES().DecryptCFB(cipherTry1, newKey, iv);


   // Now try correct passphrase
   cout << "Attempting to decrypt with CORRECT passphrase" << endl;
   passphrase = SecureBinaryData("This passphrase is tough to guess");
   newKey = newKdf.DeriveKey( passphrase );
   CryptoAES().DecryptCFB(cipherTry2, newKey, iv);
}
Ejemplo n.º 12
0
/////////////////////////////////////////////////////////////////////////////
// Deterministically generate new private key using a chaincode
// Changed:  added using the hash of the public key to the mix
//           b/c multiplying by the chaincode alone is too "linear"
//           (there's no reason to believe it's insecure, but it doesn't
//           hurt to add some extra entropy/non-linearity to the chain
//           generation process)
SecureBinaryData CryptoECDSA::ComputeChainedPrivateKey(
                                 SecureBinaryData const & binPrivKey,
                                 SecureBinaryData const & chainCode,
                                 SecureBinaryData binPubKey,
                                 SecureBinaryData* multiplierOut)
{
   if(CRYPTO_DEBUG)
   {
      cout << "ComputeChainedPrivateKey:" << endl;
      cout << "   BinPrv: " << binPrivKey.toHexStr() << endl;
      cout << "   BinChn: " << chainCode.toHexStr() << endl;
      cout << "   BinPub: " << binPubKey.toHexStr() << endl;
   }


   if( binPubKey.getSize()==0 )
      binPubKey = ComputePublicKey(binPrivKey);

   if( binPrivKey.getSize() != 32 || chainCode.getSize() != 32)
   {
      LOGERR << "***ERROR:  Invalid private key or chaincode (both must be 32B)";
      LOGERR << "BinPrivKey: " << binPrivKey.getSize();
      LOGERR << "BinPrivKey: (not logged for security)";
      //LOGERR << "BinPrivKey: " << binPrivKey.toHexStr();
      LOGERR << "BinChain  : " << chainCode.getSize();
      LOGERR << "BinChain  : " << chainCode.toHexStr();
   }

   // Adding extra entropy to chaincode by xor'ing with hash256 of pubkey
   BinaryData chainMod  = binPubKey.getHash256();
   BinaryData chainOrig = chainCode.getRawCopy();
   BinaryData chainXor(32);
      
   for(uint8_t i=0; i<8; i++)
   {
      uint8_t offset = 4*i;
      *(uint32_t*)(chainXor.getPtr()+offset) =
                           *(uint32_t*)( chainMod.getPtr()+offset) ^ 
                           *(uint32_t*)(chainOrig.getPtr()+offset);
   }


   // Hard-code the order of the group
   static SecureBinaryData SECP256K1_ORDER_BE = SecureBinaryData().CreateFromHex(
           "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
   
   CryptoPP::Integer mult, origPrivExp, ecOrder;
   // A 
   mult.Decode(chainXor.getPtr(), chainXor.getSize(), UNSIGNED);
   // B 
   origPrivExp.Decode(binPrivKey.getPtr(), binPrivKey.getSize(), UNSIGNED);
   // C
   ecOrder.Decode(SECP256K1_ORDER_BE.getPtr(), SECP256K1_ORDER_BE.getSize(), UNSIGNED);

   // A*B mod C will get us a new private key exponent
   CryptoPP::Integer newPrivExponent = 
                  a_times_b_mod_c(mult, origPrivExp, ecOrder);

   // Convert new private exponent to big-endian binary string 
   SecureBinaryData newPrivData(32);
   newPrivExponent.Encode(newPrivData.getPtr(), newPrivData.getSize(), UNSIGNED);

   if(multiplierOut != NULL)
      (*multiplierOut) = SecureBinaryData(chainXor);

   //LOGINFO << "Computed new chained private key using:";
   //LOGINFO << "   Public key: " << binPubKey.toHexStr().c_str();
   //LOGINFO << "   PubKeyHash: " << chainMod.toHexStr().c_str();
   //LOGINFO << "   Chaincode:  " << chainOrig.toHexStr().c_str();
   //LOGINFO << "   Multiplier: " << chainXor.toHexStr().c_str();

   return newPrivData;
}