Cryptography - Substitute Bytes Transformation



One of the key components of the popular symmetric encryption technique known as the Advanced Encryption Standard (AES) is the substitution of bytes transformation. AES uses data blocks that are normally 128 bits (16 bytes) in size. It works in rounds, with each round involving a number of modifications to guarantee the security of the encrypted data. With the exception of the first round, the Substitute Bytes transformation is used in all following rounds.

A nonlinear substitution operation known as the Substitute Bytes transformation−also referred to as the "SubBytes" or "S−Box" operation−replaces each byte in the input data with a corresponding byte from a fixed substitution table known as the "S−Box." The S−Box is a pre−established, constant table with 256 entries, each of which is eight bits long. Because of its deliberate design, the S−Box prevents a variety of cryptographic attacks, including differential and linear cryptanalysis, by introducing non−linearity and confusion into the data.

How it Works?

  • Input − Data input is a 4x4 matrix (16 bytes). The SubBytes operation is applied to every byte in the matrix.
  • Substitution − A byte from the S−Box is used to replace each byte in the matrix. Byte by byte, the substitution is carried out, with the matching replacement byte being found using the S−Box.
  • Output − The 4x4 matrix is changed, and each byte is swapped out for its corresponding S−Box value.

The AES algorithm's fixed, well−known S−Box function obscures the relationship between the input and the output, making it more difficult for attackers to deduce patterns or details about the encrypted data.

The SubBytes transformation helps in obtaining the features of diffusion and confusion needed for a robust encryption system. Diffusion guarantees that changes in one area of the plaintext affect a significant portion of the ciphertext, whereas confusion ensures that the relationship between the key and the ciphertext is complex and challenging to analyse.

The Substitute Bytes transformation in AES is a key component that strengthens the encryption and adds non−linearity by substituting a value from the S−Box for each byte of data, increasing thesecurity of the encryption process and resistance to cryptographic attacks.

Substitution Box (S−Box)

A "Substitution Box," or S−Box for short, is an essential feature of several cryptographic methods, including block ciphers, symmetric−key encryption, and the Advanced Encryption Standard (AES). A fixed substitution table called an S−Box is used to substitute output values with input values, which are usually binary digits or bytes. It functions as a nonlinear transformation that strengthens the cryptographic algorithm's security by adding confusion and complexity to the encryption process.

Features

Important features of an S−Box consist of −

  • Non−linearity − The relationship between the input and output values is not a straightforward mathematical function since S−Boxes are made to be nonlinear. The non−linearity of this system helps in preventing multiple cryptographic attacks, including asymmetric and linear cryptanalysis.
  • Confusion − S−Boxes are necessary to achieve the encryption property of confusion. They make sure that there is a complex connection between the ciphertext and the plaintext, which makes it difficult for attackers to work out patterns and details about the encrypted data.
  • Fixed and Predefined − A cryptographic algorithm's S−Box is a fixed and well−known part. Transparency and confidence in the encryption process are ensured by its public awareness and standard design.
  • Substitution − S−Boxes carry out the substitution process, substituting the corresponding output value from the S−Box for each input value. This replacement takes place either bit by bit or byte by byte, dependent upon how the algorithm is constructed.

The S−Box is a particular substitution table that is utilised in the Substitute Bytes transformation in the context of AES throughout each encryption round. The AES S−Box is a key element of the AES algorithm's security because it is made to withstand a variety of cryptographic attacks. To sum up, an S−Box is a fixed, predetermined substitution table that, by complexly and nonlinearly substituting input values with corresponding output values, adds nonlinearity and improves security to cryptographic methods.

Implementation using Python

This code implements the transformation of substitute bytes using the AES S−box. It takes a 4x4 matrix of bytes as input, uses the S−box to each byte, and then generates a new matrix with the substituted bytes.

Example

# S-box substitution table for Advance Encryption Standard
S_BOX = (
   0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
   0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
   0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
   0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
   0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
   0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
   0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
   0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
   0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
   0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
   0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
   0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
   0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
   0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
   0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
   0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
)

def sbt(input_matrix):

   # Substitute bytes in the input matrix using the AES S-box.
   output_matrix = []
   for row in input_matrix:
      new_row = []
      for byte in row:
         new_row.append(S_BOX[byte])
      output_matrix.append(new_row)
   return output_matrix

# function execution
input_matrix = [
   [0x32, 0x88, 0x31, 0xe0],
   [0x43, 0x5a, 0x31, 0x37],
   [0xf6, 0x30, 0x98, 0x07],
   [0xa8, 0x8d, 0xa2, 0x34]
]

output_matrix = sbt(input_matrix)
print("Our Input Matrix:")
for row in input_matrix:
   print(row)
print("\nOur Output Matrix (After Substitution):")
for row in output_matrix:
   print(row)

Following is the output of the above example −

Input/Output

Our Input Matrix:
[50, 136, 49, 224]
[67, 90, 49, 55]
[246, 48, 152, 7]
[168, 141, 162, 52]

Our Output Matrix (After Substitution):
[35, 196, 199, 225]
[26, 190, 199, 154]
[66, 4, 70, 197]
[194, 93, 58, 24]

