summaryrefslogtreecommitdiffstats
path: root/crypt/hybridcrypt.h
blob: a9d9dc22e4ba517a1b155ec2eec19d7a24ea62d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#ifndef HYBRIDCRYPT_H
#define HYBRIDCRYPT_H

#include <cstdio>

#include <QByteArray>
#include <QDataStream>
#include <QDebug>
#include <QFile>
#include <QString>
#include <QVector>

#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>

#include "cryptexception.h"

/**
 * @brief Eine Klasse die sich um hybride Verschlüsselung mittels RSA und AES kümmert.
 */
class HybridCrypt
{
public:

    /**
     * @brief Initialisiert OpenSSL.
     */
    HybridCrypt();

    /**
     * @brief Räumt OpenSSL auf.
     */
    ~HybridCrypt();

    /**
     * @brief Ließt eine Datei ein und schreibt diese verschlüsselt
     * mit den übergebenen Schlüsseln und dem Nutzerschlüssel.
     * @param infileName Der Name der zu verschlüsselnde Datei.
     * @param outfileName Der Name der verschlüsselten Datei (wird angelegt/überschrieben).
     * @param recipientKeyfileNames Die Schlüssel der Empfänger,
     * mit denen die Datei verschlüsselt wird (Sollte nicht den Nutzerschlüssel enthalten).
     * @throws CryptException Fehler, die bei der Verschlüsselung auftreten können.
     */
    void encrypt(QString infileName, QString outfileName,
                 QVector<QString> recipientKeyfileNames);

    /**
     * @brief Entschlüsselt die übergeben Datei mit dem Nutzerschlüssel und schreibt diese entschlüsselt.
     * @param infileName Der Name der zu entschlüsselnden Datei.
     * @param outfileName Der Name der entschlüsselten Datei (wird angelegt/überschrieben).
     * @throws CryptException Fehler, die bei der Verschlüsselung auftreten können.
     */
    void decrypt(QString infileName, QString outfileName);

    /**
     * @brief Erzeugt sicher ein neues RSA Schlüsselpaar zur Verwendung in #encrypt und #decrypt.
     * Sollte mittel #exportUserKeypair exportiert werden.
     * @throws CryptException Fehler, die bei der Verschlüsselung auftreten können.
     */
    void createKeypair();

    /**
     * @brief Importiert das Schlüsselpaar des Nutzers zur Verwendung in #encrypt und #decrypt.
     * @param keyfileName Der Name der Schlüsseldatei im (PEM|DER|NET|ASC) Format, die importiert werden soll.
     * @param password Das Password mit dem der private Schlüssel in der Datei verschlüsselt ist.
     * @throws CryptException Fehler, die bei der Verschlüsselung auftreten können.
     */
    void importUserKeypair(QString keyfileName, QString password);

    /**
     * @brief Exportiert das Schlüsselpaar des Nutzers im (PEM|DER|NET|ASC) 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.
     */
    void exportUserKeypair(QString keyfileName, QString password);


    /**
     * @brief Exportiert den öffentlichen Schlüssel des Nutzers im (PEM|DER|NET|ASC) Format.
     * @param keyfileName Der Name der Datei in den der öffentliche Schlüssel exportiert wird (wird angelegt/überschrieben).
     * @throws CryptException Fehler, die bei der Verschlüsselung auftreten können.
     */
    void exportPublicUserKey(QString keyfileName);

private:
    EVP_PKEY *userKeypair; // Enthält nur den privaten Schlüssel, da OpenSSL nicht mehr braucht.

    /**
     * @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 wird.
     * @param data Der AES Key und IV.
     * @return Den RSA Verschlüsselten Block.
     */
    QByteArray encryptAesData(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.
     */
    bool isCsprngSeeded();

    /**
     * @brief Holt Zufallsblöcke aus dem Csprng.
     * @param count Die Anzahl der Zufallsbytes die geholt werden sollen.
     * @return Ein QByteArray mit den Zufallsblöcken.
     */
    QByteArray getCsprngBytes(int count);

    /**
     * @brief Überprüft, ob der Schlüssel vom Typ RSA ist.
     * @param key Der Schlüssel, der überprüft wird.
     * @return Gibt wahr zurück, falls Key vom Typ RSA ist, ansonsten flasch.
     */
    bool isKeyRsa(EVP_PKEY *key);

    /**
     * @brief Wirft eine CryptException mit dem OpenSSL Fehler.
     */
    void throwOpenSslException();

    /**
     * @brief Wirft eine CryptException, falls der Schlüssel nicht RSA ist.
     * @param key Der Pointer, der auf NULL gesetzt wird, nachdem der Schlüssel abgräumt wurde.
     */
    void throwExceptionIfEvpKeyIsNotRsa(EVP_PKEY **key);

    /**
     * @brief Wirft eine Exception, falls der Zufallszahlengenerator nicht initialisiert wurde.
     */
    void throwExceptionIfCsprngIsNotSeeded();

    /**
     * @brief throwExceptionIfUserKeyIsNull
     * Wift eine Exception, falls kein Nutzerschlüssel vorhanden ist.
     */
    void throwExceptionIfUserKeyIsNull();

    /**
     * @brief Räumt den Schlüssel hinter key ab.
     * @param key Der Pointer, der auf NULL gesetzt wird.
     */
    void freeEvpKey(EVP_PKEY **key);

    /**
     * @brief Räumt den Kontext hinter ctx ab.
     * @param ctx Der Pointer, der auf NULL gesetzt wird.
     */
    void freeCipherCtx(EVP_CIPHER_CTX **ctx);

    /**
     * @brief Räumt den Kontext hinter ctx ab.
     * @param ctx Der Pointer, der auf NULL gesetzt wird.
     */
    void freePkeyCtx(EVP_PKEY_CTX **ctx);
};

#endif // HYBRIDCRYPT_H