Which of the following is are the common steps performed in every round during encryption and decryption?

Advanced Encryption Standard (AES) is a specification for the encryption of electronic data established by the U.S National Institute of Standards and Technology (NIST) in 2001. AES is widely used today as it is a much stronger than DES and triple DES despite being harder to implement.

Points to remember

  • AES is a block cipher.
  • The key size can be 128/192/256 bits.
  • Encrypts data in blocks of 128 bits each.

That means it takes 128 bits as input and outputs 128 bits of encrypted cipher text as output. AES relies on substitution-permutation network principle which means it is performed using a series of linked operations which involves replacing and shuffling of the input data.

Working of the cipher :
AES performs operations on bytes of data rather than in bits. Since the block size is 128 bits, the cipher processes 128 bits (or 16 bytes) of the input data at a time.

The number of rounds depends on the key length as follows :

  • 128 bit key – 10 rounds
  • 192 bit key – 12 rounds
  • 256 bit key – 14 rounds

Creation of Round keys :
A Key Schedule algorithm is used to calculate all the round keys from the key. So the initial key is used to create many different round keys which will be used in the corresponding round of the encryption.

Which of the following is are the common steps performed in every round during encryption and decryption?

 

Encryption :
AES considers each block as a 16 byte (4 byte x 4 byte = 128 ) grid in a column major arrangement.

[ b0 | b4 | b8 | b12 | | b1 | b5 | b9 | b13 | | b2 | b6 | b10| b14 | | b3 | b7 | b11| b15 ]

Each round comprises of 4 steps :

  • SubBytes
  • ShiftRows
  • MixColumns
  • Add Round Key

The last round doesn’t have the MixColumns round.

The SubBytes does the substitution and ShiftRows and MixColumns performs the permutation in the algorithm.

SubBytes  :
This step implements the substitution.

In this step each byte is substituted by another byte. Its performed using a lookup table also called the S-box. This substitution is done in a way that a byte is never substituted by itself and also not substituted by another byte which is a compliment of the current byte. The result of this step is a 16 byte (4 x 4 ) matrix like before.

The next two steps implement the permutation.

ShiftRows :
This step is just as it sounds. Each row is shifted a particular number of times.

  • The first row is not shifted
  • The second row is shifted once to the left.
  • The third row is shifted twice to the left.
  • The fourth row is shifted thrice to the left.

(A left circular shift is performed.)

[ b0 | b1 | b2 | b3 ] [ b0 | b1 | b2 | b3 ] | b4 | b5 | b6 | b7 | -> | b5 | b6 | b7 | b4 | | b8 | b9 | b10 | b11 | | b10 | b11 | b8 | b9 | [ b12 | b13 | b14 | b15 ] [ b15 | b12 | b13 | b14 ]

MixColumns :
This step is basically a matrix multiplication. Each column is multiplied with a specific matrix and thus the position of each byte in the column is changed as a result.

This step is skipped in the last round.

[ c0 ] [ 2 3 1 1 ] [ b0 ] | c1 | = | 1 2 3 1 | | b1 | | c2 | | 1 1 2 3 | | b2 | [ c3 ] [ 3 1 1 2 ] [ b3 ]

Add Round Keys :
Now the resultant output of the previous stage is XOR-ed with the corresponding round key. Here, the 16 bytes is not considered as a grid but just as 128 bits of data.

Which of the following is are the common steps performed in every round during encryption and decryption?

After all these rounds 128 bits of encrypted data is given back as output. This process is repeated until all the data to be encrypted undergoes this process.

Decryption :
The stages in the rounds can be easily undone as these stages have an opposite to it which when performed reverts the changes.Each 128 blocks goes through the 10,12 or 14 rounds depending on the key size.

The stages of each round in decryption is as follows :

  • Add round key
  • Inverse MixColumns
  • ShiftRows
  • Inverse SubByte

The decryption process is the encryption process done in reverse so i will explain the steps with notable differences.

Inverse MixColumns :
 This step is similar to the MixColumns step in encryption, but differs in the matrix used to carry out the operation.

