From 4ce12493f6e32c6c8fb8396c843b05e7b327facc Mon Sep 17 00:00:00 2001
From: Matteo Brichese <mbrichese@ics.com>
Date: Tue, 3 Apr 2018 17:42:03 -0700
Subject: [PATCH 1/2] first try on OFB - not tested

---
 qaesencryption.cpp | 14 +++++++++++++-
 qaesencryption.h   |  7 ++++---
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/qaesencryption.cpp b/qaesencryption.cpp
index 4001dfe..a21e087 100644
--- a/qaesencryption.cpp
+++ b/qaesencryption.cpp
@@ -398,13 +398,16 @@ QByteArray QAESEncryption::encode(const QByteArray &rawText, const QByteArray &k
     QByteArray expandedKey = expandKey(key);
     QByteArray alignedText(rawText);
     QByteArray ivTemp(iv);
+    QByteArray ofbTemp;
 
     //Fill array with padding
     alignedText.append(getPadding(rawText.size(), m_blocklen));
 
     //Preparation for CFB
-    if (m_mode == CFB)
+    if (m_mode == CFB || m_mode == OFB)
         ret.append(byteXor(alignedText.mid(0, m_blocklen), cipher(expandedKey, iv)));
+    if (m_mode == OFB)
+        ofbTemp.append(cipher(expandedKey, iv));
 
     //Looping thru all blocks
     for(int i=0; i < alignedText.size(); i+= m_blocklen){
@@ -423,6 +426,15 @@ QByteArray QAESEncryption::encode(const QByteArray &rawText, const QByteArray &k
                 ret.append(byteXor(alignedText.mid(i+m_blocklen, m_blocklen),
                                    cipher(expandedKey, ret.mid(i, m_blocklen))));
             break;
+        case OFB:
+            if (i+m_blocklen < alignedText.size())
+            {
+                ret.append(byteXor(alignedText.mid(i+m_blocklen, m_blocklen),
+                                   cipher(expandedKey, ofbTemp.mid(i-m_blocklen, m_blocklen))));
+                ofbTemp.append(cipher(expandedKey, ofbTemp.mid(i-m_blocklen, m_blocklen)));
+            }
+
+            break;
         default:
             //do nothing
             break;
diff --git a/qaesencryption.h b/qaesencryption.h
index 9717812..5c34557 100644
--- a/qaesencryption.h
+++ b/qaesencryption.h
@@ -17,7 +17,8 @@ public:
     enum Mode {
         ECB,
         CBC,
-        CFB
+        CFB,
+        OFB
     };
 
     enum Padding {
@@ -132,9 +133,9 @@ private:
 
     // The round constant word array, Rcon[i], contains the values given by
     // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
-    //Only the first 14 elements are needed
+    // Only the first 14 elements are needed
     const quint8 Rcon[256] = {
-        0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, /*0x4d, 0x9a,
+        0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab/*, 0x4d, 0x9a,
         0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
         0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
         0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,

From 278565d6610136e277414c32dc705cc5a89f1583 Mon Sep 17 00:00:00 2001
From: Matteo Brichese <mbrichese@ics.com>
Date: Thu, 5 Apr 2018 16:07:22 -0700
Subject: [PATCH 2/2] adding OFB with basic test

---
 qaesencryption.cpp    | 126 ++++++++++++++++++++++--------------------
 unit_test/aestest.cpp |  19 ++++++-
 unit_test/aestest.h   |   2 +
 3 files changed, 87 insertions(+), 60 deletions(-)

diff --git a/qaesencryption.cpp b/qaesencryption.cpp
index a21e087..ac240fc 100644
--- a/qaesencryption.cpp
+++ b/qaesencryption.cpp
@@ -325,7 +325,8 @@ QByteArray QAESEncryption::byteXor(const QByteArray &a, const QByteArray &b)
   QByteArray::const_iterator it_b = b.begin();
   QByteArray ret;
 
-  for(int i = 0; i < m_blocklen; i++)
+  //for(int i = 0; i < m_blocklen; i++)
+  for(int i = 0; i < std::min(a.size(), b.size()); i++)
       ret.insert(i,it_a[i] ^ it_b[i]);
 
   return ret;
@@ -397,48 +398,44 @@ QByteArray QAESEncryption::encode(const QByteArray &rawText, const QByteArray &k
     QByteArray ret;
     QByteArray expandedKey = expandKey(key);
     QByteArray alignedText(rawText);
-    QByteArray ivTemp(iv);
-    QByteArray ofbTemp;
 
     //Fill array with padding
     alignedText.append(getPadding(rawText.size(), m_blocklen));
 
-    //Preparation for CFB
-    if (m_mode == CFB || m_mode == OFB)
-        ret.append(byteXor(alignedText.mid(0, m_blocklen), cipher(expandedKey, iv)));
-    if (m_mode == OFB)
-        ofbTemp.append(cipher(expandedKey, iv));
-
-    //Looping thru all blocks
-    for(int i=0; i < alignedText.size(); i+= m_blocklen){
-        switch(m_mode)
-        {
-        case ECB:
+    switch(m_mode)
+    {
+    case ECB:
+        for(int i=0; i < alignedText.size(); i+= m_blocklen)
             ret.append(cipher(expandedKey, alignedText.mid(i, m_blocklen)));
-            break;
-        case CBC:
-            alignedText.replace(i, m_blocklen, byteXor(alignedText.mid(i, m_blocklen),ivTemp));
-            ret.append(cipher(expandedKey, alignedText.mid(i, m_blocklen)));
-            ivTemp = ret.mid(i, m_blocklen);
-            break;
-        case CFB:
-            if (i+m_blocklen < alignedText.size())
-                ret.append(byteXor(alignedText.mid(i+m_blocklen, m_blocklen),
-                                   cipher(expandedKey, ret.mid(i, m_blocklen))));
-            break;
-        case OFB:
-            if (i+m_blocklen < alignedText.size())
-            {
-                ret.append(byteXor(alignedText.mid(i+m_blocklen, m_blocklen),
-                                   cipher(expandedKey, ofbTemp.mid(i-m_blocklen, m_blocklen))));
-                ofbTemp.append(cipher(expandedKey, ofbTemp.mid(i-m_blocklen, m_blocklen)));
+        break;
+    case CBC: {
+            QByteArray ivTemp(iv);
+            for(int i=0; i < alignedText.size(); i+= m_blocklen) {
+                alignedText.replace(i, m_blocklen, byteXor(alignedText.mid(i, m_blocklen),ivTemp));
+                ret.append(cipher(expandedKey, alignedText.mid(i, m_blocklen)));
+                ivTemp = ret.mid(i, m_blocklen);
             }
-
-            break;
-        default:
-            //do nothing
-            break;
         }
+        break;
+    case CFB: {
+            ret.append(byteXor(alignedText.left(m_blocklen), cipher(expandedKey, iv)));
+            for(int i=0; i < alignedText.size(); i+= m_blocklen) {
+                if (i+m_blocklen < alignedText.size())
+                    ret.append(byteXor(alignedText.mid(i+m_blocklen, m_blocklen),
+                                       cipher(expandedKey, ret.mid(i, m_blocklen))));
+            }
+        }
+        break;
+    case OFB: {
+            QByteArray ofbTemp;
+            ofbTemp.append(cipher(expandedKey, iv));
+            for (int i=m_blocklen; i < alignedText.size(); i += m_blocklen){
+                ofbTemp.append(cipher(expandedKey, ofbTemp.right(m_blocklen)));
+            }
+            ret.append(byteXor(alignedText, ofbTemp));
+        }
+        break;
+    default: break;
     }
     return ret;
 }
@@ -450,33 +447,44 @@ QByteArray QAESEncryption::decode(const QByteArray &rawText, const QByteArray &k
 
     QByteArray ret;
     QByteArray expandedKey = expandKey(key);
-    QByteArray ivTemp(iv);
 
-    //Preparation for CFB
-    if (m_mode == CFB)
-        ret.append(byteXor(rawText.mid(0, m_blocklen), cipher(expandedKey, iv)));
-
-    for(int i=0; i < rawText.size(); i+= m_blocklen){
-        switch(m_mode)
-        {
-        case ECB:
+    switch(m_mode)
+    {
+    case ECB:
+        for(int i=0; i < rawText.size(); i+= m_blocklen)
             ret.append(invCipher(expandedKey, rawText.mid(i, m_blocklen)));
-            break;
-        case CBC:
-            ret.append(invCipher(expandedKey, rawText.mid(i, m_blocklen)));
-            ret.replace(i, m_blocklen, byteXor(ret.mid(i, m_blocklen),ivTemp));
-            ivTemp = rawText.mid(i, m_blocklen);
-            break;
-        case CFB:
-            if (i+m_blocklen < rawText.size()){
-                ret.append(byteXor(rawText.mid(i+m_blocklen, m_blocklen),
-                                   cipher(expandedKey, rawText.mid(i, m_blocklen))));
+        break;
+    case CBC: {
+            QByteArray ivTemp(iv);
+            for(int i=0; i < rawText.size(); i+= m_blocklen){
+                ret.append(invCipher(expandedKey, rawText.mid(i, m_blocklen)));
+                ret.replace(i, m_blocklen, byteXor(ret.mid(i, m_blocklen),ivTemp));
+                ivTemp = rawText.mid(i, m_blocklen);
             }
-            break;
-        default:
-            //do nothing
-            break;
         }
+        break;
+    case CFB: {
+            ret.append(byteXor(rawText.mid(0, m_blocklen), cipher(expandedKey, iv)));
+            for(int i=0; i < rawText.size(); i+= m_blocklen){
+                if (i+m_blocklen < rawText.size()) {
+                    ret.append(byteXor(rawText.mid(i+m_blocklen, m_blocklen),
+                                       cipher(expandedKey, rawText.mid(i, m_blocklen))));
+                }
+            }
+        }
+        break;
+    case OFB: {
+        QByteArray ofbTemp;
+        ofbTemp.append(cipher(expandedKey, iv));
+        for (int i=m_blocklen; i < rawText.size(); i += m_blocklen){
+            ofbTemp.append(cipher(expandedKey, ofbTemp.right(m_blocklen)));
+        }
+        ret.append(byteXor(rawText, ofbTemp));
+    }
+        break;
+    default:
+        //do nothing
+        break;
     }
     return ret;
 }
diff --git a/unit_test/aestest.cpp b/unit_test/aestest.cpp
index 0119b1a..25ab728 100644
--- a/unit_test/aestest.cpp
+++ b/unit_test/aestest.cpp
@@ -1,5 +1,6 @@
 #include "aestest.h"
 
+#include <QDebug>
 #include <QByteArray>
 #include <QCryptographicHash>
 #include <QFile>
@@ -139,7 +140,7 @@ void AesTest::CBC128Decrypt()
 
 void AesTest::CFB256String()
 {
-    QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::CFB);
+    QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::CFB, QAESEncryption::PKCS7);
 
     QString inputStr("The Advanced Encryption Standard (AES), also known by its original name Rijndael "
                         "is a specification for the encryption of electronic data established by the U.S. "
@@ -171,3 +172,19 @@ void AesTest::CFB256LongText()
     QByteArray decodedText = encryption.removePadding(encryption.decode(encodeText, hashKey, iv));
     QCOMPARE(decodedText, input);
 }
+
+void AesTest::OFB256String()
+{
+    QAESEncryption encryption(QAESEncryption::AES_128, QAESEncryption::OFB, QAESEncryption::PKCS7);
+
+    QString inputStr("The Advanced Encryption Standard (AES), also known by its original name Rijndael "
+                        "is a specification for the encryption of electronic data established by the U.S. "
+                        "National Institute of Standards and Technology (NIST) in 2001");
+    QString key("123456789123");
+
+    QByteArray hashKey = QCryptographicHash::hash(key.toLocal8Bit(), QCryptographicHash::Sha256);
+    QByteArray encodeText = encryption.encode(inputStr.toLocal8Bit(), hashKey, iv);
+
+    QByteArray decodedText = encryption.removePadding(encryption.decode(encodeText, hashKey, iv));
+    QCOMPARE(inputStr, decodedText);
+}
diff --git a/unit_test/aestest.h b/unit_test/aestest.h
index bd6c03e..eeaa5fc 100644
--- a/unit_test/aestest.h
+++ b/unit_test/aestest.h
@@ -29,6 +29,8 @@ private slots:
 
     void CFB256LongText();
 
+    void OFB256String();
+
     void cleanupTestCase(){}
 
 private: