diff options
| author | Markus Mittendrein <git@maxmitti.tk> | 2014-10-06 15:03:54 +0200 |
|---|---|---|
| committer | Markus Mittendrein <git@maxmitti.tk> | 2014-10-06 15:03:54 +0200 |
| commit | 529f38bd8878b6b1bea2b5457031ce936aab8d80 (patch) | |
| tree | 1193caefcad12f6a36f818048e4547e60add4398 /libcommuni/src/3rdparty/qblowfish/qblowfish.cpp | |
| parent | 3b58b5536935adff242928ed9f30e1c0262fbd7c (diff) | |
| download | manager-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.cpp | 277 |
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])); + } + + } +} |
