Example #1
1
bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
{
    if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
        return false;

    int i = 0;
    if (nDerivationMethod == 0)
    {
        i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
                          (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV);
    }

    if (nDerivationMethod == 1)
    {
        // Passphrase conversion
        uint256 scryptHash = scrypt_salted_multiround_hash((const void*)strKeyData.c_str(), strKeyData.size(), &chSalt[0], 8, nRounds);

        i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
                          (unsigned char *)&scryptHash, sizeof scryptHash, nRounds, chKey, chIV);
        OPENSSL_cleanse(&scryptHash, sizeof scryptHash);
    }


    if (i != (int)WALLET_CRYPTO_KEY_SIZE)
    {
        OPENSSL_cleanse(chKey, sizeof(chKey));
        OPENSSL_cleanse(chIV, sizeof(chIV));
        return false;
    }

    fKeySet = true;
    return true;
}
Example #2
0
// General secure AES 256 CBC encryption routine
bool EncryptAES256(const SecureString& sKey, const SecureString& sPlaintext, const std::string& sIV, std::string& sCiphertext)
{
    // max ciphertext len for a n bytes of plaintext is
    // n + AES_BLOCK_SIZE - 1 bytes
    int nLen = sPlaintext.size();
    int nCLen = nLen + AES_BLOCK_SIZE;
    int nFLen = 0;

    // Verify key sizes
    if(sKey.size() != 32 || sIV.size() != AES_BLOCK_SIZE) {
        LogPrintf("crypter EncryptAES256 - Invalid key or block size: Key: %d sIV:%d\n", sKey.size(), sIV.size());
        return false;
    }

    // Prepare output buffer
    sCiphertext.resize(nCLen);

    // Perform the encryption
    EVP_CIPHER_CTX ctx;

    bool fOk = true;

    EVP_CIPHER_CTX_init(&ctx);
    if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, (const unsigned char*) &sKey[0], (const unsigned char*) &sIV[0]);
    if (fOk) fOk = EVP_EncryptUpdate(&ctx, (unsigned char*) &sCiphertext[0], &nCLen, (const unsigned char*) &sPlaintext[0], nLen);
    if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (unsigned char*) (&sCiphertext[0])+nCLen, &nFLen);
    EVP_CIPHER_CTX_cleanup(&ctx);

    if (!fOk) return false;

    sCiphertext.resize(nCLen + nFLen);
    return true;
}
Example #3
0
bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
{
    if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
        return false;

    // Try to keep the keydata out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
    // Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
    // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.  
    // mlock(&chKey[0], sizeof chKey);
    // mlock(&chIV[0], sizeof chIV);

    int i = 0;
    if (nDerivationMethod == 0)
        i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
                          (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV);

    if (i != (int)WALLET_CRYPTO_KEY_SIZE)
    {
        // memset(&chKey, 0, sizeof chKey);
        // memset(&chIV, 0, sizeof chIV);
        OPENSSL_cleanse(chKey, sizeof(chKey));
        OPENSSL_cleanse(chIV, sizeof(chIV));
        return false;
    }

    fKeySet = true;
    return true;
}
Example #4
0
int CCrypter::BytesToKeySHA512AES(const std::vector<unsigned char>& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const
{
    // This mimics the behavior of openssl's EVP_BytesToKey with an aes256cbc
    // cipher and sha512 message digest. Because sha512's output size (64b) is
    // greater than the aes256 block size (16b) + aes256 key size (32b),
    // there's no need to process more than once (D_0).

    if(!count || !key || !iv)
        return 0;

    unsigned char buf[CSHA512::OUTPUT_SIZE];
    CSHA512 di;

    di.Write((const unsigned char*)strKeyData.c_str(), strKeyData.size());
    di.Write(chSalt.data(), chSalt.size());
    di.Finalize(buf);

    for(int i = 0; i != count - 1; i++)
        di.Reset().Write(buf, sizeof(buf)).Finalize(buf);

    memcpy(key, buf, WALLET_CRYPTO_KEY_SIZE);
    memcpy(iv, buf + WALLET_CRYPTO_KEY_SIZE, WALLET_CRYPTO_IV_SIZE);
    memory_cleanse(buf, sizeof(buf));
    return WALLET_CRYPTO_KEY_SIZE;
}
Example #5
0
bool DecryptAES256(const SecureString& sKey, const std::string& sCiphertext, const std::string& sIV, SecureString& sPlaintext)
{
    // plaintext will always be equal to or lesser than length of ciphertext
    int nLen = sCiphertext.size();
    int nPLen = nLen, nFLen = 0;

    // Verify key sizes
    if(sKey.size() != 32 || sIV.size() != AES_BLOCK_SIZE) {
        LogPrintf("crypter DecryptAES256 - Invalid key or block size\n");
        return false;
    }

    sPlaintext.resize(nPLen);

    EVP_CIPHER_CTX ctx;

    bool fOk = true;

    EVP_CIPHER_CTX_init(&ctx);
    if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, (const unsigned char*) &sKey[0], (const unsigned char*) &sIV[0]);
    if (fOk) fOk = EVP_DecryptUpdate(&ctx, (unsigned char *) &sPlaintext[0], &nPLen, (const unsigned char *) &sCiphertext[0], nLen);
    if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (unsigned char *) (&sPlaintext[0])+nPLen, &nFLen);
    EVP_CIPHER_CTX_cleanup(&ctx);

    if (!fOk) return false;

    sPlaintext.resize(nPLen + nFLen);
    return true;
}
void permutation(int k, SecureString &s)
{
  for(unsigned int j = 1; j < s.size(); ++j)
    {
      swap(s, k % (j + 1), j);
      k = k / (j + 1);
    }
}
Example #7
0
void CKeePassIntegrator::CKeePassRequest::init()
{
    SecureString sIVSecure = generateRandomKey(KEEPASS_CRYPTO_BLOCK_SIZE);
    sIV = std::string(&sIVSecure[0], sIVSecure.size());
    // Generate Nonce, Verifier and RequestType
    SecureString sNonceBase64Secure = EncodeBase64Secure(sIVSecure);
    addStrParameter("Nonce", std::string(&sNonceBase64Secure[0], sNonceBase64Secure.size())); // Plain
    addStrParameter("Verifier", sNonceBase64Secure); // Encoded
    addStrParameter("RequestType", sType);
}
Example #8
0
// passphrase must be at most 256 characters or code may crash
void CMnemonic::ToSeed(SecureString mnemonic, SecureString passphrase, SecureVector& seedRet)
{
    SecureString ssSalt = SecureString("mnemonic") + passphrase;
    SecureVector vchSalt(ssSalt.begin(), ssSalt.end());
    seedRet.resize(64);
    // int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
    //                    const unsigned char *salt, int saltlen, int iter,
    //                    const EVP_MD *digest,
    //                    int keylen, unsigned char *out);
    PKCS5_PBKDF2_HMAC(mnemonic.c_str(), mnemonic.size(), &vchSalt[0], vchSalt.size(), 2048, EVP_sha512(), 64, &seedRet[0]);
}
Example #9
0
int __pass_cb(char *buf, int size, int rwflag, void *u) {
    Key::PassphraseFunctor* pf = (Key::PassphraseFunctor*)u;
    bool verify = (rwflag == 1);
    
    SecureString ss = (*pf)(verify);
    
    int len;
    len = ss.size();
    if (len <= 0) return 0;
    // if too long, truncate
    if (len > size) len = size;
    memcpy(buf, ss.c_str(), len);
    return len;
}
Example #10
0
void CKeePassIntegrator::rpcSetLogin(const SecureString& strWalletPass, const SecureString& sEntryId)
{

    // Convert key format
    SecureString sKey = DecodeBase64Secure(sKeyBase64);

    CKeePassRequest request(sKey, "set-login");
    request.addStrParameter("Id", sKeePassId);
    request.addStrParameter("Url", sUrl);

    if(fDebug) LogPrintf("CKeePassIntegrator::rpcSetLogin - send Url: %s\n", sUrl.c_str());

    //request.addStrParameter("SubmitUrl", sSubmitUrl); // Is used to construct the entry title
    request.addStrParameter("Login", SecureString("Nodes"));
    request.addStrParameter("Password", strWalletPass);
    if(sEntryId.size() != 0)
    {
        request.addStrParameter("Uuid", sEntryId); // Update existing
    }

    int nStatus;
    std::string sResponse;

    doHTTPPost(request.getJson(), nStatus, sResponse);


    if(fDebug) LogPrintf("CKeePassIntegrator::rpcSetLogin - send result: status: %d response: %s\n", nStatus, sResponse.c_str());

    if(nStatus != 200)
    {
        std::string sErrorMessage = "Error returned: HTTP code ";
        sErrorMessage += boost::lexical_cast<std::string>(nStatus);
        sErrorMessage += " - Response: ";
        sErrorMessage += " response: [";
        sErrorMessage += sResponse;
        sErrorMessage += "]";
        throw std::runtime_error(sErrorMessage);
    }

    // Parse the response
    CKeePassResponse response(sKey, sResponse);

    if(!response.getSuccess())
    {
        throw std::runtime_error("KeePassHttp returned failure status");
    }
}
Example #11
0
bool OldSetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod, unsigned char* chKey, unsigned char* chIV)
{
    if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
        return false;

    int i = 0;
    if (nDerivationMethod == 0)
        i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
                          (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV);

    if (i != (int)WALLET_CRYPTO_KEY_SIZE)
    {
        memory_cleanse(chKey, WALLET_CRYPTO_KEY_SIZE);
        memory_cleanse(chIV, WALLET_CRYPTO_IV_SIZE);
        return false;
    }
    return true;
}
Example #12
0
bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
{
    if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
        return false;

    int i = 0;
    if (nDerivationMethod == 0)
        i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
                          (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV);

    if (i != (int)WALLET_CRYPTO_KEY_SIZE)
    {
        OPENSSL_cleanse(chKey, sizeof(chKey));
        OPENSSL_cleanse(chIV, sizeof(chIV));
        return false;
    }

    fKeySet = true;
    return true;
}
Example #13
0
void CKeePassIntegrator::rpcAssociate(std::string& sId, SecureString& sKeyBase64)
{
    sKey = generateRandomKey(KEEPASS_CRYPTO_KEY_SIZE);
    CKeePassRequest request(sKey, "associate");

    sKeyBase64 = EncodeBase64Secure(sKey);
    request.addStrParameter("Key", std::string(&sKeyBase64[0], sKeyBase64.size()));

    int nStatus;
    std::string sResponse;

    doHTTPPost(request.getJson(), nStatus, sResponse);

    if(fDebug) LogPrintf("CKeePassIntegrator::rpcAssociate - send result: status: %d response: %s\n", nStatus, sResponse.c_str());

    if(nStatus != 200)
    {
        std::string sErrorMessage = "Error returned: HTTP code ";
        sErrorMessage += boost::lexical_cast<std::string>(nStatus);
        sErrorMessage += " - Response: ";
        sErrorMessage += " response: [";
        sErrorMessage += sResponse;
        sErrorMessage += "]";
        throw std::runtime_error(sErrorMessage);
    }

    // Parse the response
    CKeePassResponse response(sKey, sResponse);

    if(!response.getSuccess())
    {
        throw std::runtime_error("KeePassHttp returned failure status");
    }

    // If we got here, we were successful. Return the information
    sId = response.getStr("Id");
}
Example #14
0
bool CMnemonic::Check(SecureString mnemonic)
{
    if (mnemonic.empty()) {
        return false;
    }

    uint32_t nWordCount{};

    for (size_t i = 0; i < mnemonic.size(); ++i) {
        if (mnemonic[i] == ' ') {
            nWordCount++;
        }
    }
    nWordCount++;
    // check number of words
    if (nWordCount != 12 && nWordCount != 18 && nWordCount != 24) {
        return false;
    }

    SecureString ssCurrentWord;
    SecureVector bits(32 + 1);

    uint32_t nWordIndex, ki, nBitsCount{};

    for (size_t i = 0; i < mnemonic.size(); ++i)
    {
        ssCurrentWord = "";
        while (i + ssCurrentWord.size() < mnemonic.size() && mnemonic[i + ssCurrentWord.size()] != ' ') {
            if (ssCurrentWord.size() >= 9) {
                return false;
            }
            ssCurrentWord += mnemonic[i + ssCurrentWord.size()];
        }
        i += ssCurrentWord.size();
        nWordIndex = 0;
        for (;;) {
            if (!wordlist[nWordIndex]) { // word not found
                return false;
            }
            if (ssCurrentWord == wordlist[nWordIndex]) { // word found on index nWordIndex
                for (ki = 0; ki < 11; ki++) {
                    if (nWordIndex & (1 << (10 - ki))) {
                        bits[nBitsCount / 8] |= 1 << (7 - (nBitsCount % 8));
                    }
                    nBitsCount++;
                }
                break;
            }
            nWordIndex++;
        }
    }
    if (nBitsCount != nWordCount * 11) {
        return false;
    }
    bits[32] = bits[nWordCount * 4 / 3];
    CSHA256().Write(&bits[0], nWordCount * 4 / 3).Finalize(&bits[0]);

    bool fResult = 0;
    if (nWordCount == 12) {
        fResult = (bits[0] & 0xF0) == (bits[32] & 0xF0); // compare first 4 bits
    } else
    if (nWordCount == 18) {
        fResult = (bits[0] & 0xFC) == (bits[32] & 0xFC); // compare first 6 bits
    } else
    if (nWordCount == 24) {
        fResult = bits[0] == bits[32]; // compare 8 bits
    }

    return fResult;
}
int main(int argc, char* argv[])
{
  if (argc != 7){
    printf("Hashchecker needs to know the cryptographic details of your wallet!\nUsage: hashchecker pw_to_permute iterations salt crypted_key public_key crypted_secret\n");
    return 1;
  }
  CCrypter crypter;
  CKeyingMaterial vMasterKey;

  // Try any password as input
  SecureString attempt = argv[1];

  const unsigned int nDeriveIterations = atoi(argv[2]);//29731;
  const vector<unsigned char> chSalt = Convert(argv[3]);//"b29a2e128e8e0a2f");//argv[1];
  const vector<unsigned char> vchCryptedKey = Convert(argv[4]);//"982a07407ccb8d70514e7b7ccae4b53d68318ec41fd2bf99bf9dbcafd2f150a92c6eb8f9ea743b782fc5b85403421c1d");//argv[2];
  const vector<unsigned char> vchPubKey = Convert(argv[5]);//"03fefd771544971f3ab95b041bbce02cc799a335d0d12c3bcd46c7c61a4e3ba897");
  const vector<unsigned char> vchCryptedSecret = Convert(argv[6]);//"17169083a74b07ff3497027af7423b9aec1593c90f15a57f52c368593947c85e37b03430840ad48ef409e97ba5a4cdeb");

  double count = Factorial(attempt.size());
  bool found = false;

  for (int i = 0; i <= count; i++)
    {
      if (i > 0) {//test the word as typed in on first iteration
        permutation(i-1, attempt);
      }

      const SecureString strWalletPassphrase = attempt;
      cout << i << "-" << strWalletPassphrase <<"\n";
      if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, chSalt, nDeriveIterations, 0))
        {
          cout << i << " " << strWalletPassphrase <<"\n";
          continue;
        }
      if (!crypter.Decrypt(vchCryptedKey, vMasterKey))
        {
          cout << i << " " << strWalletPassphrase <<"\n";
          continue;
        }

      CSecret vchSecret;
      if(!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
        {
          cout << "** didn't decrypt **" <<"\n";
          continue;
        }
      if (vchSecret.size() != 32)
        {
          cout << "** wrong size secret **" <<"\n";
          continue;
        }
      CKey key;
      key.SetPubKey(vchPubKey);
      key.SetSecret(vchSecret);
      if (key.GetPubKey() == vchPubKey)
        {
          cout<<"Found one: "<<strWalletPassphrase<<"\n";
          found = true;
          break;
        }
      // else
      //     cout << "** didn't get the pubkey back **\n";
    }
  if (found)
    cout << "Found it! Congratulations\n";
  return 0;
}