QtLingo 1
QtLingo is an Application to make Qt Computer Translations easier
SimpleCrypt.cpp
Go to the documentation of this file.
1/*
2 * https://wiki.qt.io/Simple_encryption_with_SimpleCrypt#Versions
3 * Copyright (c) 2011, Andre Somers
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of the Rathenau Instituut, Andre Somers nor the
14 names of its contributors may be used to endorse or promote products
15 derived from this software without specific prior written permission.
16
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL ANDRE SOMERS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR #######; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28#include "SimpleCrypt.h"
29
30
34SimpleCrypt::SimpleCrypt(): myKey(0), myCompressionMode(CompressionAuto), myProtectionMode(ProtectionChecksum), myLastError(ErrorNoError)
35{
36 QRandomGenerator generator(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF));
37 generator.generate();
38 // qsrand(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF));
39}
40
44SimpleCrypt::SimpleCrypt(quint64 key): myKey(key), myCompressionMode(CompressionAuto), myProtectionMode(ProtectionChecksum), myLastError(ErrorNoError)
45{
46 QRandomGenerator generator(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF));
47 generator.generate();
48 // qsrand(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF));
49 splitKey();
50}
51
55void SimpleCrypt::setDebugMessage(bool thisState)
56{
57 isDebugMessage = thisState;
58}
59
64{
65 return isDebugMessage;
66}
67
71void SimpleCrypt::setKey(quint64 key)
72{
73 myKey = key;
74 splitKey();
75}
76
80void SimpleCrypt::splitKey()
81{
82 myKeyParts.clear();
83 myKeyParts.resize(8);
84 for (int i = 0;i < 8; i++)
85 {
86 quint64 part = myKey;
87 for (int j = i; j > 0; j--) { part = part >> 8; }
88 part = part & 0xff;
89 myKeyParts[i] = static_cast<char>(part);
90 }
91}
92
96QByteArray SimpleCrypt::encryptToByteArray(const QString &plaintext)
97{
98 QByteArray plaintextArray = plaintext.toUtf8();
99 return encryptToByteArray(plaintextArray);
100}
101
105QByteArray SimpleCrypt::encryptToByteArray(const QByteArray &plaintext)
106{
107 if (myKeyParts.isEmpty())
108 {
109 qWarning() << "No key set.";
110 myLastError = ErrorNoKeySet;
111 return QByteArray();
112 }
113
114 QByteArray ba = plaintext;
115
116 CryptoFlags flags = CryptoFlagNone;
117 if (myCompressionMode == CompressionAlways)
118 {
119 ba = qCompress(ba, 9); // maximum compression
120 flags |= CryptoFlagCompression;
121 }
122 else if (myCompressionMode == CompressionAuto)
123 {
124 QByteArray compressed = qCompress(ba, 9);
125 if (compressed.count() < ba.count())
126 {
127 ba = compressed;
128 flags |= CryptoFlagCompression;
129 }
130 }
131
132 QByteArray integrityProtection;
133 if (myProtectionMode == ProtectionChecksum)
134 {
135 flags |= CryptoFlagChecksum;
136 QDataStream s(&integrityProtection, QIODevice::WriteOnly);
137 s << qChecksum(ba.constData(), ba.length());
138 }
139 else if (myProtectionMode == ProtectionHash)
140 {
141 flags |= CryptoFlagHash;
142 QCryptographicHash hash(QCryptographicHash::Sha1);
143 hash.addData(ba);
144
145 integrityProtection += hash.result();
146 }
147 // prepend a random char to the string
148 QRandomGenerator generator(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF));
149 char randomChar = char(generator.generate() & 0xFF);
150 // char randomChar = char(qrand() & 0xFF);
151
152 ba = randomChar + integrityProtection + ba;
153
154 int pos(0);
155 char lastChar(0);
156
157 int cnt = ba.count();
158
159 while (pos < cnt)
160 {
161 ba[pos] = ba.at(pos) ^ myKeyParts.at(pos % 8) ^ lastChar;
162 lastChar = ba.at(pos);
163 ++pos;
164 }
165
166 QByteArray resultArray;
167 resultArray.append(char(0x03)); // version for future updates to algorithm
168 resultArray.append(char(flags)); // encryption flags
169 resultArray.append(ba);
170
171 myLastError = ErrorNoError;
172 return resultArray;
173}
174
178QString SimpleCrypt::encryptToString(const QString &plaintext)
179{
180 QByteArray plaintextArray = plaintext.toUtf8();
181 QByteArray cypher = encryptToByteArray(plaintextArray);
182 QString cypherString = QString::fromLatin1(cypher.toBase64());
183 return cypherString;
184}
185
189QString SimpleCrypt::encryptToString(const QByteArray &plaintext)
190{
191 QByteArray cypher = encryptToByteArray(plaintext);
192 QString cypherString = QString::fromLatin1(cypher.toBase64());
193 return cypherString;
194}
195
199QString SimpleCrypt::decryptToString(const QString &cyphertext)
200{
201 QByteArray cyphertextArray = QByteArray::fromBase64(cyphertext.toLatin1());
202 QByteArray plaintextArray = decryptToByteArray(cyphertextArray);
203 QString plaintext = QString::fromUtf8(plaintextArray, plaintextArray.size());
204
205 return plaintext;
206}
207
211QString SimpleCrypt::decryptToString(const QByteArray &cypher)
212{
213 QByteArray ba = decryptToByteArray(cypher);
214 QString plaintext = QString::fromUtf8(ba, ba.size());
215
216 return plaintext;
217}
218
222QByteArray SimpleCrypt::decryptToByteArray(const QString &cyphertext)
223{
224 QByteArray cyphertextArray = QByteArray::fromBase64(cyphertext.toLatin1());
225 QByteArray ba = decryptToByteArray(cyphertextArray);
226
227 return ba;
228}
229
233QByteArray SimpleCrypt::decryptToByteArray(QByteArray cypher)
234{
235 if (myKeyParts.isEmpty())
236 {
237 qWarning() << "No key set.";
238 myLastError = ErrorNoKeySet;
239 return QByteArray();
240 }
241
242 QByteArray ba = cypher;
243
244 if( cypher.count() < 3 )
245 { return QByteArray(); }
246
247 char version = ba.at(0);
248
249 if (version != 3)
250 { // we only work with version 3
251 myLastError = ErrorUnknownVersion;
252 qWarning() << "Invalid version or not a cyphertext.";
253 return QByteArray();
254 }
255
256 CryptoFlags flags = CryptoFlags(ba.at(1));
257
258 ba = ba.mid(2);
259 int pos(0);
260 int cnt(ba.count());
261 char lastChar = 0;
262
263 while (pos < cnt)
264 {
265 char currentChar = ba[pos];
266 ba[pos] = ba.at(pos) ^ lastChar ^ myKeyParts.at(pos % 8);
267 lastChar = currentChar;
268 ++pos;
269 }
270
271 ba = ba.mid(1); // chop off the random number at the start
272
273 bool integrityOk(true);
274 if (flags.testFlag(CryptoFlagChecksum))
275 {
276 if (ba.length() < 2)
277 {
278 myLastError = ErrorIntegrityFailed;
279 return QByteArray();
280 }
281 quint16 storedChecksum;
282 {
283 QDataStream s(&ba, QIODevice::ReadOnly);
284 s >> storedChecksum;
285 }
286 ba = ba.mid(2);
287 quint16 checksum = qChecksum(ba.constData(), ba.length());
288 integrityOk = (checksum == storedChecksum);
289 }
290 else if (flags.testFlag(CryptoFlagHash))
291 {
292 if (ba.length() < 20)
293 {
294 myLastError = ErrorIntegrityFailed;
295 return QByteArray();
296 }
297 QByteArray storedHash = ba.left(20);
298 ba = ba.mid(20);
299 QCryptographicHash hash(QCryptographicHash::Sha1);
300 hash.addData(ba);
301 integrityOk = (hash.result() == storedHash);
302 }
303
304 if (!integrityOk)
305 {
306 myLastError = ErrorIntegrityFailed;
307 return QByteArray();
308 }
309
310 if (flags.testFlag(CryptoFlagCompression))
311 { ba = qUncompress(ba); }
312
313 myLastError = ErrorNoError;
314 return ba;
315}
316
320void SimpleCrypt::setMessage(const QString &thisMessage)
321{
322 if (isDebugMessage)
323 {
324 qDebug() << thisMessage;
325 //std::cout << thisMessage.toStdString() << std::endl;
326 }
327}
328
@ CompressionAlways
Definition: SimpleCrypt.h:80
bool getDebugMessage()
get Debug Message
Definition: SimpleCrypt.cpp:63
@ ProtectionChecksum
Definition: SimpleCrypt.h:92
void setDebugMessage(bool thisState)
set Debug Message
Definition: SimpleCrypt.cpp:55
void setMessage(const QString &thisMessage)
set Message
QString decryptToString(const QString &cyphertext)
decrypt To String QString. decryptToString
void setKey(quint64 key)
set Key. setKey
Definition: SimpleCrypt.cpp:71
@ ErrorUnknownVersion
Definition: SimpleCrypt.h:100
@ ErrorIntegrityFailed
Definition: SimpleCrypt.h:101
@ CryptoFlagChecksum
CryptoFlagChecksum
Definition: SimpleCrypt.h:208
@ CryptoFlagNone
CryptoFlagNone
Definition: SimpleCrypt.h:206
@ CryptoFlagCompression
CryptoFlagCompression
Definition: SimpleCrypt.h:207
@ CryptoFlagHash
CryptoFlagHash
Definition: SimpleCrypt.h:209
SimpleCrypt()
Constructor. SimpleCrypt.
Definition: SimpleCrypt.cpp:34
QByteArray decryptToByteArray(const QString &cyphertext)
decrypt To Byte Array QString. decryptToByteArray
QByteArray encryptToByteArray(const QString &plaintext)
encrypt To Byte Array QString. encryptToByteArray
Definition: SimpleCrypt.cpp:96
QString encryptToString(const QString &plaintext)
encrypt To String QString. encryptToString