3 * \file CryptographicEncryption.h
4 * This file is part of LyX, the document processor.
5 * Licence details can be found in the file COPYING.
9 * Full author contact details are available in file CREDITS.
14 #include "CryptographicEncryption.h"
16 #include <QDataStream>
20 #include <openssl/aes.h>
21 #include <openssl/evp.h>
30 CryptographicEncryption::CryptographicEncryption()
35 int CryptographicEncryption::blockAlign(int blockSize, QByteArray& bytes)
37 int pad = 2 * blockSize - (bytes.size() % blockSize); // pad at least one block
38 bytes.append(QByteArray(pad, (char)pad));
43 int CryptographicEncryption::blockDealign(QByteArray& bytes)
45 int size = bytes.size();
48 char padded = bytes.at(size - 1);
49 bytes.resize(size - padded);
54 bool CryptographicEncryption::aesEnryption(QByteArray const & in, QByteArray* out, QByteArray const & key, bool encrypt)
56 #ifndef LYX_ENCRYPTION
66 int keySize = key.size();
67 if (keySize != 16 && keySize != 24 && keySize != 32) {
71 // AES needs aligned data, but we must not touch already encrypted data
72 QByteArray aligned = in;
74 blockAlign(AES_BLOCK_SIZE, aligned);
76 if ((aligned.size() % AES_BLOCK_SIZE) != 0) {
80 *out = QByteArray(aligned.size(), 0);
83 AES_set_encrypt_key((unsigned char*)key.constData(), keySize * 8, &aeskey);
85 AES_set_decrypt_key((unsigned char*)key.constData(), keySize * 8, &aeskey);
87 // use some arbitrary start values
88 unsigned char iv[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
90 AES_cbc_encrypt((unsigned char*)aligned.constData(),
91 (unsigned char*)out->data(),
92 aligned.size(), &aeskey, iv,
93 (encrypt ? AES_ENCRYPT : AES_DECRYPT));
103 QByteArray CryptographicEncryption::hash(QByteArray const & bytes, QCryptographicHash::Algorithm algorithm)
105 QCryptographicHash hashAlgo(algorithm);
106 hashAlgo.addData(bytes);
107 return hashAlgo.result();
111 bool CryptographicEncryption::encyrpt(QByteArray const & plain, QByteArray* encrypted, QByteArray const & key)
117 QDataStream stream(&bytes, QIODevice::WriteOnly);
118 stream.setVersion(QDataStream::Qt_4_6);
120 stream << hash(plain, QCryptographicHash::Md5);
122 if (!aesEnryption(bytes, encrypted, key, true)) {
131 bool CryptographicEncryption::decyrpt(QByteArray const & encrypted, QByteArray* plain, QByteArray const & key)
137 if (!aesEnryption(encrypted, &bytes, key, false))
140 QByteArray decryptedHash;
141 QDataStream stream(bytes);
142 stream.setVersion(QDataStream::Qt_4_6);
144 stream >> decryptedHash;
146 if (decryptedHash != hash(*plain, QCryptographicHash::Md5)) {
155 QByteArray CryptographicEncryption::bytesToKey(QByteArray const & bytes)
157 #ifndef LYX_ENCRYPTION
161 const char* in = bytes.constData();
162 int iterations = 10000; // here we could adjust our paranoija
163 unsigned char out[64];
164 PKCS5_PBKDF2_HMAC_SHA1(in, bytes.size(), 0, 0, iterations, 32, out);
166 return QByteArray((const char*) out, 32);
171 QByteArray CryptographicEncryption::stringToKey(QString const & str)
173 QByteArray utf8 = str.toUtf8();
174 return bytesToKey(utf8);