예제 #1
0
serializedAsymmetricKey TrezorCrypto::HDNodeToSerialized(
    const HDNode& node,
    const DerivationMode privateVersion) const
{
    serializedAsymmetricKey key = std::make_shared<proto::AsymmetricKey>();

    key->set_version(1);
    key->set_type(proto::AKEYTYPE_SECP256K1);

    if (privateVersion) {
        key->set_mode(proto::KEYMODE_PRIVATE);
        key->set_chaincode(node.chain_code, sizeof(node.chain_code));

        OTPassword plaintextKey;
        plaintextKey.setMemory(node.private_key, sizeof(node.private_key));
        OTData encryptedKey;
        BinarySecret masterPassword(
            App::Me().Crypto().AES().InstantiateBinarySecretSP());
        masterPassword = CryptoSymmetric::GetMasterKey("");

        bool encrypted = Libsecp256k1::EncryptPrivateKey(
            plaintextKey,
            *masterPassword,
            encryptedKey);

        if (encrypted) {
            key->set_key(encryptedKey.GetPointer(), encryptedKey.GetSize());
        }
    } else {
        key->set_mode(proto::KEYMODE_PUBLIC);
        key->set_key(node.public_key, sizeof(node.public_key));
    }

    return key;
}
// This function will base64 DECODE the string contents
// and return them as binary in theData
bool OTASCIIArmor::GetData(OTData & theData, bool bLineBreaks) const //linebreaks=true
{	
	return GetAndUnpackData(theData, bLineBreaks);
	
	
	
	size_t		outSize	= 0;
	uint8_t *	pData	= NULL;
	
	theData.Release();
	
	if (GetLength() < 1)
		return true;
	
	pData = OT_base64_decode(Get(), &outSize, (bLineBreaks ? 1 : 0));
	
	if (pData)
	{
		theData.Assign(pData, outSize);
		delete [] pData; pData=NULL;
		return true;
	}
	else 
	{
		OTLog::Error("Error while base64_decoding in OTASCIIArmor::GetData.\n");
		return false;
	}
}
예제 #3
0
const std::string PaymentCode::asBase58() const
{
    OTData pubkey = Pubkey();

    uint8_t serialized[81]{};

    serialized[0] = PaymentCode::BIP47_VERSION_BYTE;
    serialized[1] = version_;
    serialized[2] = hasBitmessage_ ? 0x80 : 0;
    OTPassword::safe_memcpy(
        &serialized[3],
        33,
        pubkey.GetPointer(),
        pubkey.GetSize(),
        false);
    OTPassword::safe_memcpy(
        &serialized[36],
        32,
        chain_code_.GetPointer(),
        chain_code_.GetSize(),
        false);
    serialized[68] = bitmessage_version_;
    serialized[69] = bitmessage_stream_;

    OTData binaryVersion(serialized, sizeof(serialized));

    return App::Me().Crypto().Util().Base58CheckEncode(binaryVersion).Get();
}
// This function will base64 ENCODE theData,
// and then Set() that as the string contents.
bool OTASCIIArmor::SetData(const OTData & theData, bool bLineBreaks/*=true*/)
{
	return SetAndPackData(theData, bLineBreaks);
	
	
	
	char *	pString	= NULL;
	
	Release();
	
	if (theData.GetSize() < 1)
		return true;
	
	pString = OT_base64_encode((const uint8_t*)theData.GetPointer(), theData.GetSize(), (bLineBreaks ? 1 : 0));
	
	if (pString)
	{
		Set(pString);
		delete [] pString; pString=NULL;
		return true;
	}
	else 
	{
		OTLog::Error("Error while base64_encoding in OTASCIIArmor::GetData.\n");
		return false;
	}
}
예제 #5
0
// Base64-decode
bool OTASCIIArmor::GetData(OTData& theData,
                           bool bLineBreaks) const // linebreaks=true
{
    theData.Release();

    if (GetLength() < 1) return true;

    size_t outSize = 0;
    uint8_t* pData = App::Me().Crypto().Util().Base64Decode(Get(), &outSize, bLineBreaks);

    // Some versions of OpenSSL will handle input without line breaks when bLineBreaks is true,
    // other versions of OpenSSL will return a zero-length output.
    //
    // Functions which call this method do not always know the correct value for bLineBreaks, since
    // the input may be too short to warrant a line break.
    //
    // To make this funciton less fragile, if the first attempt does not result in the expected
    // output, try again with the opposite value set for bLineBreaks.
    if (!pData||(0==outSize)) {
        pData = App::Me().Crypto().Util().Base64Decode(Get(), &outSize, !bLineBreaks);
        if (!pData||(0==outSize)) {
            otErr << __FUNCTION__ << "Base64Decode fail\n";
            return false;
        }
    }
    theData.Assign(pData, outSize);
    delete[] pData;
    return true;
}
예제 #6
0
const Identifier PaymentCode::ID() const
{

    uint8_t core[65]{};

    OTData pubkey = Pubkey();
    OTPassword::safe_memcpy(
        &core[0],
        33,
        pubkey.GetPointer(),
        pubkey.GetSize(),
        false);
    if (chain_code_.GetSize() == 32) {
        OTPassword::safe_memcpy(
            &core[33],
            32,
            chain_code_.GetPointer(),
            chain_code_.GetSize(),
            false);
    }

    OTData dataVersion(core, sizeof(core));

    Identifier paymentCodeID;

    paymentCodeID.CalculateDigest(dataVersion);

    return paymentCodeID;
}
예제 #7
0
// This function will base64 ENCODE theData,
// and then Set() that as the string contents.
// Additionally it will pack and compress the data!
//
bool OTASCIIArmor::SetAndPackData(const OTData & theData, bool bLineBreaks/*=true*/)
{
	char *	pString	= NULL;
	
	Release();
	
	if (theData.GetSize() < 1)
		return true;
	// --------------------------------------------------------
	OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either.
	
	// Here I use the default storage context to create the object (the blob.)
	// I also originally created OTASCIIArmor::GetPacker() using OTDB_DEFAULT_PACKER,
	// so I know everything is compatible.
	//
	OTDB::Blob * pBlob = dynamic_cast<OTDB::Blob *>(OTDB::CreateObject(OTDB::STORED_OBJ_BLOB));
	
	OT_ASSERT(NULL != pBlob); // Beyond this point, responsible to delete pBlob.
	OTCleanup<OTDB::Blob> theBlobAngel(*pBlob); // make sure memory is cleaned up.
	// ----------------------------
	pBlob->m_memBuffer.assign(static_cast<const unsigned char *>(theData.GetPointer()), 
							  static_cast<const unsigned char *>(theData.GetPointer())+theData.GetSize());
		
	OTDB::PackedBuffer * pBuffer = pPacker->Pack(*pBlob); // Now we PACK our data before compressing/encoding it.
	
	if (NULL == pBuffer)
	{
		OTLog::Error("Failed packing data in OTASCIIArmor::SetAndPackData. \n");
		return false;
	}
	
	OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // make sure memory is cleaned up.
	// --------------------------------------------------------
	const uint8_t* pUint = static_cast<const uint8_t*>(pBuffer->GetData());
	const size_t theSize = pBuffer->GetSize();
	
	if (NULL != pUint)
        pString = OTCrypto::It()->Base64Encode(pUint, static_cast<int>(theSize), bLineBreaks);
//		pString = OT_base64_encode(pUint, static_cast<int> (theSize), (bLineBreaks ? 1 : 0));
	else 
	{
		OTLog::Error("Error while base64_encoding in OTASCIIArmor::SetAndPackData.\n");
		return false;
	}
	// -------------------------------------
	if (NULL != pString)
	{
		Set(pString);
		delete [] pString; pString=NULL;
		return true;
	}
	else 
	{
		OTLog::Error("Error while base64_encoding in OTASCIIArmor::SetAndPackData.\n");
		return false;
	}
}
예제 #8
0
int32_t OTPassword::setMemory(const OTData& data)
{
    const uint32_t dataSize = data.GetSize();
    uint32_t returnedSize = dataSize;

    bool memorySet = setMemory(data.GetPointer(), returnedSize);
    // TODO maybe we should check for truncation?
    return memorySet;
}
// This function will base64 DECODE the string contents
// and return them as binary in theData
// Additionally it will decompress and unpack the data!
//
bool OTASCIIArmor::GetAndUnpackData(OTData & theData, bool bLineBreaks) const //linebreaks=true
{	
	size_t		outSize	= 0;
	uint8_t *	pData	= NULL;
	
	theData.Release();
	
	if (GetLength() < 1)
		return true;
	
	// --------------------------------------------------------------
	//
	pData = OT_base64_decode(Get(), &outSize, (bLineBreaks ? 1 : 0));
	
	if (pData)
	{
		// --------------------------------------------------------
		
		OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either.
		
		OTDB::PackedBuffer * pBuffer = pPacker->CreateBuffer(); // Need to clean this up.
		OT_ASSERT(NULL != pBuffer);
		OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // make sure buffer is deleted.
		
		pBuffer->SetData(static_cast<const unsigned char*>(pData), outSize);
		delete [] pData; pData=NULL; 
		// -----------------------------
		
		OTDB::Blob * pBlob = dynamic_cast<OTDB::Blob *>(OTDB::CreateObject(OTDB::STORED_OBJ_BLOB));
		OT_ASSERT(NULL != pBlob);
		OTCleanup<OTDB::Blob> theBlobAngel(*pBlob); // clean up this blob.
		
		bool bUnpacked = pPacker->Unpack(*pBuffer, *pBlob);
		
		// ----------------------
		
		if (false == bUnpacked)
		{
			OTLog::Error("Failed unpacking data in OTASCIIArmor::GetAndUnpackData.\n");
			delete [] pData; pData=NULL;
			return false;
		}
		
		// --------------------------------------------------------
		
		theData.Assign(pBlob->m_memBuffer.data(), pBlob->m_memBuffer.size());
		delete [] pData; pData=NULL;
		return true;
	}
	else 
	{
		OTLog::Error("Error while base64_decoding in OTASCIIArmor::GetAndUnpackData.\n");
		return false;
	}
}
예제 #10
0
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;
}
예제 #11
0
const OTData PaymentCode::Pubkey() const
{
    OTData pubkey;
    pubkey.SetSize(33);

    if (pubkey_) {
        std::dynamic_pointer_cast<AsymmetricKeySecp256k1>(pubkey_)->GetKey(pubkey);
    }

    OT_ASSERT(33 == pubkey.GetSize());

    return pubkey;
}
예제 #12
0
void PaymentCode::ConstructKey(const OTData& pubkey, const OTData& chaincode)
{
    proto::AsymmetricKey newKey;

    newKey.set_version(1);
    newKey.set_type(proto::AKEYTYPE_SECP256K1);
    newKey.set_mode(proto::KEYMODE_PUBLIC);
    newKey.set_role(proto::KEYROLE_SIGN);
    newKey.set_key(pubkey.GetPointer(), pubkey.GetSize());
    newKey.set_chaincode(chaincode.GetPointer(), chaincode.GetSize());

    OTAsymmetricKey* key = OTAsymmetricKey::KeyFactory(newKey);

    pubkey_.reset(key);
}
예제 #13
0
SerializedPaymentCode PaymentCode::Serialize() const
{
    SerializedPaymentCode serialized = std::make_shared<proto::PaymentCode>();

    serialized->set_version(version_);

    if (pubkey_) {
        OTData pubkey = Pubkey();
        serialized->set_key(pubkey.GetPointer(), pubkey.GetSize());
    }

    serialized->set_chaincode(chain_code_.GetPointer(), chain_code_.GetSize());
    serialized->set_bitmessageversion(bitmessage_version_);
    serialized->set_bitmessagestream(bitmessage_stream_);

    return serialized;
}
예제 #14
0
uint32_t OTPayload::ReadBytesFrom(OTData & theData, uint32_t lSize)
{
	// The size requested to read MUST be less or equal to size of theData
	if (theData.GetSize() < lSize)
		abort();

	OTPayload & refPayload = (OTPayload &)theData;
	
	// Copy from theData to this, up until lSize
	Assign(refPayload.GetPayloadPointer(), lSize);
	
	// Create a temp var, starting from theData+lSize, copying to the end of theData
	OTData TEMPdata((unsigned char *)refPayload.GetPayloadPointer() + lSize, theData.GetSize() - lSize);
	
	// theData is assigned to TEMPdata (thus removing from it the bytes that we just read into this.)
	theData.Assign(TEMPdata);
	
	return lSize;
}
예제 #15
0
// Base64-encode
bool OTASCIIArmor::SetData(const OTData& theData, bool bLineBreaks)
{
    Release();

    if (theData.GetSize() < 1) return true;

    char* pString = App::Me().Crypto().Util().Base64Encode(
        static_cast<const uint8_t*>(theData.GetPointer()), theData.GetSize(),
        bLineBreaks);

    if (!pString) {
        otErr << __FUNCTION__ << "Base64Encode fail\n";
        return false;
    }

    Set(pString);
    delete[] pString;
    return true;
}
예제 #16
0
void OTData::Assign(const OTData &theSource)
{
	if ((&theSource) == this)
		return; // can't assign to self.
	
	if (false == theSource.IsEmpty()) // If something is there...
	{
		Assign(theSource.m_pData, theSource.m_lSize); // Copy it.
	}
	else
		Release(); // Otherwise if it's empty, then empty this also.
}
예제 #17
0
void OTData::Assign(const OTData& source)
{
    // can't assign to self.
    if (&source == this) {
        return;
    }

    if (!source.IsEmpty()) {
        Assign(source.data_, source.size_);
    }
    else {
        // Otherwise if it's empty, then empty this also.
        Release();
    }
}
예제 #18
0
bool Identifier::CalculateDigest(const OTData& dataInput)
{
    auto dataPtr = static_cast<const unsigned char*>(dataInput.GetPointer());
    return CalculateDigest(dataPtr, dataInput.GetSize());
}
예제 #19
0
// 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;
}
예제 #20
0
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;
}
예제 #21
0
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;
}
예제 #22
0
PaymentCode::PaymentCode(const std::string& base58)
{
    OTData rawCode;
    App::Me().Crypto().Util().Base58CheckDecode(base58, rawCode);

    if (81 == rawCode.GetSize()) {
        uint8_t prependByte, features;
        rawCode.OTfread(&prependByte, 1);

        rawCode.OTfread(&version_, 1);
        rawCode.OTfread(&features, 1);

        if (features & 0x80) {
            hasBitmessage_ = true;
        }

        OTData key;
        key.SetSize(33);
        chain_code_.SetSize(32);

        OT_ASSERT(33 == key.GetSize());
        OT_ASSERT(32 == chain_code_.GetSize());

        rawCode.OTfread(static_cast<uint8_t*>(const_cast<void*>(key.GetPointer())), key.GetSize());
        rawCode.OTfread(static_cast<uint8_t*>(const_cast<void*>(chain_code_.GetPointer())), chain_code_.GetSize());

        ConstructKey(key, chain_code_);

        if (hasBitmessage_) {
            rawCode.OTfread(&bitmessage_version_, 1);
            rawCode.OTfread(&bitmessage_stream_, 1);
        }
    }
}
예제 #23
0
bool OTEnvelope::Open(const OTPseudonym & theRecipient, OTString & theContents)
{
	bool retval = false;
	
    EVP_CIPHER_CTX	ctx;

    unsigned char	buffer[4096];
    unsigned char	buffer_out[4096 + EVP_MAX_IV_LENGTH];
    unsigned char	iv[EVP_MAX_IV_LENGTH];

    size_t			len = 0;
    int				len_out = 0;
    
	unsigned char *	ek = NULL;
    int				eklen = 0;
    uint32_t		eklen_n = 0;
	
	memset(buffer, 0, 4096);
	memset(buffer_out, 0, 4096 + EVP_MAX_IV_LENGTH);
	memset(iv, 0, EVP_MAX_IV_LENGTH);

	OTAsymmetricKey &	privateKey	= (OTAsymmetricKey &)theRecipient.GetPrivateKey();
	EVP_PKEY *			pkey		= (EVP_PKEY *)privateKey.GetKey();
	
	if (NULL == pkey)
	{
		OTLog::Error("Null private key in OTEnvelope::Open\n");
		return false;
	}
		
	EVP_CIPHER_CTX_init(&ctx);
    ek = (unsigned char*)malloc(EVP_PKEY_size(pkey));  // I assume this is for the AES key
	
	OT_ASSERT(NULL != ek);
	
	memset(ek, 0, EVP_PKEY_size(pkey));

	eklen = EVP_PKEY_size(pkey);
	
	
	//int EVP_OpenInit(EVP_CIPHER_CTX *ctx,
	//EVP_CIPHER *type,
	//unsigned char *ek, 
	//int ekl,
	//unsigned char *iv,
	//EVP_PKEY *priv);
	
	//EVP_OpenInit() initializes a cipher context ctx for decryption with cipher type. It decrypts the encrypted 
	//	symmetric key of length ekl bytes passed in the ek parameter using the private key priv. The IV is supplied 
	//	in the iv parameter.
		

	theContents.Release();	// This is where we'll put the decrypted data.
	m_dataContents.reset(); // reset the fread position on this object.
	
	int nReadLength = 0;
	int nReadKey = 0;
	int nReadIV = 0;
	
	// First we read the encrypted key size.
	if (0 == (nReadLength = m_dataContents.OTfread((char*)&eklen_n, sizeof(eklen_n))))
	{
		OTLog::Error("Error reading encrypted key size in OTEnvelope::Open\n");
		free(ek); ek = NULL;
		return false;
	}
	
	// convert it from network to host endian.
	eklen = ntohl(eklen_n);
	
	// Next we read the encrypted key itself.
	if (0 == (nReadKey = m_dataContents.OTfread((char*)ek, eklen)))
	{
		OTLog::Error("Error reading encrypted key size in OTEnvelope::Open\n");
		free(ek); ek = NULL;
		return false;
	}
	
	// Next we read the initialization vector.
	if (0 == (nReadIV = m_dataContents.OTfread((char*)iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()))))
	{
		OTLog::Error("Error reading initialization vector in OTEnvelope::Open\n");
		free(ek); ek = NULL;
		return false;
	}
	
	OTData ciphertext((const void*)((unsigned char *)m_dataContents.GetPointer() + nReadLength + nReadKey + nReadIV), 
					  m_dataContents.GetSize() - nReadLength - nReadKey - nReadIV);
	
	
	
	// Now we process ciphertext and write the decrypted data to plaintext.
	OTData plaintext;

	if (!EVP_OpenInit(&ctx, EVP_aes_128_cbc(), ek, eklen, iv, pkey))
    {
        OTLog::Error("EVP_OpenInit: failed.\n");
		free(ek); ek = NULL;
		return false;
    }
		
    while ((len = ciphertext.OTfread((char*)buffer, sizeof(buffer))) > 0)
    {
        if (!EVP_OpenUpdate(&ctx, buffer_out, &len_out, buffer, len))
        {
            OTLog::Error("EVP_OpenUpdate: failed.\n");
			free(ek); ek = NULL;
			return false;
        }
		
		OTData dataOpenUpdate(buffer_out, len_out);
		plaintext += dataOpenUpdate;
	}
	
    if (!EVP_OpenFinal(&ctx, buffer_out, &len_out))
    {
		OTLog::Error("EVP_OpenFinal: failed.\n");
 		free(ek); ek = NULL;
		return false;
    }
	
	OTData dataOpenFinal(buffer_out, len_out);
	plaintext += dataOpenFinal;
	
	// Make sure it's null terminated
	int nIndex = plaintext.GetSize()-1;
	((unsigned char*)plaintext.GetPointer())[nIndex] = 0;
	
	// Set it into theContents (to return the plaintext to the caller)
	theContents.Set((const char *)plaintext.GetPointer());
	
	retval = true;
	
    free(ek); ek = NULL;
	
    return retval;
	
}
TEST_F(Test_RouterDealer, Dealer_3_Router_Dealer_Router)
{
    ASSERT_NE(nullptr, &Test_RouterDealer::context_.get());

    auto dealerCallback =
        zmq::ListenCallback::Factory([this](zeromq::Message& input) -> void {
            EXPECT_EQ(3, input.size());
            const std::string& inputString = *input.Body().begin();
            bool match = inputString == testMessage_ ||
                         inputString == testMessage2_ ||
                         inputString == testMessage3_;

            EXPECT_TRUE(match);

            auto sent = routerSocket_->get().Send(input);

            EXPECT_TRUE(sent);

            ++callbackFinishedCount_;
        });

    ASSERT_NE(nullptr, &dealerCallback.get());

    auto dealerSocket = zmq::DealerSocket::Factory(
        Test_RouterDealer::context_,
        zmq::Socket::Direction::Bind,
        dealerCallback);

    ASSERT_NE(nullptr, &dealerSocket.get());
    ASSERT_EQ(SocketType::Dealer, dealerSocket->Type());

    dealerSocket->SetTimeouts(
        std::chrono::milliseconds(0),
        std::chrono::milliseconds(30000),
        std::chrono::milliseconds(-1));
    dealerSocket->Start(dealerEndpoint_);

    dealerSocket_ = &dealerSocket;

    auto routerCallback =
        zmq::ListenCallback::Factory([this](zeromq::Message& input) -> void {
            EXPECT_EQ(3, input.size());
            const std::string& inputString = *input.Body().begin();
            bool match = inputString == testMessage_ ||
                         inputString == testMessage2_ ||
                         inputString == testMessage3_;

            EXPECT_TRUE(match);

            auto sent = dealerSocket_->get().Send(input);

            EXPECT_TRUE(sent);

            ++callbackFinishedCount_;
        });

    ASSERT_NE(nullptr, &routerCallback.get());

    auto routerSocket = zmq::RouterSocket::Factory(
        Test_RouterDealer::context_,
        zmq::Socket::Direction::Bind,
        routerCallback);

    ASSERT_NE(nullptr, &routerSocket.get());
    ASSERT_EQ(SocketType::Router, routerSocket->Type());

    routerSocket->SetTimeouts(
        std::chrono::milliseconds(0),
        std::chrono::milliseconds(-1),
        std::chrono::milliseconds(30000));
    routerSocket->Start(routerEndpoint_);

    routerSocket_ = &routerSocket;

    std::vector<OTZMQMessage> replyMessages;

    auto clientRouterCallback = zmq::ListenCallback::Factory(
        [this, &replyMessages](const network::zeromq::Message& input) -> void {
            const std::string& inputString = *input.Body().begin();
            bool match = inputString == testMessage_ ||
                         inputString == testMessage2_ ||
                         inputString == testMessage3_;

            EXPECT_TRUE(match);

            auto replyMessage = zeromq::Message::Factory();
            for (auto it = input.begin(); it != input.end(); ++it) {
                auto& frame = *it;
                if (0 < frame.size()) {
                    OTData data = Data::Factory(frame.data(), frame.size());
                    replyMessage->AddFrame(data.get());
                } else {
                    replyMessage->AddFrame();
                }
            }
            replyMessages.push_back(replyMessage);

            ++callbackFinishedCount_;
        });

    ASSERT_NE(nullptr, &clientRouterCallback.get());

    auto clientRouterSocket = zmq::RouterSocket::Factory(
        Test_RouterDealer::context_,
        zmq::Socket::Direction::Connect,
        clientRouterCallback);

    ASSERT_NE(nullptr, &clientRouterSocket.get());
    ASSERT_EQ(SocketType::Router, clientRouterSocket->Type());

    clientRouterSocket->SetTimeouts(
        std::chrono::milliseconds(0),
        std::chrono::milliseconds(30000),
        std::chrono::milliseconds(-1));
    clientRouterSocket->Start(dealerEndpoint_);

    // Send the requests on separate threads so this thread can continue and
    // wait for clientRouterCallback to finish.
    std::thread dealerSocketThread1(
        &Test_RouterDealer::dealerSocketThread,
        this,
        routerEndpoint_,
        testMessage_);

    std::thread dealerSocketThread2(
        &Test_RouterDealer::dealerSocketThread,
        this,
        routerEndpoint_,
        testMessage2_);

    std::thread dealerSocketThread3(
        &Test_RouterDealer::dealerSocketThread,
        this,
        routerEndpoint_,
        testMessage3_);

    auto end = std::time(nullptr) + 30;
    while (callbackFinishedCount_ < 6 && std::time(nullptr) < end)
        std::this_thread::sleep_for(std::chrono::milliseconds(100));

    ASSERT_EQ(6, callbackFinishedCount_);

    for (auto replyMessage : replyMessages) {
        clientRouterSocket->Send(replyMessage.get());
    }

    end = std::time(nullptr) + 30;
    while (callbackFinishedCount_ < 9 && std::time(nullptr) < end)
        std::this_thread::sleep_for(std::chrono::milliseconds(100));

    ASSERT_EQ(9, callbackFinishedCount_);

    dealerSocketThread1.join();
    dealerSocketThread2.join();
    dealerSocketThread3.join();

    routerSocket_ = nullptr;
    dealerSocket_ = nullptr;
}