[ b0 ] [ 14 11 13 9 ] [ c0 ] | b1 | = | 9 14 11 13 | | c1 | | b2 | | 13 9 14 11 | | c2 | [ b3 ] [ 11 13 9 14 ] [ c3 ]

Inverse SubBytes :
Inverse S-box is used as a lookup table and using which the bytes are substituted during decryption.

Summary : 
AES instruction set is now integrated into the CPU (offers throughput of several GB/s)to improve the speed and security of applications that use AES for encryption and decryption. Even though its been 20 years since its introduction we have failed to break the AES algorithm as it is infeasible even with the current technology. Till date the only vulnerability remains in the implementation of the algorithm.


Page 2

#include

using namespace std;

string hex2bin(string s)

{

    unordered_map mp;

    mp['0'] = "0000";

    mp['1'] = "0001";

    mp['2'] = "0010";

    mp['3'] = "0011";

    mp['4'] = "0100";

    mp['5'] = "0101";

    mp['6'] = "0110";

    mp['7'] = "0111";

    mp['8'] = "1000";

    mp['9'] = "1001";

    mp['A'] = "1010";

    mp['B'] = "1011";

    mp['C'] = "1100";

    mp['D'] = "1101";

    mp['E'] = "1110";

    mp['F'] = "1111";

    string bin = "";

    for (int i = 0; i < s.size(); i++) {

        bin += mp[s[i]];

    }

    return bin;

}

string bin2hex(string s)

{

    unordered_map mp;

    mp["0000"] = "0";

    mp["0001"] = "1";

    mp["0010"] = "2";

    mp["0011"] = "3";

    mp["0100"] = "4";

    mp["0101"] = "5";

    mp["0110"] = "6";

    mp["0111"] = "7";

    mp["1000"] = "8";

    mp["1001"] = "9";

    mp["1010"] = "A";

    mp["1011"] = "B";

    mp["1100"] = "C";

    mp["1101"] = "D";

    mp["1110"] = "E";

    mp["1111"] = "F";

    string hex = "";

    for (int i = 0; i < s.length(); i += 4) {

        string ch = "";

        ch += s[i];

        ch += s[i + 1];

        ch += s[i + 2];

        ch += s[i + 3];

        hex += mp[ch];

    }

    return hex;

}

string permute(string k, int* arr, int n)

{

    string per = "";

    for (int i = 0; i < n; i++) {

        per += k[arr[i] - 1];

    }

    return per;

}

string shift_left(string k, int shifts)

{

    string s = "";

    for (int i = 0; i < shifts; i++) {

        for (int j = 1; j < 28; j++) {

            s += k[j];

        }

        s += k[0];

        k = s;

        s = "";

    }

    return k;

}

string xor_(string a, string b)

{

    string ans = "";

    for (int i = 0; i < a.size(); i++) {

        if (a[i] == b[i]) {

            ans += "0";

        }

        else {

            ans += "1";

        }

    }

    return ans;

}

string encrypt(string pt, vector rkb,

               vector rk)