Implamentation using Java

Now we will implement the code for substitute byte transformation using Java. This Java code implements the transformation of substitute bytes using the AES S-box. It takes a 4x4 matrix of bytes as input, uses the S-box to each byte, and then generates a new matrix with the substituted bytes. The main method shows how to use this function with an example input matrix. Below is the implamentation of sustitute byte transformation −

Example

public class SBT {

   // S-box substitution table for Advance Encryption Standard
   private static final int[] S_BOX = {
      0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
      0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
      0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
      0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
      0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
      0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
      0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
      0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
      0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
      0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
      0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
      0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
      0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
      0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
      0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
      0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
   };

   public static void main(String[] args) {
      int[][] inputMatrix = {
         {0x32, 0x88, 0x31, 0xe0},
         {0x43, 0x5a, 0x31, 0x37},
         {0xf6, 0x30, 0x98, 0x07},
         {0xa8, 0x8d, 0xa2, 0x34}
      };

      int[][] outputMatrix = SBT(inputMatrix);
      System.out.println("Our Input Matrix:");
      ourMatrix(inputMatrix);
      System.out.println("\nOur Output Matrix (After Substitution):");
      ourMatrix(outputMatrix);
   }

   public static int[][] SBT(int[][] inputMatrix) {
      int[][] outputMatrix = new int[4][4];
      for (int i = 0; i < 4; i++) {
         for (int j = 0; j < 4; j++) {
            outputMatrix[i][j] = S_BOX[inputMatrix[i][j]];
         }
      }
      return outputMatrix;
   }

   private static void ourMatrix(int[][] matrix) {
      for (int i = 0; i < matrix.length; i++) {
         System.out.print("[");
         for (int j = 0; j < matrix[i].length; j++) {
            System.out.printf("%d", matrix[i][j]);
            if (j < matrix[i].length - 1) {
               System.out.print(", ");
            }
         }
         System.out.println("]");
      }
   }
}

Following is the output of the above example −

Input/Output

Our Input Matrix:
[50, 136, 49, 224]
[67, 90, 49, 55]
[246, 48, 152, 7]
[168, 141, 162, 52]

Our Output Matrix (After Substitution):
[35, 196, 199, 225]
[26, 190, 199, 154]
[66, 4, 70, 197]
[194, 93, 58, 24]

Implamentation using C++

This C++ code implements the functionality of the previously provided Java code. The input and output matrices are produced in the appropriate format, and the substitution is done using the AES S-box through the definition of a function called substituteBytes. So the code is as follows −

Example

#include <iostream>
#include <iomanip>

// S-box substitution table for Advance Encryption Stadard
const unsigned char S_BOX[] = {
   0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
   0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
   0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
   0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
   0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
   0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
   0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
   0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
   0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
   0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
   0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
   0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
   0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
   0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
   0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
   0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};

void sbt(unsigned char inputMatrix[4][4], unsigned char outputMatrix[4][4]) {
   for (int i = 0; i < 4; i++) {
      for (int j = 0; j < 4; j++) {
         outputMatrix[i][j] = S_BOX[inputMatrix[i][j]];
      }
   }
}

void ourMatrix(unsigned char matrix[4][4]) {
   std::cout << "Our Input Matrix:" << std::endl;
   for (int i = 0; i < 4; i++) {
      std::cout << "[";
      for (int j = 0; j < 4; j++) {
         std::cout << std::setw(3) << (int)matrix[i][j];
         if (j < 3) {
            std::cout << ", ";
         }
      }
      std::cout << "]" << std::endl;
   }
}

void ourMatrixHex(unsigned char matrix[4][4]) {
   std::cout << "\nOur Output Matrix (After Substitution):" << std::endl;
   for (int i = 0; i < 4; i++) {
      std::cout << "[";
      for (int j = 0; j < 4; j++) {
         std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)matrix[i][j];
         if (j < 3) {
            std::cout << ", ";
         }
      }
      std::cout << "]" << std::endl;
   }
}

int main() {
   unsigned char inputMatrix[4][4] = {
      {0x32, 0x88, 0x31, 0xe0},
      {0x43, 0x5a, 0x31, 0x37},
      {0xf6, 0x30, 0x98, 0x07},
      {0xa8, 0x8d, 0xa2, 0x34}
   };

   unsigned char outputMatrix[4][4];
   sbt(inputMatrix, outputMatrix);
   ourMatrix(inputMatrix);
   ourMatrixHex(outputMatrix);

   return 0;
}

OutputM

Our Input Matrix:
[ 50, 136,  49, 224]
[ 67,  90,  49,  55]
[246,  48, 152,   7]
[168, 141, 162,  52]

Our Output Matrix (After Substitution):
[23, c4, c7, e1]
[1a, be, c7, 9a]
[42, 04, 46, c5]
[c2, 5d, 3a, 18]

Summary

The Substitute Bytes transformation enhances AES encryption by introducing non−linearity and confusion, two qualities needed in robust cryptographic systems. It strengthens the general protections of the AES algorithm against different cryptographic attacks and increases security.

Advertisements