diff options
| author | Stefan Suhren <suhren.stefan@fh-swf.de> | 2015-09-19 14:46:39 +0200 |
|---|---|---|
| committer | Stefan Suhren <suhren.stefan@fh-swf.de> | 2015-09-19 18:13:45 +0200 |
| commit | c69cbcc54549f1733eefd8c275d083c6fa44cc26 (patch) | |
| tree | c910f7fafb4babe8ea9cd1e308c81af1953e27f8 | |
| parent | 8e05c99a599ca51d5aaf92a121d1f68acc07459e (diff) | |
| download | src-c69cbcc54549f1733eefd8c275d083c6fa44cc26.tar.gz src-c69cbcc54549f1733eefd8c275d083c6fa44cc26.zip | |
Implementiere decrypt und passe keyCount Länge an
| -rw-r--r-- | crypt/hybridcrypt.cpp | 177 | ||||
| -rw-r--r-- | crypt/hybridcrypt.h | 9 |
2 files changed, 183 insertions, 3 deletions
diff --git a/crypt/hybridcrypt.cpp b/crypt/hybridcrypt.cpp index 63e241e..a9b410d 100644 --- a/crypt/hybridcrypt.cpp +++ b/crypt/hybridcrypt.cpp @@ -80,7 +80,7 @@ void HybridCrypt::encrypt(QString infileName, QString outfileName, } // Schreibe die Anzahl der PublicKeys als erstes in die Datei - outfileStream << (qint64) keyCount; + outfileStream << (qint32) keyCount; EVP_PKEY *tmpKey; QByteArray tmpData; @@ -166,8 +166,7 @@ void HybridCrypt::encrypt(QString infileName, QString outfileName, } // Nun bekommen wir den letzten Block, falls die Datei nicht ein Vielfaches der AES Blöckgröße war - if (1 != EVP_EncryptFinal_ex(ctx, (unsigned char *)outBuf.data(), - &len)) + if (1 != EVP_EncryptFinal_ex(ctx, (unsigned char *) outBuf.data(), &len)) { // Räume den symmetrischen Schlüsselkontext ab freeCipherCtx(&ctx); @@ -183,7 +182,107 @@ void HybridCrypt::encrypt(QString infileName, QString outfileName, void HybridCrypt::decrypt(QString infileName, QString outfileName) { + throwExceptionIfUserKeyIsNull(); + + QFile infile(infileName); + QFile outfile(outfileName); + + if (!infile.open(QFile::ReadOnly)) + { + throw CryptException("Datei nicht gefunden: " + infileName.toStdString(), + CryptException::FileNotFound); + } + + if (!outfile.open(QFile::ReadWrite | QFile::Truncate)) + { + throw CryptException("Konnte Datei nicht schreiben: " + + outfileName.toStdString(), CryptException::FileNotWritable); + } + + QDataStream infileStream(&infile); + QDataStream outfileStream(&outfile); + + qint32 keyCount = 0; + + // Lese die Anzahl der Schlüssel aus der Datei + infileStream >> keyCount; + + QByteArray tmpData; + QByteArray aesKey(EVP_CIPHER_key_length(EVP_aes_256_cbc()), 0); + QByteArray aesIv(EVP_CIPHER_iv_length(EVP_aes_256_cbc()), 0); + + // Versuche alle Header zu entschlüsseln + for (qint32 i = 0; i < keyCount && tmpData.length() == 0; i++) + { + tmpData.resize(256); + infileStream.readRawData(tmpData.data(), tmpData.length()); + tmpData = decryptAesData(userKeypair, tmpData); + } + + // Wenn kein Header entschlüsselt werden konnte, wirf eine Excption + if (tmpData.length() == 0) + { + throw CryptException("Fehler beim Entschlüsseln des RSA Blockes", + CryptException::DecryptionErrorRsa); + } + + // Ließ die Aes Daten aus + aesKey = tmpData.left(aesKey.length()); + aesIv = tmpData.mid(aesKey.length(), aesIv.length()); + + // Erzeuge den symmetrischen Kontext + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + + // Überprüfe den Schlüssel + if (!ctx) + { + throwOpenSslException(); + } + + // Setze den Verschlüsselungsalgorithmus, sowie den Schlüssel und den IV + if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, + (unsigned char *) aesKey.data(), (unsigned char *) aesIv.data())) + { + // Räume den symmetrischen Schlüsselkontext ab + freeCipherCtx(&ctx); + throwOpenSslException(); + } + + QByteArray inBuf(EVP_CIPHER_block_size(EVP_aes_256_cbc()), 0); + QByteArray outBuf(EVP_CIPHER_block_size(EVP_aes_256_cbc()), 0); + int bufRead; + int len; + + while (!infileStream.atEnd()) + { + // Hole jeweils einen Block an Daten aus der Datei + bufRead = infileStream.readRawData(inBuf.data(), inBuf.size()); + + // Entschlüssele den Block mit AES + if (1 != EVP_DecryptUpdate(ctx, (unsigned char *) outBuf.data(), &len, + (unsigned char *) inBuf.data(), bufRead)) + { + // Räume den symmetrischen Schlüsselkontext ab + freeCipherCtx(&ctx); + throwOpenSslException(); + } + + // Schreibe den Block in die Ausgabedatei + outfileStream.writeRawData(outBuf.data(), len); + } + // Wirft Fehler, falls Padding falsch oder der letzte Block unvollständig war + if (1 != EVP_DecryptFinal_ex(ctx, (unsigned char *) outBuf.data(), &len)) + { + // Räume den symmetrischen Schlüsselkontext ab + freeCipherCtx(&ctx); + throwOpenSslException(); + } + + outfileStream.writeRawData(outBuf.data(), len); + + // Räume den symmetrischen Schlüsselkontext ab + freeCipherCtx(&ctx); } void HybridCrypt::createKeypair() @@ -378,6 +477,78 @@ QByteArray HybridCrypt::encryptAesData(EVP_PKEY *pkey, QByteArray data) return out; } +QByteArray HybridCrypt::decryptAesData(EVP_PKEY *pkey, QByteArray data) +{ + // Das QByteArray das zurück gegeben wird + QByteArray out; + + // Wird benutzt um die Länge von out zu bestimmen + size_t outlen; + + // Lege Schlüsselkontext an + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); + + // Überprüfe erflogreiche Schlüsselkontexterzeugung + if (!ctx) + { + throwOpenSslException(); + } + + // Initialisiere den Schlüsselkontext + if (EVP_PKEY_decrypt_init(ctx) <= 0) + { + // Räume den Schlüsselkontext ab + freePkeyCtx(&ctx); + throwOpenSslException(); + } + + // Setze für den Schlüsselkontext das RSA Padding + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) + { + // Räume den Schlüsselkontext ab + freePkeyCtx(&ctx); + throwOpenSslException(); + } + + // Finde die Blockgröße für RSA raus + if (EVP_PKEY_decrypt(ctx, NULL, &outlen, (unsigned char *) data.data(), + data.length()) <= 0) + { + // Räume den Schlüsselkontext ab + freePkeyCtx(&ctx); + throwOpenSslException(); + } + + // Setze out auf RSA Blockgröße + out.resize(outlen); + + // Entschlüssele den AES Key und den IV + if (EVP_PKEY_decrypt(ctx, (unsigned char *) out.data(), &outlen, + (unsigned char *) data.data(), data.length()) <= 0) + { + // Wenn der Fehler von OAEP kommt, ignoriere fürs erste + if (ERR_GET_LIB(ERR_peek_error()) == 4 && + ERR_GET_FUNC(ERR_peek_error()) == 161 && + ERR_GET_REASON(ERR_peek_error()) == 121) + { + // Lösche Error aus der Schlange + ERR_get_error(); + out.resize(0); + } + else + { + // Räume den Schlüsselkontext ab + freePkeyCtx(&ctx); + throwOpenSslException(); + } + } + + // Räume den Schlüsselkontext ab + freePkeyCtx(&ctx); + + return out; +} + bool HybridCrypt::isCsprngSeeded() { return RAND_status() == 1; diff --git a/crypt/hybridcrypt.h b/crypt/hybridcrypt.h index a9d9dc2..d0c7202 100644 --- a/crypt/hybridcrypt.h +++ b/crypt/hybridcrypt.h @@ -100,6 +100,15 @@ private: QByteArray encryptAesData(EVP_PKEY *pkey, QByteArray data); /** + * @brief Verschlüsselt den IV und den Key vom AES mit RSA. + * Und nutzt als Padding RSA_OAEP_PADDING. + * @param pkey Der EVP_PKEY mit dem Verschlüsselt wurde. + * @param data Der RSA Verschlüsselte Block. + * @return Der Aes Key and IV. (Länge is null, falls OAEP Fehler auftrat. + */ + QByteArray decryptAesData(EVP_PKEY *pkey, QByteArray data); + + /** * @brief Gibt an, ob der Zufallszahlengenerator von OpenSSL mit ausreichend Entropie initialisiert wurde. * @return Gibt wahr zurück wenn ausreichend intialisert wurde, ansonsten falsch. */ |
