// Base64-decode an decompress bool OTASCIIArmor::GetString(String& strData, bool bLineBreaks) const // bLineBreaks=true { strData.Release(); if (GetLength() < 1) { return true; } size_t outSize = 0; uint8_t* pData = App::Me().Crypto().Util().Base64Decode(Get(), &outSize, bLineBreaks); if (!pData) { otErr << __FUNCTION__ << "Base64Decode fail\n"; return false; } std::string str_decoded(pData, pData + outSize); delete[] pData; std::string str_uncompressed; try { str_uncompressed = decompress_string(str_decoded); } catch (const std::runtime_error&) { otErr << __FUNCTION__ << ": decompress failed\n"; return false; } strData.Set(str_uncompressed.c_str(), str_uncompressed.length()); return true; }
/// if we pack, compress, encode on the way in, that means, therefore, we /// need to decode, uncompress, then unpack on our way out. Right? /// /// This function will base64-DECODE the string contents, then uncompress them using /// zlib, and then unpack the result using whatever is the default packer (MsgPack, Protobuf, etc). /// /// I originally added compression because message sizes were too big. Now I'm adding packing, /// to solve any issues of binary compatibility across various platforms. // bool OTASCIIArmor::GetAndUnpackString(OTString & strData, bool bLineBreaks) const //bLineBreaks=true { size_t outSize = 0; uint8_t * pData = NULL; strData.Release(); if (GetLength() < 1) { return true; } // -------------------------------------------------------------- pData = OTCrypto::It()->Base64Decode(this->Get(), &outSize, bLineBreaks); // pData = OT_base64_decode(Get(), &outSize, (bLineBreaks ? 1 : 0)); if (pData) { std::string str_decoded( pData, pData+outSize ); delete [] pData; pData=NULL; std::string str_uncompressed = decompress_string( str_decoded ); // --------------------------------------- // PUT THE PACKED BUFFER HERE, AND UNPACK INTO strData // -------------------------------------------------------- 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); // This will make sure buffer is deleted later. pBuffer->SetData(reinterpret_cast<const uint8_t *>(str_uncompressed.data()), str_uncompressed.size()); // ----------------------------- OTDB::OTDBString * pOTDBString = dynamic_cast<OTDB::OTDBString *>(OTDB::CreateObject(OTDB::STORED_OBJ_STRING)); OT_ASSERT(NULL != pOTDBString); OTCleanup<OTDB::OTDBString> theStringAngel(*pOTDBString); // clean up this string. bool bUnpacked = pPacker->Unpack(*pBuffer, *pOTDBString); // ---------------------- if (false == bUnpacked) { OTLog::Error("Failed unpacking string in OTASCIIArmor::GetAndUnpackString.\n"); return false; } // -------------------------------------------------------- // This enforces the null termination. (using the 2nd parameter as nEnforcedMaxLength) strData.Set(pOTDBString->m_string.c_str(), static_cast<uint32_t> (pOTDBString->m_string.length())); return true; } else { OTLog::Error("OTASCIIArmor::GetAndUnpackString: NULL pData while base64-decoding pData.\n"); return false; } }
void DlgDecrypt::on_pushButtonDecrypt_clicked() { bool bSuccessDecrypting = false; bool bSuccessVerifying = false; QString qstrNymWhoDecrypted; QString qstrNymWhoVerified; QString qstrText = ui->plainTextEdit->toPlainText().trimmed(); // -------------------------------- if (qstrText.isEmpty()) { // pop up a message box warning that the input text is empty. // QMessageBox::warning(this, tr("Ciphertext is Empty"), tr("Please paste something to be decrypted/verified.")); return; } // -------------------------------- else //qstrText not empty. { std::string str_input(qstrText.toStdString()); opentxs::String strInput (str_input.c_str()); if (strInput.Exists()) { if (strInput.Contains("-----BEGIN OT ARMORED ENVELOPE-----")) { opentxs::OTEnvelope theEnvelope; if (theEnvelope.SetFromBookendedString(strInput)) { opentxs::String strOutput; // ------------------------- // First we'll try the default nym, if one is available. // QString qstrTempID = Moneychanger::It()->get_default_nym_id(); if (!qstrTempID.isEmpty()) // Default Nym IS available. { std::string str_nym (qstrTempID.toStdString()); opentxs::String strNym (str_nym.c_str()); opentxs::Identifier nym_id (strNym); if (!nym_id.IsEmpty()) { opentxs::OTPasswordData thePWData("Recipient passphrase"); opentxs::Nym * pNym = opentxs::OTAPI_Wrap::OTAPI()->GetOrLoadPrivateNym(nym_id, false, //bChecking=false __FUNCTION__, &thePWData); if (NULL != pNym) { if (theEnvelope.Open(*pNym, strOutput) && strOutput.Exists()) { bSuccessDecrypting = true; qstrNymWhoDecrypted = qstrTempID; strInput = strOutput; str_input = strInput.Get(); qstrText = QString::fromStdString(str_input); } } } } // ------------ if (!bSuccessDecrypting) // Default nym is NOT available. Okay let's loop through all the Nyms in the wallet then, and try then all... { const int32_t nym_count = opentxs::OTAPI_Wrap::It()->GetNymCount(); // ----------------------------------------------- for (int32_t ii = 0; ii < nym_count; ++ii) { //Get OT Nym ID QString OT_nym_id = QString::fromStdString(opentxs::OTAPI_Wrap::It()->GetNym_ID(ii)); if (!OT_nym_id.isEmpty()) { std::string str_nym (OT_nym_id.toStdString()); opentxs::String strNym (str_nym.c_str()); opentxs::Identifier nym_id (strNym); if (!nym_id.IsEmpty()) { opentxs::OTPasswordData thePWData("Recipient passphrase"); opentxs::Nym * pNym = opentxs::OTAPI_Wrap::OTAPI()->GetOrLoadPrivateNym(nym_id, false, //bChecking=false "DlgEncrypt::on_pushButtonDecrypt_clicked", &thePWData); if (NULL != pNym) { // Okay there is a private key available for this Nym, so let's // try to open the envelope using it. // if (theEnvelope.Open(*pNym, strOutput) && strOutput.Exists()) { bSuccessDecrypting = true; qstrNymWhoDecrypted = OT_nym_id; strInput = strOutput; str_input = strInput.Get(); qstrText = QString::fromStdString(str_input); break; } } } // ------------ } } // for } // else default nym not available. // ----------------------- if (!bSuccessDecrypting) { QMessageBox::warning(this, tr("Failed Decrypting"), tr("None of the identities in your wallet (including your default identity, " "if applicable) were able to open this message.")); return; } // ----------------------- } // if (theEnvelope.SetFromBookendedString(strInput)) } // if (strInput.Contains("-----BEGIN OT ARMORED ENVELOPE-----")) // -------------------------------------------- // This call to DecodeIfArmored is what handles the: "-----BEGIN OT ARMORED ... -----" if (strInput.DecodeIfArmored(false)) // bEscapedIsAllowed=true by default. { std::string str_decoded(strInput.Get()); QString qstrDecoded(QString::fromStdString(str_decoded)); if (!qstrDecoded.isEmpty()) qstrText = qstrDecoded; // ----------------------------------- // At this point, we know it's been decrypted, if applicable, and it's been // de-armored, if applicable. So now we check to see if it's a signed file. // if (strInput.Contains("-----BEGIN SIGNED FILE-----")) { opentxs::OTSignedFile theSignedFile; if (theSignedFile.LoadContractFromString(strInput)) { opentxs::String strSignerNymID = theSignedFile.GetSignerNymID(); std::string str_signer_nym(strSignerNymID.Get()); QString qstrSignerNym(QString::fromStdString(str_signer_nym)); if (!str_signer_nym.empty()) { opentxs::OTPasswordData thePWData("Sometimes need to load private part of nym in order to use its public key. (Fix that!)"); opentxs::Identifier id_signer_nym(strSignerNymID); const opentxs::Nym * pNym = opentxs::OTAPI_Wrap::OTAPI()->GetOrLoadNym(id_signer_nym, false, //bChecking=false __FUNCTION__, &thePWData); if (NULL != pNym) { if (theSignedFile.VerifySignature(*pNym, &thePWData)) { bSuccessVerifying = true; qstrNymWhoVerified = qstrSignerNym; opentxs::String strContents = theSignedFile.GetFilePayload(); if (strContents.Exists()) { strInput = strContents; str_input = strInput.Get(); qstrText = QString::fromStdString(str_input); } } // signature verified } // pNym exists } // if str_signer_nym exists } // signed file: load contract from string. } // "BEGIN SIGNED FILE" } // Decode If Armored. // ----------------------------------------------- // if qstrText still contains something, pop up a dialog to display the result to the user. // if (!qstrText.isEmpty()) { MTNameLookupQT theLookup; QString qstrNymWhoDecryptedName(""), qstrNymWhoVerifiedName(""); if (!qstrNymWhoDecrypted.isEmpty()) qstrNymWhoDecryptedName = QString::fromStdString(theLookup.GetNymName(qstrNymWhoDecrypted.toStdString(), "")); if (!qstrNymWhoVerified.isEmpty()) qstrNymWhoVerifiedName = QString::fromStdString(theLookup.GetNymName(qstrNymWhoVerified.toStdString(), "")); // ------------------------------- if (qstrNymWhoDecryptedName.isEmpty()) qstrNymWhoDecryptedName = qstrNymWhoDecrypted; else if (qstrNymWhoDecryptedName != qstrNymWhoDecrypted) qstrNymWhoDecryptedName += QString(" (%1)").arg(qstrNymWhoDecrypted); // ------------------------------- if (qstrNymWhoVerifiedName.isEmpty()) qstrNymWhoVerifiedName = qstrNymWhoVerified; else if (qstrNymWhoVerifiedName != qstrNymWhoVerified) qstrNymWhoVerifiedName += QString(" (%1)").arg(qstrNymWhoVerified); // ------------------------------- QString qstrType("Output:"); if (bSuccessVerifying) { qstrType = QString("%1: %2").arg(tr("Verified signature by Nym")).arg(qstrNymWhoVerifiedName); } // ----------- if (bSuccessDecrypting) { if (bSuccessVerifying) qstrType = QString("%1: %2\n%3: %4").arg(tr("Decrypted using Nym")).arg(qstrNymWhoDecryptedName).arg(tr("Verified signature by Nym")).arg(qstrNymWhoVerifiedName); else qstrType = QString("%1: %2").arg(tr("Decrypted using Nym")).arg(qstrNymWhoDecryptedName); } // ----------- QString qstrSubTitle(tr("Be sure to copy it somewhere before closing this dialog.")); // ----------- // Pop up the result dialog. // DlgExportedToPass dlgExported(this, qstrText, qstrType, qstrSubTitle, false); dlgExported.exec(); } // if (!qstrText.isEmpty()) } // if strInput } //qstrText not empty }