4 Replies - 403 Views - Last Post: 26 April 2012 - 04:17 PM Rate Topic: -----

#1 razbarrie  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 26-April 12

Problem With Method Performing Inverse Operations (Encrypt/Decrypt)

Posted 26 April 2012 - 03:23 PM

I am trying to learn more about encryption/decryption based off of how AES works. I have constructed a less-functional clone of it, let's call it RBES (Really Bad Encryption Scheme) for now. I am using this as a guide (Adobe Flash warning).

My problem is that I am not getting the original data after my encryption method is followed by my decryption method. Can anybody tell me where I went wrong?

This code is written 100% by me, so I can most likely clarify anything that is unclear. The code is as follows:

// main.h

// This space intentionally left blank.



// main.cpp

#include <iostream>
#include <fstream>
#include <string>

#include "main.h"
#include "rbes.h"

using namespace std;

/*
#define MAGIC_NUMBER_1 98 // Magic Numbers NO LONGER USED
#define MAGIC_NUMBER_2 47 // Magic Numbers NO LONGER USED
#define MAGIC_NUMBER_3 52 // Magic Numbers NO LONGER USED
#define MAGIC_NUMBER_4 39 // Magic Numbers NO LONGER USED
*/

int main()
{
    /* // Just saving this here.

    ifstream inFile;
    ofstream outFile;

    cin >> fileName;
    inFile.open(fileName.c_str(), ios::in | ios::binary);

    inFile.close();
    outFile.close();

    */

    RBES *encrypter = new RBES();

    // tmp is the starting 128 bit key
    char tmp[4][4] = {{72, 12, 18, 24}, {37, 19, 34, 8}, {220, 187, 119, 224}, {3, 75, 134, 149}};

    // 16 bytes (128 bits) of data to encrypt
    char data[4][4] = {{'S', 'o', 'm', 'e'}, {' ', 't', 'e', 'x'}, {'t', ' ', 's', 't'}, {'u', 'f', 'f', '.'}};

    // encrypter->talk(tmp); // Print the key

    encrypter->setKey(tmp); // Set the key in the instance of RBES

    // cout << "Key set." << endl << endl; // Inform that the key has been set

    cout << endl << "Original Data" << endl << endl;

    encrypter->talk(data); // Print the original data

    cout << endl << "Encrypting" << endl << endl;

    encrypter->enc16(data); // Encrypt the data

    cout << endl << "Encrypted Data" << endl << endl;

    encrypter->talk(data); // Print the encrypted data

    cout << endl << "Decrypting" << endl << endl;

    encrypter->dec16(data); // Decrypt the data

    cout << endl << "Decrypted Data" << endl << endl;

    encrypter->talk(data); // Print the decrypted data

    return 0;
}

// Just saving this here.
// out.open(ofileStr.c_str(), ios::out | ios::binary);



// rbes.h

class RBES
{
    public:
        RBES();
        void setKey(char (&k)[4][4]);
        void enc16(char (&k)[4][4]);
        void dec16(char (&k)[4][4]);
        void talk(char (&c)[4][4]);
    private:
        char key[4][4];
        char roundKey[4][4];
        static const int sbox[256];
        static const int rsbox[256];
        static const int rc[16];
        void shiftCols(char (&data)[4][4]);
        void rshiftCols(char (&data)[4][4]);
        void makeRoundKey(int num);
};



// rbes.cpp

#include <iostream>
#include <string.h>

#include "rbes.h"

using namespace std;


RBES::RBES()
{
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            key[i][j] = 'A'; // Fill key with 'A' as the default key, in case enc16 is called without calling setKey first.
        }
    }
}

void RBES::setKey(char (&k)[4][4])
{
    memcpy(key, k, sizeof(k)); // Set the key.
}

void RBES::enc16(char (&data)[4][4])
{
    int curRound = 0; // This variable will be used as an index to traverse previous round keys.
    makeRoundKey(curRound++); // Get round key number 'curRound' THEN increment curRound.
    for(int h = 0; h < 4; h++) // 2 loops to access full 2D array.
    {
        for(int i = 0; i < 4; i++) // 2 loops to access full 2D array.
        {
            data[h][i] ^= roundKey[h][i]; // XOR the data with the previously selected round key.
        }
    }
    // talk(data);

    for(int t = 1; t <= 16; t++) // Loop 15 times for a total of 16 XOR's with round keys.
    {
        for(int h = 0; h < 4; h++) // 2 loops to access full 2D array.
        {
            for(int i = 0; i < 4; i++) // 2 loops to access full 2D array.
            {
                data[h][i] = sbox[data[h][i]]; // Use the s-box to substitute values.  NOTE: rsbox is the inverse of sbox.
            }
        }
        // talk(data);

        shiftCols(data); // This should be called shiftCells; I need to rename this.
        // talk(data);

        makeRoundKey(curRound++); // Get round key number 'curRound' THEN increment curRound.
        for(int h = 0; h < 4; h++) // 2 loops to access full 2D array.
        {
            for(int i = 0; i < 4; i++) // 2 loops to access full 2D array.
            {
                data[h][i] ^= roundKey[h][i]; // XOR the data with the previously selected round key.
            }
        }
        // talk(data);
    }
}

