From f57cfd7285dca6dfd16ceec22332436cee3de9cd Mon Sep 17 00:00:00 2001 From: Stefan Suhren Date: Mon, 21 Sep 2015 20:38:56 +0200 Subject: Nutze DER und zeige Nutzerschlüsselstatus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Der Im/Export von bzw. in DER funktioniert. Außerdem kann nun von außen überprüft werden, ob ein Nutzerschlüssel angelegt bzw. importiert wurde. Werfe einen Fehler, falls ein Nutzerschlüssel nicht vom Typ RSA ist. --- crypt/cryptexception.h | 3 +- crypt/hybridcrypt.cpp | 118 ++++++++++++++++++++++++++++++++++++++----------- crypt/hybridcrypt.h | 15 ++++++- 3 files changed, 109 insertions(+), 27 deletions(-) (limited to 'crypt') diff --git a/crypt/cryptexception.h b/crypt/cryptexception.h index 0a4edae..172c5c9 100644 --- a/crypt/cryptexception.h +++ b/crypt/cryptexception.h @@ -25,7 +25,8 @@ public: KeyNotRsa, CsprngNotSeeded, NoUserKeyCreated, - NoRecipients + NoRecipients, + FormatNotSupported }; /** diff --git a/crypt/hybridcrypt.cpp b/crypt/hybridcrypt.cpp index a9b410d..05e9995 100644 --- a/crypt/hybridcrypt.cpp +++ b/crypt/hybridcrypt.cpp @@ -84,30 +84,10 @@ void HybridCrypt::encrypt(QString infileName, QString outfileName, EVP_PKEY *tmpKey; QByteArray tmpData; - FILE *tmpKeyfile; for (int i = 0; i < recipientKeyfileNames.length(); i++) { - tmpKeyfile = fopen(recipientKeyfileNames[i].toStdString().c_str(), "r"); - - // Datei existiert nicht - if (tmpKeyfile == NULL) - { - throw CryptException("Datei nicht gefunden: " + - recipientKeyfileNames[i].toStdString(), CryptException::FileNotFound); - } - - // Ließ den aktuellen Empfängerschlüssel ein - tmpKey = PEM_read_PUBKEY(tmpKeyfile, NULL, NULL, NULL); - - // Räume die Ressourcen auf - fclose(tmpKeyfile); - - // Wirf Fehler, falls der Schlüssel nicht gelesen werden konnte - if (tmpKey == NULL) - { - throwOpenSslException(); - } + tmpKey = readRecipientKey(recipientKeyfileNames[i]); // Schreibe den Header in die Datei tmpData = encryptAesData(tmpKey, aesKey + aesIv); @@ -341,9 +321,26 @@ void HybridCrypt::importUserKeypair(QString keyfileName, QString password) CryptException::FileNotFound); } - // Ließ den Schlüssel des Nutzers ein - userKeypair = PEM_read_PrivateKey(keyfile, NULL, NULL, - (void *) password.toStdString().c_str()); + // Ließ den Schlüssel des Nutzers anhand der Erweiterung ein + QString keyfileExtension = keyfileName.right(3).toLower(); + + if (keyfileExtension == "pem") + { + userKeypair = PEM_read_PrivateKey(keyfile, NULL, NULL, + (void *) password.toStdString().c_str()); + } + else if (keyfileExtension == "der") + { + userKeypair = d2i_PKCS8PrivateKey_fp(keyfile, NULL, NULL, + (void *) password.toStdString().c_str()); + } + else + { + // Räume die Ressourcen auf + fclose(keyfile); + throw CryptException("Dateiformat wird nicht unterstützt.", + CryptException::FormatNotSupported); + } // Räume die Ressourcen auf fclose(keyfile); @@ -374,6 +371,7 @@ void HybridCrypt::exportUserKeypair(QString keyfileName, QString password) } // Wenn password ein Leerstring ist, verschlüssele den privaten Schlüssel nicht + // Wird nur im PEM-Format exportiert int opensslReturnError = PEM_write_PKCS8PrivateKey(keyfile, userKeypair, (password.isEmpty()) ? NULL : EVP_aes_256_cbc(), NULL, 0, NULL, (void *) password.toStdString().c_str()); @@ -401,7 +399,26 @@ void HybridCrypt::exportPublicUserKey(QString keyfileName) keyfileName.toStdString(), CryptException::FileNotWritable); } - int opensslReturnError = PEM_write_PUBKEY(keyfile, userKeypair); + int opensslReturnError; + + // Wähle Funktion zum Schreiben des öffentlichen Schlüssels anhand der Dateierweiterung aus + QString keyfileExtension = keyfileName.right(3).toLower(); + + if (keyfileExtension == "pem") + { + opensslReturnError = PEM_write_PUBKEY(keyfile, userKeypair); + } + else if (keyfileExtension == "der") + { + opensslReturnError = i2d_PUBKEY_fp(keyfile, userKeypair); + } + else + { + // Räume die Ressourcen auf + fclose(keyfile); + throw CryptException("Dateiformat wird nicht unterstützt.", + CryptException::FormatNotSupported); + } // Räume die Ressourcen auf fclose(keyfile); @@ -413,6 +430,11 @@ void HybridCrypt::exportPublicUserKey(QString keyfileName) } } +bool HybridCrypt::isUserKeyInitialised() +{ + return userKeypair == NULL; +} + /* * Private Funktionen */ @@ -549,6 +571,52 @@ QByteArray HybridCrypt::decryptAesData(EVP_PKEY *pkey, QByteArray data) return out; } +EVP_PKEY *HybridCrypt::readRecipientKey(QString keyfileName) +{ + FILE *tmpKeyfile = fopen(keyfileName.toStdString().c_str(), "r"); + + // Datei existiert nicht + if (tmpKeyfile == NULL) + { + throw CryptException("Datei nicht gefunden: " + + keyfileName.toStdString(), CryptException::FileNotFound); + } + + EVP_PKEY *tmpKey; + + // Entscheide welche Funktion zu benutzen ist + QString keyfileExtension = keyfileName.right(3).toLower(); + + if (keyfileExtension == "pem") + { + tmpKey = PEM_read_PUBKEY(tmpKeyfile, NULL, NULL, NULL); + } + else if (keyfileExtension == "der") + { + tmpKey = d2i_PUBKEY_fp(tmpKeyfile, NULL); + } + else + { + // Räume die Ressourcen auf + fclose(tmpKeyfile); + throw CryptException("Dateiformat wird nicht unterstützt.", + CryptException::FormatNotSupported); + } + + // Räume die Ressourcen auf + fclose(tmpKeyfile); + + // Wirf Fehler, falls der Schlüssel nicht gelesen werden konnte + if (tmpKey == NULL) + { + throwOpenSslException(); + } + + throwExceptionIfEvpKeyIsNotRsa(&tmpKey); + + return tmpKey; +} + bool HybridCrypt::isCsprngSeeded() { return RAND_status() == 1; diff --git a/crypt/hybridcrypt.h b/crypt/hybridcrypt.h index d0c7202..fd0d515 100644 --- a/crypt/hybridcrypt.h +++ b/crypt/hybridcrypt.h @@ -72,7 +72,7 @@ public: void importUserKeypair(QString keyfileName, QString password); /** - * @brief Exportiert das Schlüsselpaar des Nutzers im (PEM|DER|NET|ASC) Format. + * @brief Exportiert das Schlüsselpaar des Nutzers im PEM-Format. * @param keyfileName Der Name der Datei in die das Schlüsselpaar exportiert wird (wird angelegt/überschrieben). * @param password Das Password mit dem der private Schlüssel des Nutzers verschlüsselt wird. * @throws CryptException Fehler, die bei der Verschlüsselung auftreten können. @@ -87,6 +87,12 @@ public: */ void exportPublicUserKey(QString keyfileName); + /** + * @brief Gibt an, ob eine Nutzerschlüssel bereits importiert/erzeugt wurde. + * @return Wahr, falls ein Nutzerschlüssel existiert, ansonsten falsch. + */ + bool isUserKeyInitialised(); + private: EVP_PKEY *userKeypair; // Enthält nur den privaten Schlüssel, da OpenSSL nicht mehr braucht. @@ -108,6 +114,13 @@ private: */ QByteArray decryptAesData(EVP_PKEY *pkey, QByteArray data); + /** + * @brief Ließt einen Empfängerschlüssel aus einer Datei ein. + * @param keyfileName Der Dateiname aus dem der öffentliche Schlüssel gelsen wird. + * @return Der EVP_PKEY für OpenSSL. + */ + EVP_PKEY *readRecipientKey(QString keyfileName); + /** * @brief Gibt an, ob der Zufallszahlengenerator von OpenSSL mit ausreichend Entropie initialisiert wurde. * @return Gibt wahr zurück wenn ausreichend intialisert wurde, ansonsten falsch. -- cgit v1.2.3-70-g09d2