Exemplo n.º 1
0
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;
}