summaryrefslogtreecommitdiffstats
path: root/libcommuni/src/3rdparty/qblowfish/qblowfish.cpp
diff options
context:
space:
mode:
authorMarkus Mittendrein <git@maxmitti.tk>2014-10-06 15:03:54 +0200
committerMarkus Mittendrein <git@maxmitti.tk>2014-10-06 15:03:54 +0200
commit529f38bd8878b6b1bea2b5457031ce936aab8d80 (patch)
tree1193caefcad12f6a36f818048e4547e60add4398 /libcommuni/src/3rdparty/qblowfish/qblowfish.cpp
parent3b58b5536935adff242928ed9f30e1c0262fbd7c (diff)
downloadmanager-529f38bd8878b6b1bea2b5457031ce936aab8d80.tar.gz
manager-529f38bd8878b6b1bea2b5457031ce936aab8d80.zip
addedd communi
Diffstat (limited to 'libcommuni/src/3rdparty/qblowfish/qblowfish.cpp')
-rw-r--r--libcommuni/src/3rdparty/qblowfish/qblowfish.cpp277
1 files changed, 277 insertions, 0 deletions
diff --git a/libcommuni/src/3rdparty/qblowfish/qblowfish.cpp b/libcommuni/src/3rdparty/qblowfish/qblowfish.cpp
new file mode 100644
index 0000000..605ff24
--- /dev/null
+++ b/libcommuni/src/3rdparty/qblowfish/qblowfish.cpp
@@ -0,0 +1,277 @@
+/*
+ This file is part of QBlowfish and is licensed under the MIT License
+
+ Copyright (C) 2012 Roopesh Chander <roop@forwardbias.in>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject
+ to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#include "qblowfish.h"
+#include "qblowfish_p.h"
+#include <QtEndian>
+#include <QDebug>
+
+QBlowfish::QBlowfish(const QByteArray &key)
+ : m_key(key)
+ , m_initialized(false)
+ , m_paddingEnabled(false)
+{
+}
+
+void QBlowfish::setPaddingEnabled(bool enabled)
+{
+ m_paddingEnabled = enabled;
+}
+
+bool QBlowfish::isPaddingEnabled() const
+{
+ return m_paddingEnabled;
+}
+
+QByteArray QBlowfish::encrypted(const QByteArray &_clearText)
+{
+ QByteArray clearText(_clearText);
+ if (clearText.isEmpty()) {
+ return QByteArray();
+ }
+
+ if (isPaddingEnabled()) {
+ // Add padding as per PKCS5
+ // Ref: RFC 5652 http://tools.ietf.org/html/rfc5652#section-6.3
+ quint8 paddingLength = 8 - (clearText.size() % 8);
+ QByteArray paddingBa(paddingLength, static_cast<char>(paddingLength));
+ clearText.append(paddingBa);
+ } else {
+ if (clearText.size() % 8 != 0) {
+ qWarning("Cannot encrypt. Clear-text length is not a multiple of 8 and padding is not enabled.");
+ return QByteArray();
+ }
+ }
+
+ Q_ASSERT(clearText.size() % 8 == 0);
+ if ((clearText.size() % 8 == 0) && init()) {
+
+ QByteArray copyBa(clearText.constData(), clearText.size());
+ for (int i = 0; i < clearText.size(); i += 8) {
+ coreEncrypt(copyBa.data() + i);
+ }
+ return copyBa;
+
+ }
+ return QByteArray();
+}
+
+QByteArray QBlowfish::decrypted(const QByteArray &cipherText)
+{
+ if (cipherText.isEmpty()) {
+ return QByteArray();
+ }
+
+ Q_ASSERT(cipherText.size() % 8 == 0);
+ if ((cipherText.size() % 8 == 0) && init()) {
+
+ QByteArray copyBa(cipherText.constData(), cipherText.size());
+ for (int i = 0; i < cipherText.size(); i += 8) {
+ coreDecrypt(copyBa.data() + i);
+ }
+
+ if (isPaddingEnabled()) {
+ // Remove padding as per PKCS5
+ quint8 paddingLength = static_cast<quint8>(copyBa.right(1).at(0));
+ QByteArray paddingBa(paddingLength, static_cast<char>(paddingLength));
+ if (copyBa.right(paddingLength) == paddingBa) {
+ return copyBa.left(copyBa.length() - paddingLength);
+ }
+ return QByteArray();
+ }
+ return copyBa;
+ }
+ return QByteArray();
+}
+
+/*
+ Core encryption code follows. This is an implementation of the Blowfish algorithm as described at:
+ http://www.schneier.com/paper-blowfish-fse.html
+*/
+
+bool QBlowfish::init()
+{
+ if (m_initialized) {
+ return true;
+ }
+
+ if (m_key.isEmpty()) {
+ qWarning("Cannot init. Key is empty.");
+ return false;
+ }
+
+ m_sbox1 = QByteArray::fromHex(QByteArray::fromRawData(sbox0, SBOX_SIZE_BYTES * 2));
+ m_sbox2 = QByteArray::fromHex(QByteArray::fromRawData(sbox1, SBOX_SIZE_BYTES * 2));
+ m_sbox3 = QByteArray::fromHex(QByteArray::fromRawData(sbox2, SBOX_SIZE_BYTES * 2));
+ m_sbox4 = QByteArray::fromHex(QByteArray::fromRawData(sbox3, SBOX_SIZE_BYTES * 2));
+ m_parray = QByteArray::fromHex(QByteArray::fromRawData(parray, PARRAY_SIZE_BYTES * 2));
+
+ const QByteArray &key = m_key;
+ int keyLength = key.length();
+ for (int i = 0; i < PARRAY_SIZE_BYTES; i++) {
+ m_parray[i] = static_cast<char>(static_cast<quint8>(m_parray[i]) ^ static_cast<quint8>(key[i % keyLength]));
+ }
+
+ char seed[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ // Update p-array
+ for (int i = 0; i < (PARRAY_SIZE_BYTES / 4); i += 2) {
+ coreEncrypt(seed);
+ for (int j = 0; j < 8; j++) {
+ // P1 = xL; P2 = xR
+ m_parray[i * 4 + j] = seed[j];
+ }
+ }
+
+ // Update s-boxes
+ for (int sboxIndex = 1; sboxIndex <= 4; sboxIndex++) {
+ QByteArray *sbox = 0;
+ switch (sboxIndex) {
+ case 1: sbox = &m_sbox1; break;
+ case 2: sbox = &m_sbox2; break;
+ case 3: sbox = &m_sbox3; break;
+ case 4: sbox = &m_sbox4; break;
+ default: Q_ASSERT(false);
+ }
+ Q_ASSERT(sbox != 0);
+
+ for (int i = 0; i < (SBOX_SIZE_BYTES / 4); i += 2) {
+ coreEncrypt(seed);
+ for (int j = 0; j < 8; j++) {
+ // S1,1 = xL; S1,2 = xR
+ sbox->operator[](i * 4 + j) = seed[j];
+ }
+ }
+ }
+
+ m_initialized = true;
+ return true;
+}
+
+void QBlowfish::coreEncrypt(char *x) // encrypts 8 bytes pointed to by x, result is written to the same location
+{
+ // Divide x into two 32-bit halves: xL, xR
+ char *xL = x;
+ char *xR = x + 4;
+ uchar f_xL_bytes[4] = { 0, 0, 0, 0 };
+
+ for (int i = 0; i < 16; i++) {
+
+ // xL = xL XOR Pi
+ for (int j = 0; j < 4; j++) {
+ // quint8 old_xL = xL[j];
+ xL[j] = static_cast<char>(static_cast<quint8>(xL[j]) ^ static_cast<quint8>(m_parray[i * 4 + j]));
+ }
+
+ // Divide xL into four eight-bit quarters: a, b, c, and d
+ quint8 a = static_cast<quint8>(xL[0]);
+ quint8 b = static_cast<quint8>(xL[1]);
+ quint8 c = static_cast<quint8>(xL[2]);
+ quint8 d = static_cast<quint8>(xL[3]);
+
+ // F(xL) = ((S1,a + S2,b mod 2**32) XOR S3,c) + S4,d mod 2**32
+ quint32 s1a = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(m_sbox1.constData() + a * 4));
+ quint32 s2b = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(m_sbox2.constData() + b * 4));
+ quint32 s3c = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(m_sbox3.constData() + c * 4));
+ quint32 s4d = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(m_sbox4.constData() + d * 4));
+ quint32 f_xL = ((((s1a + s2b) & 0xffffffff) ^ s3c) + s4d) & 0xffffffff;
+ qToBigEndian<quint32>(f_xL, f_xL_bytes);
+
+ // xR = F(xL) XOR xR
+ for (int j = 0; j < 4; j++) {
+ xR[j] = static_cast<char>(static_cast<quint8>(f_xL_bytes[j]) ^ static_cast<quint8>(xR[j]));
+ }
+
+ // Swap xL and xR, but not in the last iteration
+ if (i != 15) {
+ for (int j = 0; j < 4; j++) {
+ char temp = xL[j];
+ xL[j] = xR[j];
+ xR[j] = temp;
+ }
+ }
+
+ }
+
+ // xR = xR XOR P17
+ // xL = xL XOR P18
+ for (int j = 0; j < 4; j++) {
+ xR[j] = static_cast<char>(static_cast<quint8>(xR[j]) ^ static_cast<quint8>(m_parray[16 * 4 + j]));
+ xL[j] = static_cast<char>(static_cast<quint8>(xL[j]) ^ static_cast<quint8>(m_parray[17 * 4 + j]));
+ }
+}
+
+void QBlowfish::coreDecrypt(char *x) // decrypts 8 bytes pointed to by x, result is written to the same location
+{
+ // Divide x into two 32-bit halves: xL, xR
+ char *xL = x;
+ char *xR = x + 4;
+ uchar f_xL_bytes[4] = { 0, 0, 0, 0 };
+
+ // xL = xL XOR P18
+ // xR = xR XOR P17
+ for (int j = 0; j < 4; j++) {
+ xL[j] = static_cast<char>(static_cast<quint8>(xL[j]) ^ static_cast<quint8>(m_parray[17 * 4 + j]));
+ xR[j] = static_cast<char>(static_cast<quint8>(xR[j]) ^ static_cast<quint8>(m_parray[16 * 4 + j]));
+ }
+
+ for (int i = 15; i >= 0; i--) {
+
+ // Swap xL and xR, but not in the first iteration
+ if (i != 15) {
+ for (int j = 0; j < 4; j++) {
+ char temp = xL[j];
+ xL[j] = xR[j];
+ xR[j] = temp;
+ }
+ }
+
+ // Divide xL into four eight-bit quarters: a, b, c, and d
+ quint8 a = static_cast<quint8>(xL[0]);
+ quint8 b = static_cast<quint8>(xL[1]);
+ quint8 c = static_cast<quint8>(xL[2]);
+ quint8 d = static_cast<quint8>(xL[3]);
+
+ // F(xL) = ((S1,a + S2,b mod 2**32) XOR S3,c) + S4,d mod 2**32
+ quint32 s1a = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(m_sbox1.constData() + a * 4));
+ quint32 s2b = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(m_sbox2.constData() + b * 4));
+ quint32 s3c = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(m_sbox3.constData() + c * 4));
+ quint32 s4d = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(m_sbox4.constData() + d * 4));
+ quint32 f_xL = ((((s1a + s2b) & 0xffffffff) ^ s3c) + s4d) & 0xffffffff;
+ qToBigEndian<quint32>(f_xL, f_xL_bytes);
+
+ // xR = F(xL) XOR xR
+ for (int j = 0; j < 4; j++) {
+ xR[j] = static_cast<char>(static_cast<quint8>(f_xL_bytes[j]) ^ static_cast<quint8>(xR[j]));
+ }
+
+ // xL = xL XOR Pi
+ for (int j = 0; j < 4; j++) {
+ xL[j] = static_cast<char>(static_cast<quint8>(xL[j]) ^ static_cast<quint8>(m_parray[i * 4 + j]));
+ }
+
+ }
+}