|
1 | 1 | #include "qtinyaesencryptor_p.h" |
2 | 2 |
|
3 | 3 | #include <QtCore/QJsonDocument> |
| 4 | +#include <QtCore/qcryptographichash.h> |
4 | 5 |
|
5 | 6 | #include <qtinyaes.h> |
6 | 7 | using namespace QtDataSync; |
7 | 8 |
|
8 | 9 | QTinyAesEncryptor::QTinyAesEncryptor(QObject *parent) : |
9 | 10 | Encryptor(parent), |
10 | | - key() |
| 11 | + _defaults(nullptr), |
| 12 | + _key() |
11 | 13 | {} |
12 | 14 |
|
13 | 15 | void QTinyAesEncryptor::initialize(Defaults *defaults) |
14 | 16 | { |
15 | | - key = defaults->property("encryptKey").toByteArray(); |
16 | | - if(key.isNull()) { |
17 | | - for(auto i = 0; i < QTinyAes::KEYSIZES.first(); i++) |
18 | | - key += (char)qrand(); |
| 17 | + _defaults = defaults; |
| 18 | + _key = _defaults->settings()->value(QStringLiteral("encryption/key")).toByteArray(); |
| 19 | + if(_key.isNull()) { |
| 20 | + for(quint32 i = 0; i < QTinyAes::KEYSIZE; i++) |
| 21 | + _key += (char)qrand(); |
| 22 | + _defaults->settings()->setValue(QStringLiteral("encryption/key"), _key); |
19 | 23 | } |
20 | 24 | } |
21 | 25 |
|
| 26 | +QByteArray QTinyAesEncryptor::key() const |
| 27 | +{ |
| 28 | + return _key; |
| 29 | +} |
| 30 | + |
| 31 | +void QTinyAesEncryptor::setKey(const QByteArray &key) |
| 32 | +{ |
| 33 | + if((quint32)_key.size() != QTinyAes::KEYSIZE) |
| 34 | + throw InvalidKeyException(); |
| 35 | + _key = key; |
| 36 | + _defaults->settings()->setValue(QStringLiteral("encryption/key"), _key); |
| 37 | +} |
| 38 | + |
22 | 39 | QJsonValue QTinyAesEncryptor::encrypt(const ObjectKey &key, const QJsonObject &object, const QByteArray &keyProperty) const |
23 | 40 | { |
| 41 | + QByteArray salt; |
| 42 | + for(quint32 i = 0; i < 28; i++)//224 bits |
| 43 | + salt += (char)qrand(); |
| 44 | + auto iv = QCryptographicHash::hash(salt + key.first + key.second.toUtf8() + keyProperty, QCryptographicHash::Sha3_224); |
| 45 | + iv.resize(QTinyAes::BLOCKSIZE); |
| 46 | + |
24 | 47 | auto data = QJsonDocument(object).toBinaryData(); |
25 | | - auto iv = ""; |
| 48 | + auto cipher = QTinyAes::cbcEncrypt( _key, iv, data); |
| 49 | + |
| 50 | + QJsonObject result; |
| 51 | + result[QStringLiteral("salt")] = QString::fromUtf8(salt.toBase64()); |
| 52 | + result[QStringLiteral("data")] = QString::fromUtf8(cipher.toBase64()); |
| 53 | + return result; |
26 | 54 | } |
27 | 55 |
|
28 | 56 | QJsonObject QTinyAesEncryptor::decrypt(const ObjectKey &key, const QJsonValue &data, const QByteArray &keyProperty) const |
29 | 57 | { |
| 58 | + auto obj = data.toObject(); |
| 59 | + auto salt = QByteArray::fromBase64(obj[QStringLiteral("salt")].toString().toUtf8()); |
| 60 | + if(salt.size() != 28)//224 bits |
| 61 | + throw DecryptionFailedException(); |
| 62 | + auto iv = QCryptographicHash::hash(salt + key.first + key.second.toUtf8() + keyProperty, QCryptographicHash::Sha3_224); |
| 63 | + iv.resize(QTinyAes::BLOCKSIZE); |
30 | 64 |
|
| 65 | + auto cipher = QByteArray::fromBase64(obj[QStringLiteral("data")].toString().toUtf8()); |
| 66 | + if(cipher.size() % QTinyAes::KEYSIZE != 0) |
| 67 | + throw DecryptionFailedException(); |
| 68 | + |
| 69 | + auto plain = QTinyAes::cbcDecrypt(_key, iv, cipher); |
| 70 | + auto json = QJsonDocument::fromBinaryData(plain); |
| 71 | + if(json.isObject()) |
| 72 | + return json.object(); |
| 73 | + else |
| 74 | + throw DecryptionFailedException(); |
| 75 | +} |
| 76 | + |
| 77 | + |
| 78 | + |
| 79 | +const char *InvalidKeyException::what() const noexcept |
| 80 | +{ |
| 81 | + return "The given key does not have the valid length of 128 bit!"; |
| 82 | +} |
| 83 | + |
| 84 | +void InvalidKeyException::raise() const |
| 85 | +{ |
| 86 | + throw *this; |
| 87 | +} |
| 88 | + |
| 89 | +QException *InvalidKeyException::clone() const |
| 90 | +{ |
| 91 | + return new InvalidKeyException(); |
| 92 | +} |
| 93 | + |
| 94 | +const char *DecryptionFailedException::what() const noexcept |
| 95 | +{ |
| 96 | + return "Failed to decrypt data returned from server. Maybe it's not encrypted?"; |
| 97 | +} |
| 98 | + |
| 99 | +void DecryptionFailedException::raise() const |
| 100 | +{ |
| 101 | + throw *this; |
| 102 | +} |
| 103 | + |
| 104 | +QException *DecryptionFailedException::clone() const |
| 105 | +{ |
| 106 | + return new DecryptionFailedException(); |
31 | 107 | } |
0 commit comments