{

    pt = hex2bin(pt);

    int initial_perm[64]

        = { 58, 50, 42, 34, 26, 18, 10, 2,  60, 52, 44,

            36, 28, 20, 12, 4,  62, 54, 46, 38, 30, 22,

            14, 6,  64, 56, 48, 40, 32, 24, 16, 8,  57,

            49, 41, 33, 25, 17, 9,  1,  59, 51, 43, 35,

            27, 19, 11, 3,  61, 53, 45, 37, 29, 21, 13,

            5,  63, 55, 47, 39, 31, 23, 15, 7 };

    pt = permute(pt, initial_perm, 64);

    cout << "After initial permutation: " << bin2hex(pt)

         << endl;

    string left = pt.substr(0, 32);

    string right = pt.substr(32, 32);

    cout << "After splitting: L0=" << bin2hex(left)

         << " R0=" << bin2hex(right) << endl;

    int exp_d[48]

        = { 32, 1,  2,  3,  4,  5,  4,  5,  6,  7,  8,  9,

            8,  9,  10, 11, 12, 13, 12, 13, 14, 15, 16, 17,

            16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,

            24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 };

    int s[8][4][16] = {

        { 14, 4,  13, 1, 2,  15, 11, 8,  3,  10, 6,  12, 5,

          9,  0,  7,  0, 15, 7,  4,  14, 2,  13, 1,  10, 6,

          12, 11, 9,  5, 3,  8,  4,  1,  14, 8,  13, 6,  2,

          11, 15, 12, 9, 7,  3,  10, 5,  0,  15, 12, 8,  2,

          4,  9,  1,  7, 5,  11, 3,  14, 10, 0,  6,  13 },

        { 15, 1,  8,  14, 6,  11, 3, 4,  9,  7,  2,  13, 12,

          0,  5,  10, 3,  13, 4,  7, 15, 2,  8,  14, 12, 0,

          1,  10, 6,  9,  11, 5,  0, 14, 7,  11, 10, 4,  13,

          1,  5,  8,  12, 6,  9,  3, 2,  15, 13, 8,  10, 1,

          3,  15, 4,  2,  11, 6,  7, 12, 0,  5,  14, 9 },

        { 10, 0,  9,  14, 6,  3,  15, 5,  1,  13, 12,

          7,  11, 4,  2,  8,  13, 7,  0,  9,  3,  4,

          6,  10, 2,  8,  5,  14, 12, 11, 15, 1,  13,

          6,  4,  9,  8,  15, 3,  0,  11, 1,  2,  12,

          5,  10, 14, 7,  1,  10, 13, 0,  6,  9,  8,

          7,  4,  15, 14, 3,  11, 5,  2,  12 },

        { 7,  13, 14, 3,  0,  6,  9,  10, 1,  2, 8,  5,  11,

          12, 4,  15, 13, 8,  11, 5,  6,  15, 0, 3,  4,  7,

          2,  12, 1,  10, 14, 9,  10, 6,  9,  0, 12, 11, 7,

          13, 15, 1,  3,  14, 5,  2,  8,  4,  3, 15, 0,  6,

          10, 1,  13, 8,  9,  4,  5,  11, 12, 7, 2,  14 },

        { 2,  12, 4, 1,  7,  10, 11, 6, 8,  5,  3,  15, 13,

          0,  14, 9, 14, 11, 2,  12, 4, 7,  13, 1,  5,  0,

          15, 10, 3, 9,  8,  6,  4,  2, 1,  11, 10, 13, 7,

          8,  15, 9, 12, 5,  6,  3,  0, 14, 11, 8,  12, 7,

          1,  14, 2, 13, 6,  15, 0,  9, 10, 4,  5,  3 },

        { 12, 1,  10, 15, 9,  2,  6,  8,  0,  13, 3, 4, 14,

          7,  5,  11, 10, 15, 4,  2,  7,  12, 9,  5, 6, 1,

          13, 14, 0,  11, 3,  8,  9,  14, 15, 5,  2, 8, 12,

          3,  7,  0,  4,  10, 1,  13, 11, 6,  4,  3, 2, 12,

          9,  5,  15, 10, 11, 14, 1,  7,  6,  0,  8, 13 },

        { 4,  11, 2,  14, 15, 0,  8, 13, 3,  12, 9,  7,  5,

          10, 6,  1,  13, 0,  11, 7, 4,  9,  1,  10, 14, 3,

          5,  12, 2,  15, 8,  6,  1, 4,  11, 13, 12, 3,  7,

          14, 10, 15, 6,  8,  0,  5, 9,  2,  6,  11, 13, 8,

          1,  4,  10, 7,  9,  5,  0, 15, 14, 2,  3,  12 },

        { 13, 2,  8, 4,  6,  15, 11, 1,  10, 9, 3, 14, 5,

          0,  12, 7, 1,  15, 13, 8,  10, 3,  7, 4, 12, 5,

          6,  11, 0, 14, 9,  2,  7,  11, 4,  1, 9, 12, 14,

          2,  0,  6, 10, 13, 15, 3,  5,  8,  2, 1, 14, 7,

          4,  10, 8, 13, 15, 12, 9,  0,  3,  5, 6, 11 }

    };

    int per[32]

        = { 16, 7, 20, 21, 29, 12, 28, 17, 1,  15, 23,

            26, 5, 18, 31, 10, 2,  8,  24, 14, 32, 27,

            3,  9, 19, 13, 30, 6,  22, 11, 4,  25 };

    cout << endl;

    for (int i = 0; i < 16; i++) {

        string right_expanded = permute(right, exp_d, 48);

        string x = xor_(rkb[i], right_expanded);

        string op = "";

        for (int i = 0; i < 8; i++) {

            int row = 2 * int(x[i * 6] - '0')

                      + int(x[i * 6 + 5] - '0');

            int col = 8 * int(x[i * 6 + 1] - '0')

                      + 4 * int(x[i * 6 + 2] - '0')

                      + 2 * int(x[i * 6 + 3] - '0')

                      + int(x[i * 6 + 4] - '0');

            int val = s[i][row][col];

            op += char(val / 8 + '0');

            val = val % 8;

            op += char(val / 4 + '0');

            val = val % 4;

            op += char(val / 2 + '0');

            val = val % 2;

            op += char(val + '0');

        }

        op = permute(op, per, 32);

        x = xor_(op, left);

        left = x;

        if (i != 15) {

            swap(left, right);

        }

        cout << "Round " << i + 1 << " " << bin2hex(left)

             << " " << bin2hex(right) << " " << rk[i]

             << endl;

    }

    string combine = left + right;

    int final_perm[64]

        = { 40, 8,  48, 16, 56, 24, 64, 32, 39, 7,  47,

            15, 55, 23, 63, 31, 38, 6,  46, 14, 54, 22,

            62, 30, 37, 5,  45, 13, 53, 21, 61, 29, 36,

            4,  44, 12, 52, 20, 60, 28, 35, 3,  43, 11,

            51, 19, 59, 27, 34, 2,  42, 10, 50, 18, 58,

            26, 33, 1,  41, 9,  49, 17, 57, 25 };

    string cipher

        = bin2hex(permute(combine, final_perm, 64));

    return cipher;

}

