summaryrefslogtreecommitdiffstats
path: root/crypt/hybridcrypt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'crypt/hybridcrypt.cpp')
-rw-r--r--crypt/hybridcrypt.cpp177
1 files changed, 174 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;