void RBES::dec16(char (&data)[4][4])
{
    int curRound = 16; // This variable will be used as an index to traverse previous round keys.  Start at 16th round and go down to be inverse of the encryption.
    makeRoundKey(curRound--); // Get round key number 'curRound' THEN decrement curRound.
    for(int h = 0; h < 4; h++) // 2 loops to access full 2D array.
    {
        for(int i = 0; i < 4; i++) // 2 loops to access full 2D array.
        {
            data[h][i] ^= roundKey[h][i]; // XOR the data with the previously selected round key.  SHOULD undo the encryption.
                                          // In fact, it undo's the last operation of the encryption just fine.
        }
    }
    // talk(data);

    for(int t = 1; t <= 16; t++) // Loop 15 times for a total of 16 XOR's with round keys.
    {
        rshiftCols(data); // Reverse the original cell shifts.  This should be called rshiftCells; I need to rename this.
        // talk(data);

        for(int h = 0; h < 4; h++) // 2 loops to access full 2D array.
        {
            for(int i = 0; i < 4; i++) // 2 loops to access full 2D array.
            {
                data[h][i] = rsbox[data[h][i]]; // Use the reverse s-box to substitute values.  NOTE: rsbox is the inverse of sbox.
            }
        }
        // talk(data);

        makeRoundKey(curRound--); // Get round key number 'curRound' THEN decrement curRound.
        for(int h = 0; h < 4; h++) // 2 loops to access full 2D array.
        {
            for(int i = 0; i < 4; i++) // 2 loops to access full 2D array.
            {
                data[h][i] ^= roundKey[h][i];// XOR the data with the previously selected round key to reverse the encryption.
            }
        }
        // talk(data);
    }
}

void RBES::talk(char (&c)[4][4]) // This debug method neatly prints the contents of a 4x4 char array.
{
    cout << "    1  2  3  4 " << endl;
    for(int i = 0; i < 4; i++)
    {
        cout << " " << i << " ";
        for(int h = 0; h < 4; h++)
        {
            if(!(c[i][h] >= 32 && c[i][h] <= 126) && !(c[i][h] >= 128 && c[i][h] <= 254)) // Non-printing values are printed as decimal points
            {
                cout << "[.]";
            }
            else
            {
                cout << "[" << c[i][h] << "]";
            }
        }
        cout << endl;
    }
}