int main()

{

    string pt, key;

    pt = "123456ABCD132536";

    key = "AABB09182736CCDD";

    key = hex2bin(key);

    int keyp[56]

        = { 57, 49, 41, 33, 25, 17, 9,  1,  58, 50, 42, 34,

            26, 18, 10, 2,  59, 51, 43, 35, 27, 19, 11, 3,

            60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7,

            62, 54, 46, 38, 30, 22, 14, 6,  61, 53, 45, 37,

            29, 21, 13, 5,  28, 20, 12, 4 };

    key = permute(key, keyp, 56);

    int shift_table[16] = { 1, 1, 2, 2, 2, 2, 2, 2,

                            1, 2, 2, 2, 2, 2, 2, 1 };

    int key_comp[48] = { 14, 17, 11, 24, 1,  5,  3,  28,

                         15, 6,  21, 10, 23, 19, 12, 4,

                         26, 8,  16, 7,  27, 20, 13, 2,

                         41, 52, 31, 37, 47, 55, 30, 40,

                         51, 45, 33, 48, 44, 49, 39, 56,

                         34, 53, 46, 42, 50, 36, 29, 32 };

    string left = key.substr(0, 28);

    string right = key.substr(28, 28);

    vector rkb;

    vector rk;

    for (int i = 0; i < 16; i++) {

        left = shift_left(left, shift_table[i]);

        right = shift_left(right, shift_table[i]);

        string combine = left + right;

        string RoundKey = permute(combine, key_comp, 48);

        rkb.push_back(RoundKey);

        rk.push_back(bin2hex(RoundKey));

    }

    cout << "\nEncryption:\n\n";

    string cipher = encrypt(pt, rkb, rk);

    cout << "\nCipher Text: " << cipher << endl;

    cout << "\nDecryption\n\n";

    reverse(rkb.begin(), rkb.end());

    reverse(rk.begin(), rk.end());

    string text = encrypt(cipher, rkb, rk);

    cout << "\nPlain Text: " << text << endl;

}