密码学 - 字节替换变换



高级加密标准 (AES) 是一种流行的对称加密技术的关键组成部分,其中一个关键组成部分是字节替换变换。AES 使用通常大小为 128 位(16 字节)的数据块。它以轮次工作,每一轮都涉及对数据进行多次修改以确保加密数据的安全性。除了第一轮之外,在所有后续轮次中都使用字节替换变换。

字节替换变换(也称为“SubBytes”或“S-Box”操作)是一种非线性替换操作,它将输入数据中的每个字节替换为来自固定替换表的相应字节,该替换表称为“S-Box”。S-Box 是一个预先建立的常量表,包含 256 个条目,每个条目都是 8 位长。由于其精心设计,S-Box 通过引入非线性性和混淆来防止各种密码攻击,包括差分和线性密码分析。

它是如何工作的?

  • 输入 - 数据输入是一个 4x4 矩阵(16 字节)。SubBytes 操作应用于矩阵中的每个字节。
  • 替换 - 使用来自 S-Box 的字节替换矩阵中的每个字节。逐字节进行替换,使用 S-Box 查找匹配的替换字节。
  • 输出 - 4x4 矩阵发生变化,每个字节都被换成其对应的 S-Box 值。

AES 算法的固定、众所周知的 S-Box 函数模糊了输入和输出之间的关系,使攻击者更难以推断出关于加密数据的模式或细节。

字节替换变换有助于获得健壮加密系统所需的扩散和混淆特性。扩散确保明文的一个区域中的变化会影响密文的大部分,而混淆确保密钥和密文之间的关系复杂且难以分析。

AES 中的字节替换变换是一个关键组件,它通过将 S-Box 中的值替换为每个数据字节来增强加密并添加非线性,从而提高加密过程的安全性并抵抗密码攻击。

替换盒 (S-Box)

“替换盒”或简称 S-Box 是几种密码方法(包括分组密码、对称密钥加密和高级加密标准 (AES))的重要特征。S-Box 是一个固定的替换表,用于将输入值(通常是二进制数字或字节)替换为输出值。它充当非线性变换,通过在加密过程中添加混淆和复杂性来增强密码算法的安全性。

特征

S-Box 的重要特征包括 -

  • 非线性 - S-Box 被设计为非线性的,因为输入和输出值之间的关系不是简单的数学函数。此系统的非线性有助于防止多种密码攻击,包括非对称和线性密码分析。
  • 混淆 - S-Box 对于实现加密的混淆特性是必要的。它们确保密文和明文之间存在复杂的关系,这使得攻击者难以确定关于加密数据的模式和细节。
  • 固定且预定义 - 密码算法的 S-Box 是一个固定且众所周知的组件。其公开性和标准设计确保了加密过程的透明度和信心。
  • 替换 - S-Box 执行替换过程,将 S-Box 中的相应输出值替换为每个输入值。这种替换逐位或逐字节进行,具体取决于算法的构造方式。

在 AES 的上下文中,S-Box 是在每个加密轮次中用于字节替换变换的特定替换表。AES S-Box 是 AES 算法安全性的一个关键因素,因为它旨在抵御各种密码攻击。总而言之,S-Box 是一个固定且预定义的替换表,通过复杂且非线性地将输入值替换为相应的输出值,从而向密码方法添加非线性并提高安全性。

使用 Python 实现

此代码使用 AES S-box 实现字节替换变换。它将 4x4 字节矩阵作为输入,将 S-box 应用于每个字节,然后生成一个包含替换字节的新矩阵。

示例

# 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)

以下是上述示例的输出 -

输入/输出

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]

使用 Java 实现

现在我们将使用 Java 实现字节替换变换的代码。此 Java 代码使用 AES S-box 实现字节替换变换。它将 4x4 字节矩阵作为输入,将 S-box 应用于每个字节,然后生成一个包含替换字节的新矩阵。main 方法展示了如何使用此函数以及示例输入矩阵。以下是字节替换变换的实现 -

示例

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("]");
      }
   }
}

以下是上述示例的输出 -

输入/输出

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]

使用 C++ 实现

此 C++ 代码实现了先前提供的 Java 代码的功能。输入和输出矩阵以适当的格式生成,并且替换是通过名为 substituteBytes 的函数的定义使用 AES S-box 完成的。因此,代码如下 -

示例

#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;
}

输出M

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]

总结

替代字节变换通过引入非线性与混淆增强了AES加密,这是健壮的密码系统所需的两个特性。它增强了AES算法针对不同密码攻击的总体防护能力,并提高了安全性。

广告