const int RBES::sbox[256] = { 0, 196, 95, 236, 205, 225, 81, 63, 59, 187, 108, 162, 234, 150, 139, 71, 37, 68, 103, 137, 86, 224, 147, 23, 235, 14, 199, 242, 195, 54, 130, 191, 161, 97, 181, 126, 233, 55, 154, 121, 167, 91, 165, 157, 15, 200, 238, 74, 43, 138, 243, 131, 134, 172, 64, 219, 252, 79, 141, 179, 117, 178, 58, 170, 38, 105, 201, 3, 250, 231, 93, 61, 175, 25, 163, 136, 99, 60, 151, 177, 92, 169, 119, 8, 94, 144, 19, 16, 189, 192, 133, 27, 17, 217, 66, 2, 4, 166, 174, 221, 241, 85, 1, 123, 21, 176, 254, 229, 67, 83, 124, 211, 209, 153, 226, 146, 245, 116, 78, 48, 88, 190, 57, 239, 41, 65, 13, 20, 210, 135, 251, 98, 33, 76, 160, 198, 204, 29, 47, 101, 129, 246, 22, 145, 142, 36, 194, 158, 203, 186, 202, 46, 237, 75, 5, 115, 31, 104, 148, 216, 56, 193, 18, 72, 53, 127, 248, 223, 90, 28, 182, 206, 30, 32, 62, 227, 45, 232, 240, 70, 228, 89, 102, 80, 114, 149, 11, 109, 220, 96, 77, 188, 106, 156, 51, 113, 87, 143, 12, 140, 173, 120, 213, 39, 52, 10, 155, 255, 9, 132, 44, 171, 112, 183, 122, 253, 100, 247, 24, 40, 164, 42, 118, 110, 152, 49, 7, 128, 185, 69, 212, 82, 168, 184, 73, 180, 230, 249, 207, 111, 84, 215, 50, 244, 125, 208, 35, 214, 34, 222, 26, 197, 6, 159, 218, 107 };
const int RBES::rsbox[256] = { 0, 102, 95, 67, 96, 154, 252, 226, 83, 208, 205, 186, 198, 126, 25, 44, 87, 92, 162, 86, 127, 104, 142, 23, 218, 73, 250, 91, 169, 137, 172, 156, 173, 132, 248, 246, 145, 16, 64, 203, 219, 124, 221, 48, 210, 176, 151, 138, 119, 225, 242, 194, 204, 164, 29, 37, 160, 122, 62, 8, 77, 71, 174, 7, 54, 125, 94, 108, 17, 229, 179, 15, 163, 234, 47, 153, 133, 190, 118, 57, 183, 6, 231, 109, 240, 101, 20, 196, 120, 181, 168, 41, 80, 70, 84, 2, 189, 33, 131, 76, 216, 139, 182, 18, 157, 65, 192, 255, 10, 187, 223, 239, 212, 195, 184, 155, 117, 60, 222, 82, 201, 39, 214, 103, 110, 244, 35, 165, 227, 140, 30, 51, 209, 90, 52, 129, 75, 19, 49, 14, 199, 58, 144, 197, 85, 143, 115, 22, 158, 185, 13, 78, 224, 113, 38, 206, 193, 43, 147, 253, 134, 32, 11, 74, 220, 42, 97, 40, 232, 81, 63, 211, 53, 200, 98, 72, 105, 79, 61, 59, 235, 34, 170, 213, 233, 228, 149, 9, 191, 88, 121, 31, 89, 161, 146, 28, 1, 251, 135, 26, 45, 66, 150, 148, 136, 4, 171, 238, 245, 112, 128, 111, 230, 202, 247, 241, 159, 93, 254, 55, 188, 99, 249, 167, 21, 5, 114, 175, 180, 107, 236, 69, 177, 36, 12, 24, 3, 152, 46, 123, 178, 100, 27, 50, 243, 116, 141, 217, 166, 237, 68, 130, 56, 215, 106, 207 };
const int RBES::rc[16] = { 1, 2, 4, 8, 16, 32, 64, 128, 41, 42, 44, 48, 56, 72, 104, 168 };

void RBES::shiftCols(char (&data)[4][4])
{
    for(int i = 1; i < 4; i++) // Shift row 0 cells 0 over.  Row 1 cells 1 right.  Row 2 cells 2 right.  Row 3 cells 3 right.
    {
        for(int h = 0; h < i; h++) // If it is row i, shift the cells i times (aka until h = i).
        {
            char tmp = data[i][0]; // Swap variable for the rightmost cell.
            for(int l = 0; l < 3; l++)
            {
                data[i][l] = data[i][l+1]; // Shift each cell right once.
            }
            data[i][3] = tmp; // Original rightmost cell now goes on the left.
        }
    }
}

void RBES::rshiftCols(char (&data)[4][4])
{
    for(int i = 1; i < 4; i++) // Shift row 0 cells 0 over.  Row 1 cells 1 left.  Row 2 cells 2 left.  Row 3 cells 3 left.
    {
        for(int h = 0; h < i; h++) // If it is row i, shift the cells i times (aka until h = i).
        {
            char tmp = data[i][3]; // Swap variable for the leftmost cell.
            for(int l = 3; l > 0; l--)
            {
                data[i][l] = data[i][l-1]; // Shift each cell left once.
            }
            data[i][0] = tmp; // Original leftmost cell now goes on the left.
        }
    }
}

