bool OTEnvelope::Encrypt(const OTString & 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. // OTPayload theIV; if (false == theIV.Randomize(OTCryptoConfig::SymmetricIvSize())) { OTLog::vError("%s: Failed trying to randomly generate IV.\n", __FUNCTION__); 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))) { OTLog::vError("%s: Failed trying to generate symmetric key using password.\n", __FUNCTION__); return false; } // ----------------------------------------------- if (!theKey.HasHashCheck()) { if(!theKey.GenerateHashCheck(thePassword)) { OTLog::vError("%s: Failed trying to generate hash check using password.\n", __FUNCTION__); return false; } } OT_ASSERT(theKey.HasHashCheck()); OTPassword theRawSymmetricKey; if (false == theKey.GetRawKeyFromPassphrase(thePassword, theRawSymmetricKey)) { OTLog::vError("%s: Failed trying to retrieve raw symmetric key using password.\n", __FUNCTION__); return false; } // ----------------------------------------------- // OTPayload 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) { OTLog::vError("%s: (static) call failed to encrypt. Wrong key? (Returning false.)\n", __FUNCTION__); 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. uint16_t env_type_n = static_cast<uint16_t>(htons(static_cast<uint16_t>(2))); // Calculate "network-order" version of envelope type 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.GetPayloadPointer(), static_cast<uint32_t>(theIV.GetSize())); // ------------------------------------------------------------ // Write the Ciphertext. // m_dataContents.Concatenate(theCipherText.GetPayloadPointer(), static_cast<uint32_t>(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; }
// The above method uses this one internally... bool OTAccount::GenerateNewAccount(const OTPseudonym & theServer, const OTMessage & theMessage, const OTAccount::AccountType eAcctType/*=OTAccount::simple*/, int64_t lStashTransNum/*=0*/) { const char *szFunc = "OTAccount::GenerateNewAccount"; // ----------------------------------------------- // First we generate a secure random number into a binary object... // OTPayload thePayload; if (false == thePayload.Randomize(100)) // todo hardcoding. Plus: is 100 bytes of random a little much here? { OTLog::vError("%s: Failed trying to acquire random numbers.\n", szFunc); return false; } // -------------------------------------------------- // // Next we calculate that binary object into a message digest (an OTIdentifier). // OTIdentifier newID; if (!newID.CalculateDigest(thePayload)) { OTLog::vError("%s: Error generating new account ID.\n", szFunc); return false; } // -------------------------------------------------- // // Next we get that digest (which is a binary hash number) // and extract a human-readable standard string format of that hash, // into an OTString. // OTString strID(newID); SetRealAccountID(newID); // Set the account number based on what we just generated. SetPurportedAccountID(newID); // Might as well set them both. (Safe here to do so, for once.) m_strName.Set(strID); // So it's not blank. The user can always change it. // Next we create the full path filename for the account using the ID. // m_strFoldername = OTFolders::Account().Get(); m_strFilename = strID.Get(); // Then we try to load it, in order to make sure that it doesn't already exist. // -------------------------------------------------------------------- if (OTDB::Exists(m_strFoldername.Get(), m_strFilename.Get())) { OTLog::vError("%s: Account already exists: %s\n", szFunc, m_strFilename.Get()); return false; } // -------------------------------------------------------------------- // Set up the various important starting values of the account. m_AcctType = eAcctType; // account type defaults to OTAccount::simple. But there are also issuer accts... // -------------------------------------------------------------------- if (IsInternalServerAcct()) // basket, basketsub, mint, voucher, and stash accounts are all "owned" by the server. { theServer.GetIdentifier(m_AcctUserID); } else { m_AcctUserID.SetString(theMessage.m_strNymID); } // -------------------------------------------------------------------- m_AcctAssetTypeID.SetString(theMessage.m_strAssetID); OTLog::vOutput(3, "%s: Creating new account, type:\n%s\n", szFunc, theMessage.m_strAssetID.Get()); OTIdentifier SERVER_ID(theMessage.m_strServerID); SetRealServerID(SERVER_ID); // todo this assumes the serverID on the message is correct. It's vetted, but still... SetPurportedServerID(SERVER_ID); const time64_t tDate = OTTimeGetCurrentTime(); // Today, now. m_BalanceDate.Format("%d", tDate); m_BalanceAmount.Set("0"); // -------------------------------------------------------------------- if (IsStashAcct()) { OT_ASSERT_MSG(lStashTransNum > 0, "You created a stash account, but with a zero-or-negative transaction number for its cron item."); m_lStashTransNum = lStashTransNum; } // -------------------------------------------------------------------- // Sign the Account (so we know that we did)... Otherwise someone could put a fake // account file on the server if the code wasn't designed to verify the signature on the // account. SignContract(theServer); SaveContract(); // Save the Account to storage (based on its ID.) SaveAccount(); // Don't know why I had this here. Putting SaveAccount() instead. // OTString strFilename(m_strFilename); // SaveContract(strFilename.Get()); // Saves the account to a specific filename // No need to create the inbox and outbox ledgers...they will be created automatically // if they do not exist when they are needed. return true; }