QByteArray EncryptioNgSimliteDecryptor::decrypt(const QByteArray &data, bool *ok) { if (ok) *ok = false; if (!Valid) return data; //check if the message has at least the length of the shortest possible encrypted message if (data.length() < 192) return data; //decode the message from the Base64 encoding QCA::Base64 decoder(QCA::Decode); QCA::SecureArray decodedMessage = decoder.stringToArray(data); if (!decoder.ok()) return data; //extract the Blowfish key (first 128 characters) QCA::SecureArray encryptedBlowfishKey(decodedMessage.toByteArray().left(128)); //and the encrypted message (the rest) QCA::SecureArray encryptedMessage(decodedMessage.toByteArray().mid(128)); QCA::SymmetricKey blowfishKey; if (!DecodingKey.decrypt(encryptedBlowfishKey, &blowfishKey, QCA::EME_PKCS1_OAEP)) return data; //recreate the initialization vector (should be the same as the one used for ciphering) char ivec[8] = {0, 0, 0, 0, 0, 0, 0, 0}; QCA::InitializationVector iv(QByteArray(ivec, 8)); //now that we have the symmetric Blowfish key, we can decrypt the message; //create a 128 bit Blowfish cipher object using Cipher Block Chaining (CBC) mode, //with default padding and for decoding QCA::Cipher cipher(QString("blowfish"), QCA::Cipher::CBC, QCA::Cipher::DefaultPadding, QCA::Decode, blowfishKey, iv); //decipher the message (put the message into the decoding cipher object) QCA::SecureArray plainText = cipher.process(encryptedMessage); if (!cipher.ok()) return data; //check whether the decrypted data length is at least the size of the header - //if not, then we have an invalid message if (plainText.size() < (int)sizeof(sim_message_header)) return data; //extract the header from the decrypted data and check if the magic number is //correct sim_message_header head; memcpy(&head, plainText.data(), sizeof(sim_message_header)); if (head.magicFirstPart != SIM_MAGIC_V1_1 || head.magicSecondPart != SIM_MAGIC_V1_2) return data; if (ok) *ok = true; //the message has been decrypted! :D //put it into the input/output byte array return cp2unicode(&plainText.data()[sizeof(sim_message_header)]).toUtf8(); }
bool EncryptedStore::openRead(const QString& name) { Q_D(KOdfStore); if (bad()) return false; const KArchiveEntry* fileArchiveEntry = m_pZip->directory()->entry(name); if (!fileArchiveEntry) { return false; } if (fileArchiveEntry->isDirectory()) { kWarning(30002) << name << " is a directory!"; return false; } const KZipFileEntry* fileZipEntry = static_cast<const KZipFileEntry*>(fileArchiveEntry); delete d->stream; d->stream = fileZipEntry->createDevice(); d->size = fileZipEntry->size(); if (m_encryptionData.contains(name)) { // This file is encrypted, do some decryption first if (m_bPasswordDeclined) { // The user has already declined to give a password // Open the file as empty d->stream->close(); delete d->stream; d->stream = new QBuffer(); d->stream->open(QIODevice::ReadOnly); d->size = 0; return true; } QCA::SecureArray encryptedFile(d->stream->readAll()); if (encryptedFile.size() != d->size) { // Read error detected d->stream->close(); delete d->stream; d->stream = NULL; kWarning(30002) << "read error"; return false; } d->stream->close(); delete d->stream; d->stream = NULL; KoEncryptedStore_EncryptionData encData = m_encryptionData.value(name); QCA::SecureArray decrypted; // If we don't have a password yet, try and find one if (m_password.isEmpty()) { findPasswordInKWallet(); } while (true) { QByteArray pass; QCA::SecureArray password; bool keepPass = false; // I already have a password! Let's test it. If it's not good, we can dump it, anyway. if (!m_password.isEmpty()) { password = m_password; m_password = QCA::SecureArray(); } else { if (!m_filename.isNull()) keepPass = false; QPointer<KPasswordDialog> dlg = new KPasswordDialog(d->window , keepPass ? KPasswordDialog::ShowKeepPassword : static_cast<KPasswordDialog::KPasswordDialogFlags>(0)); dlg->setPrompt(i18n("Please enter the password to open this file.")); if (! dlg->exec()) { m_bPasswordDeclined = true; d->stream = new QBuffer(); d->stream->open(QIODevice::ReadOnly); d->size = 0; delete dlg; return true; } if (dlg) { password = QCA::SecureArray(dlg->password().toUtf8()); if (keepPass) keepPass = dlg->keepPassword(); if (password.isEmpty()) { delete dlg; continue; } } delete dlg; } decrypted = decryptFile(encryptedFile, encData, password); if (decrypted.isEmpty()) { kError(30002) << "empty decrypted file" << endl; return false; } if (!encData.checksum.isEmpty()) { QCA::SecureArray checksum; if (encData.checksumShort && decrypted.size() > 1024) { // TODO: Eww!!!! I don't want to convert via insecure arrays to get the first 1K characters of a secure array <- fix QCA? checksum = QCA::Hash("sha1").hash(QCA::SecureArray(decrypted.toByteArray().left(1024))); } else { checksum = QCA::Hash("sha1").hash(decrypted); } if (checksum != encData.checksum) { continue; } } // The password passed all possible tests, so let's accept it m_password = password; m_bPasswordUsed = true; if (keepPass) { savePasswordInKWallet(); } break; } QByteArray *resultArray = new QByteArray(decrypted.toByteArray()); QIODevice *resultDevice = KFilterDev::device(new QBuffer(resultArray, NULL), "application/x-gzip"); if (!resultDevice) { delete resultArray; return false; } static_cast<KFilterDev*>(resultDevice)->setSkipHeaders(); d->stream = resultDevice; d->size = encData.filesize; } d->stream->open(QIODevice::ReadOnly); return true; }
if (s != SECSuccess) { qDebug() << "DigestBegin failed"; return; } } void update(const QCA::MemoryRegion &a) { PK11_DigestOp(m_context, (const unsigned char*)a.data(), a.size()); } QCA::MemoryRegion final() { unsigned int len = 0; QCA::SecureArray a( 64 ); PK11_DigestFinal(m_context, (unsigned char*)a.data(), &len, a.size()); a.resize(len); return a; } private: PK11SlotInfo *m_slot; int m_status; PK11Context *m_context; SECOidTag m_hashAlgo; }; //----------------------------------------------------------- class nssHmacContext : public QCA::MACContext {
void HatchetSipPlugin::webSocketConnected() { tLog() << Q_FUNC_INFO << "WebSocket connected"; if ( m_token.isEmpty() || !m_account->credentials().contains( "username" ) ) { tLog() << Q_FUNC_INFO << "access token or username is empty, aborting"; disconnectPlugin(); return; } hatchetAccount()->setConnectionState( Tomahawk::Accounts::Account::Connected ); m_sipState = AcquiringVersion; m_uuid = QUuid::createUuid().toString(); QCA::SecureArray sa( m_uuid.toLatin1() ); QCA::SecureArray result = m_publicKey->encrypt( sa, QCA::EME_PKCS1_OAEP ); tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "uuid:" << m_uuid << ", size of uuid:" << m_uuid.size() << ", size of sa:" << sa.size() << ", size of result:" << result.size(); QVariantMap nonceVerMap; nonceVerMap[ "version" ] = VERSION; nonceVerMap[ "nonce" ] = QString( result.toByteArray().toBase64() ); sendBytes( nonceVerMap ); }