// static bool OTKeyring::IOS_StoreSecret(const OTString& strUser, const OTPassword& thePassword, const std::string& str_display) { OT_ASSERT(strUser.Exists()); OT_ASSERT(thePassword.getMemorySize() > 0); CFStringRef service_name = CFSTR("opentxs"); CFStringRef account_name = CFStringCreateWithCString(nullptr, strUser.Get(), kCFStringEncodingUTF8); CFDataRef vData = CFDataCreateWithBytesNoCopy( nullptr, thePassword.getMemory_uint8(), thePassword.getMemorySize(), kCFAllocatorNull); const void* keys[] = {kSecClass, kSecAttrService, kSecAttrAccount, kSecValueData}; const void* values[] = {kSecClassGenericPassword, service_name, account_name, vData}; CFDictionaryRef item = CFDictionaryCreate(nullptr, keys, values, 4, nullptr, nullptr); OSStatus theError = SecItemAdd(item, nullptr); CFRelease(item); CFRelease(vData); CFRelease(account_name); if (theError != noErr) { otErr << "OTKeyring::IOS_StoreSecret: Error in SecItemAdd.\n"; return false; } return true; }
serializedAsymmetricKey TrezorCrypto::SeedToPrivateKey(const OTPassword& seed) const { serializedAsymmetricKey derivedKey; HDNode node; int result = ::hdnode_from_seed( static_cast<const uint8_t*>(seed.getMemory()), seed.getMemorySize(), &node); OT_ASSERT_MSG((1 == result), "Derivation of root node failed."); if (1 == result) { derivedKey = HDNodeToSerialized(node, TrezorCrypto::DERIVE_PRIVATE); } OTPassword root; App::Me().Crypto().Hash().Digest( CryptoHash::HASH160, seed, root); derivedKey->mutable_path()->set_root( root.getMemory(), root.getMemorySize()); return derivedKey; }
// static bool OTKeyring::Mac_StoreSecret(const OTString& strUser, const OTPassword& thePassword, const std::string& str_display) { OT_ASSERT(strUser.Exists()); OT_ASSERT(thePassword.getMemorySize() > 0); const std::string service_name = "opentxs"; const std::string account_name = strUser.Get(); OTMacKeychain theKeychain; void* vData = const_cast<void*>(static_cast<const void*>(thePassword.getMemory())); OSStatus theError = theKeychain.AddSecret( nullptr, service_name.size(), service_name.data(), account_name.size(), account_name.data(), thePassword.getMemorySize(), vData, // thePassword.getMemory() nullptr); if (theError != noErr) { otErr << "OTKeyring::Mac_StoreSecret: Error in theKeychain.AddSecret.\n"; return false; } return true; }
bool Server::SetPrivateKey(const OTPassword& key) const { if (CURVE_KEY_BYTES != key.getMemorySize()) { otErr << OT_METHOD << __FUNCTION__ << ": Invalid private key." << std::endl; return false; } return set_private_key(key.getMemory(), key.getMemorySize()); }
// static bool OTKeyring::Gnome_StoreSecret(const OTString& strUser, const OTPassword& thePassword, const std::string& str_display) { OT_ASSERT(strUser.Exists()); OT_ASSERT(thePassword.getMemorySize() > 0); OTData theData(thePassword.getMemory(), thePassword.getMemorySize()); OTASCIIArmor ascData(theData); theData.zeroMemory(); // security reasons. OTString strOutput; const bool bSuccess = ascData.Exists() && ascData.WriteArmoredString(strOutput, "DERIVED KEY"); // There's no // default, to // force you to // enter the right // string. ascData.zeroMemory(); GnomeKeyringResult theResult = GNOME_KEYRING_RESULT_IO_ERROR; if (bSuccess && strOutput.Exists()) { theResult = gnome_keyring_store_password_sync( GNOME_KEYRING_NETWORK_PASSWORD, GNOME_KEYRING_DEFAULT, // GNOME_KEYRING_SESSION, str_display.c_str(), strOutput.Get(), "user", strUser.Get(), "protocol", "opentxs", // todo: hardcoding. nullptr); strOutput.zeroMemory(); bool bResult = false; if (theResult == GNOME_KEYRING_RESULT_OK) bResult = true; else otErr << "OTKeyring::Gnome_StoreSecret: " << "Failure in gnome_keyring_store_password_sync: " << gnome_keyring_result_to_message(theResult) << '\n'; return bResult; } otOut << "OTKeyring::Gnome_StoreSecret: No secret to store.\n"; return false; }
std::string TrezorCrypto::toWords(const OTPassword& seed) const { std::string wordlist( ::mnemonic_from_data( static_cast<const uint8_t*>(seed.getMemory()), seed.getMemorySize())); return wordlist; }
String CryptoUtil::Base58CheckEncode(const OTPassword& input) { const uint8_t* inputStart = static_cast<const uint8_t*>(input.getMemory()); const uint8_t* inputEnd = inputStart + input.getMemorySize(); String encodedInput = ::EncodeBase58Check(inputStart, inputEnd); return encodedInput; }
// static bool OTKeyring::KWallet_StoreSecret(const OTString& strUser, const OTPassword& thePassword, const std::string& str_display) { OT_ASSERT(strUser.Exists()); OT_ASSERT(thePassword.getMemorySize() > 0); KWallet::Wallet* pWallet = OTKeyring::OpenKWallet(); if (nullptr != pWallet) { const QString qstrKey(strUser.Get()); OTData theData(thePassword.getMemory(), thePassword.getMemorySize()); OTASCIIArmor ascData(theData); theData.zeroMemory(); // security reasons. OTString strOutput; const bool bSuccess = ascData.Exists() && ascData.WriteArmoredString( strOutput, "DERIVED KEY"); // There's no default, to force you // to enter the right string. ascData.zeroMemory(); // Set the password // bool bReturnVal = false; if (bSuccess && strOutput.Exists() && pWallet->writePassword(qstrKey, QString::fromUtf8(strOutput.Get())) == 0) bReturnVal = true; else otErr << "OTKeyring::KWallet_StoreSecret: Failed trying to store " "secret into KWallet.\n"; strOutput.zeroMemory(); return bReturnVal; } otErr << "OTKeyring::KWallet_StoreSecret: Unable to open kwallet.\n"; return false; }
String CryptoUtil::Nonce(const uint32_t size, OTData& rawOutput) const { rawOutput.zeroMemory(); rawOutput.SetSize(size); OTPassword source; source.randomizeMemory(size); String nonce(Base58CheckEncode(source)); rawOutput.Assign(source.getMemory(), source.getMemorySize()); return nonce; }
bool OTPassword::Compare(OTPassword & rhs) const { OT_ASSERT(this->isPassword() || this->isMemory()); OT_ASSERT(rhs.isPassword() || rhs.isMemory()); if (this->isPassword() && !rhs.isPassword()) return false; if (this->isMemory() && !rhs.isMemory()) return false; const int nThisSize = this->isPassword() ? this->getPasswordSize() : this->getMemorySize(); const int nRhsSize = rhs.isPassword() ? rhs.getPasswordSize() : rhs.getMemorySize(); if (nThisSize != nRhsSize) return false; if (0 == memcmp(this->isPassword() ? this->getPassword() : this->getMemory(), rhs.isPassword() ? rhs.getPassword() : rhs.getMemory(), rhs.isPassword() ? rhs.getPasswordSize() : rhs.getMemorySize()) ) return true; return false; }
// static bool OTKeyring::FlatFile_StoreSecret(const String& strUser, const OTPassword& thePassword, const std::string& str_display) { OT_ASSERT(strUser.Exists()); OT_ASSERT(thePassword.getMemorySize() > 0); const std::string str_pw_folder(OTKeyring::FlatFile_GetPasswordFolder()); if (!str_pw_folder.empty()) { String strExactPath; strExactPath.Format("%s%s%s", str_pw_folder.c_str(), Log::PathSeparator(), strUser.Get()); const std::string str_ExactPath(strExactPath.Get()); OTData theData(thePassword.getMemory(), thePassword.getMemorySize()); OTASCIIArmor ascData(theData); theData.zeroMemory(); // security reasons. // Save the password // const bool bSaved = ascData.Exists() && ascData.SaveToExactPath(str_ExactPath); ascData.zeroMemory(); if (!bSaved) otErr << "OTKeyring::FlatFile_StoreSecret: Failed trying to store " "secret.\n"; return bSaved; } otErr << "OTKeyring::FlatFile_StoreSecret: Unable to cache derived key, " "since password_folder not provided in config file.\n"; return false; }
bool OTPassword::Compare(OTPassword& rhs) const { OT_ASSERT(isPassword() || isMemory()); OT_ASSERT(rhs.isPassword() || rhs.isMemory()); if (isPassword() && !rhs.isPassword()) return false; if (isMemory() && !rhs.isMemory()) return false; const uint32_t nThisSize = isPassword() ? getPasswordSize() : getMemorySize(); const uint32_t nRhsSize = rhs.isPassword() ? rhs.getPasswordSize() : rhs.getMemorySize(); if (nThisSize != nRhsSize) return false; if (0 == memcmp(isPassword() ? getPassword_uint8() : getMemory_uint8(), rhs.isPassword() ? rhs.getPassword_uint8() : rhs.getMemory_uint8(), rhs.isPassword() ? rhs.getPasswordSize() : rhs.getMemorySize())) return true; return false; }
OTPassword::OTPassword(const OTPassword& rhs) : size_(0) , isText_(rhs.isPassword()) , isBinary_(rhs.isMemory()) , isPageLocked_(false) , blockSize_( rhs.blockSize_) // The buffer has this size+1 as its static size. { if (isText_) { data_[0] = '\0'; setPassword_uint8(rhs.getPassword_uint8(), rhs.getPasswordSize()); } else if (isBinary_) { setMemory(rhs.getMemory_uint8(), rhs.getMemorySize()); } }
OTPassword::OTPassword(const OTPassword & rhs) : m_nPasswordSize(0), m_bIsText(rhs.isPassword()), m_bIsBinary(rhs.isMemory()), m_bIsPageLocked(false), m_theBlockSize(rhs.m_theBlockSize) // The buffer has this size+1 as its static size. { if (m_bIsText) { m_szPassword[0] = '\0'; setPassword_uint8(rhs.getPassword_uint8(), rhs.getPasswordSize()); } else if (m_bIsBinary) { setMemory(rhs.getMemory_uint8(), rhs.getMemorySize()); } }
OTSymmetricKey Symmetric::Factory( const crypto::SymmetricProvider& engine, const OTPassword& raw) { std::unique_ptr<implementation::Symmetric> output; if (!raw.isMemory()) { return OTSymmetricKey(output.release()); } output.reset(new implementation::Symmetric(engine)); if (!output) { return OTSymmetricKey(output.release()); } OTPasswordData password("Encrypting a symmetric key."); output->EncryptKey(raw, password); output->key_size_ = raw.getMemorySize(); return OTSymmetricKey(output.release()); }
bool OTEnvelope::Decrypt(String& theOutput, const OTSymmetricKey& theKey, const OTPassword& thePassword) { const char* szFunc = "OTEnvelope::Decrypt"; OT_ASSERT( (thePassword.isPassword() && (thePassword.getPasswordSize() > 0)) || (thePassword.isMemory() && (thePassword.getMemorySize() > 0))); OT_ASSERT(theKey.IsGenerated()); OTPassword theRawSymmetricKey; if (false == theKey.GetRawKeyFromPassphrase(thePassword, theRawSymmetricKey)) { otErr << szFunc << ": Failed trying to retrieve raw symmetric key " "using password. (Wrong password?)\n"; return false; } uint32_t nRead = 0; uint32_t nRunningTotal = 0; m_dataContents.reset(); // Reset the fread position on this object to 0. // // Read the ENVELOPE TYPE (as network order version -- and convert to host // version.) // // 0 == Error // 1 == Asymmetric Key (this function -- Seal / Open) // 2 == Symmetric Key (other functions -- Encrypt / Decrypt use this.) // Anything else: error. // uint16_t env_type_n = 0; if (0 == (nRead = m_dataContents.OTfread( reinterpret_cast<uint8_t*>(&env_type_n), static_cast<uint32_t>(sizeof(env_type_n))))) { otErr << szFunc << ": Error reading Envelope Type. Expected " "asymmetric(1) or symmetric (2).\n"; return false; } nRunningTotal += nRead; OT_ASSERT(nRead == static_cast<uint32_t>(sizeof(env_type_n))); // convert that envelope type from network to HOST endian. // const uint16_t env_type = ntohs(env_type_n); // nRunningTotal += env_type; // NOPE! Just because envelope type is 1 // or 2, doesn't mean we add 1 or 2 extra bytes to the length here. Nope! if (2 != env_type) { const uint32_t l_env_type = static_cast<uint32_t>(env_type); otErr << szFunc << ": Error: Expected Envelope for Symmetric key (type " "2) but instead found type: " << l_env_type << ".\n"; return false; } // Read network-order IV size (and convert to host version) // const uint32_t max_iv_length = OTCryptoConfig::SymmetricIvSize(); // I believe this is a max length, so // it may not match the actual length // of the IV. // Read the IV SIZE (network order version -- convert to host version.) // uint32_t iv_size_n = 0; if (0 == (nRead = m_dataContents.OTfread( reinterpret_cast<uint8_t*>(&iv_size_n), static_cast<uint32_t>(sizeof(iv_size_n))))) { otErr << szFunc << ": Error reading IV Size.\n"; return false; } nRunningTotal += nRead; OT_ASSERT(nRead == static_cast<uint32_t>(sizeof(iv_size_n))); // convert that iv size from network to HOST endian. // const uint32_t iv_size_host_order = ntohl(iv_size_n); if (iv_size_host_order > max_iv_length) { otErr << szFunc << ": Error: iv_size (" << static_cast<int64_t>(iv_size_host_order) << ") is larger than max_iv_length (" << static_cast<int64_t>(max_iv_length) << ").\n"; return false; } // nRunningTotal += iv_size_host_order; // Nope! // Then read the IV (initialization vector) itself. // OTData theIV; theIV.SetSize(iv_size_host_order); if (0 == (nRead = m_dataContents.OTfread( static_cast<uint8_t*>(const_cast<void*>(theIV.GetPointer())), static_cast<uint32_t>(iv_size_host_order)))) { otErr << szFunc << ": Error reading initialization vector.\n"; return false; } nRunningTotal += nRead; OT_ASSERT(nRead == static_cast<uint32_t>(iv_size_host_order)); OT_ASSERT(nRead <= max_iv_length); // We create an OTData object to store the ciphertext itself, which // begins AFTER the end of the IV. // So we see pointer + nRunningTotal as the starting point for the // ciphertext. // the size of the ciphertext, meanwhile, is the size of the entire thing, // MINUS nRunningTotal. // OTData theCipherText( static_cast<const void*>( static_cast<const uint8_t*>(m_dataContents.GetPointer()) + nRunningTotal), m_dataContents.GetSize() - nRunningTotal); // Now we've got all the pieces together, let's try to decrypt it... // OTData thePlaintext; // for output. const bool bDecrypted = OTCrypto::It()->Decrypt( theRawSymmetricKey, // The symmetric key, in clear form. static_cast<const char*>( theCipherText.GetPointer()), // This is the Ciphertext. theCipherText.GetSize(), theIV, thePlaintext); // OUTPUT. (Recovered plaintext.) You can pass // OTPassword& OR OTData& here (either will // work.) // theOutput is where we'll put the decrypted data. // theOutput.Release(); if (bDecrypted) { // Make sure it's null-terminated... // uint32_t nIndex = thePlaintext.GetSize() - 1; (static_cast<uint8_t*>( const_cast<void*>(thePlaintext.GetPointer())))[nIndex] = '\0'; // Set it into theOutput (to return the plaintext to the caller) // theOutput.Set(static_cast<const char*>(thePlaintext.GetPointer())); } return bDecrypted; }
bool OTEnvelope::Encrypt(const String& theInput, OTSymmetricKey& theKey, const OTPassword& thePassword) { OT_ASSERT( (thePassword.isPassword() && (thePassword.getPasswordSize() > 0)) || (thePassword.isMemory() && (thePassword.getMemorySize() > 0))); OT_ASSERT(theInput.Exists()); // Generate a random initialization vector. // OTData theIV; if (!theIV.Randomize(OTCryptoConfig::SymmetricIvSize())) { otErr << __FUNCTION__ << ": Failed trying to randomly generate IV.\n"; return false; } // If the symmetric key hasn't already been generated, we'll just do that // now... // (The passphrase is used to derive another key that is used to encrypt the // actual symmetric key, and to access it later.) // if ((false == theKey.IsGenerated()) && (false == theKey.GenerateKey(thePassword))) { otErr << __FUNCTION__ << ": Failed trying to generate symmetric key using password.\n"; return false; } if (!theKey.HasHashCheck()) { if (!theKey.GenerateHashCheck(thePassword)) { otErr << __FUNCTION__ << ": Failed trying to generate hash check using password.\n"; return false; } } OT_ASSERT(theKey.HasHashCheck()); OTPassword theRawSymmetricKey; if (false == theKey.GetRawKeyFromPassphrase(thePassword, theRawSymmetricKey)) { otErr << __FUNCTION__ << ": Failed trying to retrieve raw symmetric " "key using password.\n"; return false; } OTData theCipherText; const bool bEncrypted = OTCrypto::It()->Encrypt( theRawSymmetricKey, // The symmetric key, in clear form. theInput.Get(), // This is the Plaintext. theInput.GetLength() + 1, // for null terminator theIV, // Initialization vector. theCipherText); // OUTPUT. (Ciphertext.) // // Success? // if (!bEncrypted) { otErr << __FUNCTION__ << ": (static) call failed to encrypt. Wrong " "key? (Returning false.)\n"; return false; } // This is where the envelope final contents will be placed, // including the envelope type, the size of the IV, the IV // itself, and the ciphertext. // m_dataContents.Release(); // Write the ENVELOPE TYPE (network order version.) // // 0 == Error // 1 == Asymmetric Key (other functions -- Seal / Open.) // 2 == Symmetric Key (this function -- Encrypt / Decrypt.) // Anything else: error. // Calculate "network-order" version of envelope type 2. uint16_t env_type_n = htons(static_cast<uint16_t>(2)); m_dataContents.Concatenate(reinterpret_cast<void*>(&env_type_n), // (uint32_t here is the 2nd parameter to // Concatenate, and has nothing to do with // env_type_n being uint16_t) static_cast<uint32_t>(sizeof(env_type_n))); // Write IV size (in network-order) // uint32_t ivlen = OTCryptoConfig::SymmetricIvSize(); // Length of IV for this cipher... OT_ASSERT(ivlen >= theIV.GetSize()); uint32_t ivlen_n = htonl( theIV.GetSize()); // Calculate "network-order" version of iv length. m_dataContents.Concatenate(reinterpret_cast<void*>(&ivlen_n), static_cast<uint32_t>(sizeof(ivlen_n))); // Write the IV itself. // m_dataContents.Concatenate(theIV.GetPointer(), theIV.GetSize()); // Write the Ciphertext. // m_dataContents.Concatenate(theCipherText.GetPointer(), theCipherText.GetSize()); // We don't write the size of the ciphertext before the ciphertext itself, // since the decryption is able to deduce the size based on the total // envelope // size minus the other pieces. We might still want to add that size here, // however. // (for security / safety reasons.) return true; }
// static bool OTKeyring::Windows_StoreSecret(const OTString& strUser, const OTPassword& thePassword, const std::string& str_display) { OT_ASSERT(strUser.Exists()); OT_ASSERT(thePassword.getMemorySize() > 0); DATA_BLOB input; input.pbData = const_cast<BYTE*>( reinterpret_cast<const BYTE*>(thePassword.getMemory())); input.cbData = static_cast<DWORD>(thePassword.getMemorySize()); // CRYPTPROTECT_PROMPTSTRUCT PromptStruct; // ZeroMemory(&PromptStruct, sizeof(PromptStruct)); // PromptStruct.cbSize = sizeof(PromptStruct); // PromptStruct.dwPromptFlags = CRYPTPROTECT_PROMPT_ON_PROTECT; // PromptStruct.szPrompt = L"This is a user prompt."; DATA_BLOB output; BOOL result = CryptProtectData(&input, L"", // description string nullptr, // optional entropy nullptr, // reserved nullptr, //&PromptStruct 0, &output); if (!result) { otErr << __FUNCTION__ << ": Failed calling Win32: CryptProtectData \n"; return false; } // // this does a copy // // std::string ciphertext; // ciphertext.assign(reinterpret_cast<std::string::value_type*>(output.pbData), // output.cbData); OTData theOutput; theOutput.Assign(static_cast<void*>(output.pbData), static_cast<uint32_t>(output.cbData)); LocalFree(output.pbData); // Note: should have a check for nullptr here... ? // And above... // Success encrypting to ciphertext (std::string or OTData) // // Write it to local storage. // if (theOutput.IsEmpty()) { otErr << __FUNCTION__ << ": Error: Output of Win32 CryptProtectData was empty.\n"; } else { OTASCIIArmor ascData(theOutput); const OTString strFoldername("win32_data"); // todo hardcoding. if (ascData.Exists()) return ascData.WriteArmoredFile(strFoldername, strUser, // this is filename "WINDOWS KEYRING MASTERKEY"); } return false; }