void RBES::makeRoundKey(int num) // Int num is used to specify which roundkey is wanted.  If 0 is given, iterate once.  If 1, iterate twice.
{
    memcpy(roundKey, key, sizeof(key));

    for(int n = 0; n <= num; n++)
    {
        char oldkey[4][4]; // This will hold the previous round key, for calculating the next.
        char newkey[4][4]; // This will hold the new round key.

        memcpy(oldkey, roundKey, sizeof(roundKey)); // Load the current key into the role of the old key.

        for(int t = 0; t < 16; t++) // Iterate 16 times.
        {
            for(int i = 0; i < 4; i++) // Iterate through each column.  i is the index of the column.
            {
                for(int l = 3; l > 0; l--) // This will move the bottom cell to the top.
                {
                    newkey[l][i] = oldkey[l-1][i]; // Set the new key cells to be shifted down 1 from the old key cells.
                }
                newkey[0][i] = oldkey[3][i]; // Don't forget the last one!

                for(int h = 0; h < 4; h++) // This will substitute values from the s-box.
                {
                    newkey[h][i] = sbox[newkey[h][i]]; // Use the s-box to substitute values.
                }

                if(i == 0) // If this is the first iteration...
                {
                    newkey[0][i] ^= rc[t]; // ...then ALSO XOR with the rc value at index t.
                }

                for(int h = 0; h < 4; h++)
                {
                    newkey[h][i] ^= oldkey[h][i]; // XOR the new key with the old key.
                }
            }

            memcpy(oldkey, newkey, sizeof(newkey)); // Set the new key as oldkey, so the next newkey can refer to it as the previous.
        }

        memcpy(roundKey, newkey, sizeof(newkey)); // Copy the result into roundKey.  When the for loop exits, roundKey will have the value of round n.
    }
}



Thanks to anybody that contributes.

Attached File(s)



Is This A Good Question/Topic? 0
  • +

Replies To: Problem With Method Performing Inverse Operations (Encrypt/Decrypt)

#2 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 5666
  • View blog
  • Posts: 22,509
  • Joined: 23-August 08

Re: Problem With Method Performing Inverse Operations (Encrypt/Decrypt)

Posted 26 April 2012 - 03:27 PM

You can start by fixing your warnings:

g++ -ggdb3 -Wall -pedantic -o rbesmain rbesmain.cpp rbes.cpp
rbesmain.cpp: In function ‘int main()’:
rbesmain.cpp:37: warning: overflow in implicit constant conversion
rbesmain.cpp:37: warning: overflow in implicit constant conversion
rbesmain.cpp:37: warning: overflow in implicit constant conversion
rbesmain.cpp:37: warning: overflow in implicit constant conversion
rbesmain.cpp:37: warning: overflow in implicit constant conversion
rbes.cpp: In member function ‘void RBES::enc16(char (&)[4][4])’:
rbes.cpp:46: warning: array subscript has type ‘char’
rbes.cpp: In member function ‘void RBES::dec16(char (&)[4][4])’:
rbes.cpp:89: warning: array subscript has type ‘char’
rbes.cpp: In member function ‘void RBES::talk(char (&)[4][4])’:
rbes.cpp:114: warning: comparison is always false due to limited range of data type
rbes.cpp:114: warning: comparison is always true due to limited range of data type
rbes.cpp: In member function ‘void RBES::makeRoundKey(int)’:
rbes.cpp:186: warning: array subscript has type ‘char’

Was This Post Helpful? 1
  • +
  • -

#3 razbarrie  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 26-April 12

Re: Problem With Method Performing Inverse Operations (Encrypt/Decrypt)

Posted 26 April 2012 - 03:37 PM

View PostJackOfAllTrades, on 26 April 2012 - 04:27 PM, said:

You can start by fixing your warnings:


First off, you're right, I forgot to enable -Wall .

For "array subscript has type 'char'", aren't char c = 'A' and char c = 65 the same thing? Then, is "overflow in implicit constant conversion" because char is from -128 to 127? I assume this also covers "comparison is always false due to limited range of data type" I have successfully stored, encrypted, and decrypted binary data in chars using this method when using simple XOR's.

Thanks for the help.
Was This Post Helpful? 0
  • +
  • -

#4 razbarrie  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 26-April 12

Re: Problem With Method Performing Inverse Operations (Encrypt/Decrypt)

Posted 26 April 2012 - 04:06 PM

With apologies for the double post,

View Postrazbarrie, on 26 April 2012 - 04:37 PM, said:

Then, is "overflow in implicit constant conversion" because char is from -128 to 127? I assume this also covers "comparison is always false due to limited range of data type"


It would appear that was my problem, but I guess the real problem was that I forgot the -Wall flag when coding. Thanks JackOfAllTrades for helping me find my novice mistake!
Was This Post Helpful? 0
  • +
  • -

#5 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1831
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Problem With Method Performing Inverse Operations (Encrypt/Decrypt)

Posted 26 April 2012 - 04:17 PM

View Postrazbarrie, on 26 April 2012 - 06:37 PM, said:

For "array subscript has type 'char'", aren't char c = 'A' and char c = 65 the same thing?

Yes. That's why it's a warning & not an error. The compiler doesn't know what you know. As long as you understand what you're doing you can safely ignore some warning messages.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1