|
|
.版本 2
.支持库 spec
' ===================== 常量定义(AES标准)=====================
.常量 S盒, "0123456789ABCDEF", 0, "AES标准S盒(256字节)"
.常量 逆S盒, "0123456789ABCDEF", 0, "AES逆S盒(256字节)"
.常量 Rcon, "0123456789ABCDEF", 0, "AES轮常量(用于密钥扩展)"
.常量 GF128_POLY, 整数型, , 0xE1000000, "GF(2^128)不可约多项式:x^128+x^7+x^2+x+1(高32位)"
' ===================== 全局变量(初始化S盒/逆S盒/Rcon)=====================
.全局变量 S盒数组, 字节型, , "256"
.全局变量 逆S盒数组, 字节型, , "256"
.全局变量 Rcon数组, 字节型, , "15" ' AES-256最多需要14轮,Rcon到14即可
' ===================== 初始化函数(程序启动时执行)=====================
.子程序 初始化AES常量, , 公开
.局部变量 i, 整数型
' 初始化S盒(标准AES S盒)
S盒数组 = { 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 112, 148, 185, 206, 246, 123, 161, 189, 169, 171, 181, 102, 104, 105, 140, 158, 152, 153, 155, 142, 144, 139, 138, 137, 135, 134, 130, 128, 125, 124, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }
' 初始化逆S盒(标准AES逆S盒)
逆S盒数组 = { 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 242, 188, 140, 151, 207, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 150, 121, 193, 175, 189, 3, 1, 19, 17, 240, 230, 97, 107, 244, 172, 249, 206, 180, 234, 171, 220, 241, 226, 103, 86, 147, 223, 231, 176, 34, 71, 183, 115, 128, 10, 136, 14, 117, 239, 32, 127, 156, 24, 197, 201, 177, 254, 122, 232, 199, 110, 79, 173, 4, 138, 116, 216, 159, 210, 170, 200, 221, 111, 62, 75, 198, 219, 137, 18, 16, 89, 39, 126, 12, 153, 190, 236, 90, 23, 53, 49, 192, 154, 229, 168, 224, 211, 60, 205, 245, 59, 7, 83, 58, 225, 85, 28, 133, 31, 169, 29, 41, 113, 181, 187, 105, 55, 45, 120, 145, 174, 20, 214, 119, 38, 247, 13, 15, 235, 238, 74, 81, 160, 125, 186, 131, 95, 96, 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 242, 188, 140, 151, 207, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 150, 121, 193, 175, 189, 3, 1, 19, 17, 240, 230, 97, 107, 244, 172, 249, 206, 180, 234, 171, 220, 241, 226, 103, 86, 147, 223, 231, 176, 34, 71, 183, 115, 128, 10, 136, 14, 117, 239, 32, 127, 156, 24, 197, 201, 177, 254, 122, 232, 199, 110, 79, 173, 4, 138, 116, 216, 159, 210, 170, 200, 221, 111, 62, 75, 198, 219, 137, 18, 16, 89, 39, 126, 12, 153, 190, 236, 90, 23, 53, 49, 192, 154, 229, 168, 224, 211, 60, 205, 245, 59, 7, 83, 58, 225, 85, 28, 133, 31, 169, 29, 41, 113, 181, 187, 105, 55, 45, 120, 145, 174, 20, 214, 119, 38, 247, 13, 15, 235, 238, 74, 81, 160, 125, 186, 131, 95, 96 }
' 初始化轮常量Rcon(AES-256专用)
Rcon数组 = { 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154 }
' ===================== AES核心辅助函数 =====================
' 字节代换:对4x4矩阵执行S盒替换
.子程序 SubBytes, , 公开, 输入4x4字节矩阵,输出替换后的矩阵
.参数 矩阵, 字节型, 数组, "4,4"
.局部变量 行, 整数型
.局部变量 列, 整数型
.计次循环首 (4, 行)
.计次循环首 (4, 列)
矩阵 [行][列] = S盒数组 [矩阵 [行][列]]
.计次循环尾 ()
.计次循环尾 ()
' 逆字节代换:对4x4矩阵执行逆S盒替换
.子程序 InvSubBytes, , 公开
.参数 矩阵, 字节型, 数组, "4,4"
.局部变量 行, 整数型
.局部变量 列, 整数型
.计次循环首 (4, 行)
.计次循环首 (4, 列)
矩阵 [行][列] = 逆S盒数组 [矩阵 [行][列]]
.计次循环尾 ()
.计次循环尾 ()
' 行移位:AES标准行移位(第0行不移,第1行移1位,第2行移2位,第3行移3位)
.子程序 ShiftRows, , 公开
.参数 矩阵, 字节型, 数组, "4,4"
.局部变量 临时, 字节型
.局部变量 i, 整数型
' 第1行移位1位
临时 = 矩阵 [1][0]
.计次循环首 (3, i)
矩阵 [1][i - 1] = 矩阵 [1][i]
.计次循环尾 ()
矩阵 [1][3] = 临时
' 第2行移位2位
临时 = 矩阵 [2][0]
矩阵 [2][0] = 矩阵 [2][2]
矩阵 [2][2] = 临时
临时 = 矩阵 [2][1]
矩阵 [2][1] = 矩阵 [2][3]
矩阵 [2][3] = 临时
' 第3行移位3位
临时 = 矩阵 [3][3]
.计次循环首 (3, i)
矩阵 [3][4 - i] = 矩阵 [3][3 - i]
.计次循环尾 ()
矩阵 [3][0] = 临时
' 逆行移位:AES标准逆行移位
.子程序 InvShiftRows, , 公开
.参数 矩阵, 字节型, 数组, "4,4"
.局部变量 临时, 字节型
.局部变量 i, 整数型
' 第1行逆移位1位
临时 = 矩阵 [1][3]
.计次循环首 (3, i)
矩阵 [1][4 - i] = 矩阵 [1][3 - i]
.计次循环尾 ()
矩阵 [1][0] = 临时
' 第2行逆移位2位(和移位2位相同)
临时 = 矩阵 [2][0]
矩阵 [2][0] = 矩阵 [2][2]
矩阵 [2][2] = 临时
临时 = 矩阵 [2][1]
矩阵 [2][1] = 矩阵 [2][3]
矩阵 [2][3] = 临时
' 第3行逆移位3位
临时 = 矩阵 [3][0]
.计次循环首 (3, i)
矩阵 [3][i] = 矩阵 [3][i + 1]
.计次循环尾 ()
矩阵 [3][3] = 临时
' GF(2^8)乘法:AES列混合专用(a*b mod x^8+x^4+x^3+x+1)
.子程序 GF8_Mul, 字节型, 公开
.参数 a, 字节型
.参数 b, 字节型
.局部变量 结果, 字节型
.局部变量 i, 整数型
结果 = 0
.计次循环首 (8, i)
.如果真 (b & 1 ≠ 0)
结果 = 结果 ^ a
.如果真结束
b = b >> 1
.如果真 (a & 128 ≠ 0)
a = (a << 1) ^ 27 ' 27 = 0x1B(不可约多项式)
.如果真结束
.否则
a = a << 1
.如果真结束
.计次循环尾 ()
返回 (结果)
' 列混合:AES标准列混合(4x4矩阵列混合)
.子程序 MixColumns, , 公开
.参数 矩阵, 字节型, 数组, "4,4"
.局部变量 临时列, 字节型, 数组, "4"
.局部变量 列, 整数型
.局部变量 行, 整数型
.计次循环首 (4, 列)
' 保存当前列
.计次循环首 (4, 行)
临时列 [行] = 矩阵 [行][列]
.计次循环尾 ()
' 列混合计算
矩阵 [0][列] = GF8_Mul (2, 临时列 [0]) ^ GF8_Mul (3, 临时列 [1]) ^ 临时列 [2] ^ 临时列 [3]
矩阵 [1][列] = 临时列 [0] ^ GF8_Mul (2, 临时列 [1]) ^ GF8_Mul (3, 临时列 [2]) ^ 临时列 [3]
矩阵 [2][列] = 临时列 [0] ^ 临时列 [1] ^ GF8_Mul (2, 临时列 [2]) ^ GF8_Mul (3, 临时列 [3])
矩阵 [3][列] = GF8_Mul (3, 临时列 [0]) ^ 临时列 [1] ^ 临时列 [2] ^ GF8_Mul (2, 临时列 [3])
.计次循环尾 ()
' 逆列混合:AES标准逆列混合
.子程序 InvMixColumns, , 公开
.参数 矩阵, 字节型, 数组, "4,4"
.局部变量 临时列, 字节型, 数组, "4"
.局部变量 列, 整数型
.局部变量 行, 整数型
.计次循环首 (4, 列)
.计次循环首 (4, 行)
临时列 [行] = 矩阵 [行][列]
.计次循环尾 ()
' 逆列混合计算
矩阵 [0][列] = GF8_Mul (14, 临时列 [0]) ^ GF8_Mul (11, 临时列 [1]) ^ GF8_Mul (13, 临时列 [2]) ^ GF8_Mul (9, 临时列 [3])
矩阵 [1][列] = GF8_Mul (9, 临时列 [0]) ^ GF8_Mul (14, 临时列 [1]) ^ GF8_Mul (11, 临时列 [2]) ^ GF8_Mul (13, 临时列 [3])
矩阵 [2][列] = GF8_Mul (13, 临时列 [0]) ^ GF8_Mul (9, 临时列 [1]) ^ GF8_Mul (14, 临时列 [2]) ^ GF8_Mul (11, 临时列 [3])
矩阵 [3][列] = GF8_Mul (11, 临时列 [0]) ^ GF8_Mul (13, 临时列 [1]) ^ GF8_Mul (9, 临时列 [2]) ^ GF8_Mul (14, 临时列 [3])
.计次循环尾 ()
' 密钥扩展:AES-256密钥扩展(32字节密钥→240字节轮密钥)
.子程序 KeyExpansion, 字节型, 数组, 公开, 输入32字节密钥,输出轮密钥数组(15轮×16字节)
.参数 密钥, 字节集, , 必须32字节(256位)
.局部变量 轮密钥, 字节型, 数组, "15,4,4" ' 15轮,每轮4x4矩阵
.局部变量 临时字, 字节型, 数组, "4"
.局部变量 i, 整数型
.局部变量 j, 整数型
.局部变量 轮, 整数型
' 初始化前8个32位字(32字节)
.计次循环首 (8, i)
.计次循环首 (4, j)
轮密钥 [i \ 4][i % 4][j] = 密钥 [(i × 4) + j]
.计次循环尾 ()
.计次循环尾 ()
' 扩展剩余轮密钥
i = 8
.判断循环首 (i < 60) ' AES-256需要60个32位字(15轮×4字)
' 复制前一个字
.计次循环首 (4, j)
临时字 [j] = 轮密钥 [(i - 1) \ 4][(i - 1) % 4][j]
.计次循环尾 ()
' 每8个字执行一次SubWord+RotWord+Rcon
.如果真 (i % 8 = 0)
' RotWord:循环左移1字节
临时字 = { 临时字 [1], 临时字 [2], 临时字 [3], 临时字 [0] }
' SubWord:S盒替换
.计次循环首 (4, j)
临时字 [j] = S盒数组 [临时字 [j]]
.计次循环尾 ()
' 异或Rcon
临时字 [0] = 临时字 [0] ^ Rcon数组 [i / 8]
.如果真结束
' AES-256额外处理:每4个字异或前4个字的S盒替换
.如果真 (i % 8 = 4)
.计次循环首 (4, j)
临时字 [j] = S盒数组 [临时字 [j]]
.计次循环尾 ()
.如果真结束
' 异或前8个字的对应字
.计次循环首 (4, j)
轮密钥 [i \ 4][i % 4][j] = 轮密钥 [(i - 8) \ 4][(i - 8) % 4][j] ^ 临时字 [j]
.计次循环尾 ()
i = i + 1
.判断循环尾 ()
' 转换为一维数组返回(便于后续使用)
.局部变量 结果, 字节型, 数组, "240"
.局部变量 偏移, 整数型
.计次循环首 (15, 轮)
.计次循环首 (4, j)
.计次循环首 (4, 行)
偏移 = (轮 - 1) × 16 + j × 4 + 行
结果 [偏移] = 轮密钥 [轮 - 1][j][行]
.计次循环尾 ()
.计次循环尾 ()
.计次循环尾 ()
返回 (结果)
' AES-256加密单块(16字节)
.子程序 AES256_EncryptBlock, 字节集, 公开
.参数 输入块, 字节集, , 必须16字节
.参数 轮密钥, 字节型, 数组, "240"
.局部变量 状态, 字节型, 数组, "4,4"
.局部变量 轮, 整数型
.局部变量 行, 整数型
.局部变量 列, 整数型
.局部变量 偏移, 整数型
' 初始化状态矩阵
.计次循环首 (4, 列)
.计次循环首 (4, 行)
状态 [行][列] = 取字节集数据 (输入块, #字节型, 列 × 4 + 行 + 1)
.计次循环尾 ()
.计次循环尾 ()
' 初始轮密钥加
.计次循环首 (4, 列)
.计次循环首 (4, 行)
偏移 = 列 × 4 + 行
状态 [行][列] = 状态 [行][列] ^ 轮密钥 [偏移]
.计次循环尾 ()
.计次循环尾 ()
' 13轮主循环
.计次循环首 (13, 轮)
SubBytes (状态)
ShiftRows (状态)
MixColumns (状态)
' 轮密钥加
.计次循环首 (4, 列)
.计次循环首 (4, 行)
偏移 = 轮 × 16 + 列 × 4 + 行
状态 [行][列] = 状态 [行][列] ^ 轮密钥 [偏移]
.计次循环尾 ()
.计次循环尾 ()
.计次循环尾 ()
' 最后一轮(无MixColumns)
SubBytes (状态)
ShiftRows (状态)
.计次循环首 (4, 列)
.计次循环首 (4, 行)
偏移 = 14 × 16 + 列 × 4 + 行
状态 [行][列] = 状态 [行][列] ^ 轮密钥 [偏移]
.计次循环尾 ()
.计次循环尾 ()
' 转换为字节集返回
.局部变量 输出块, 字节集
输出块 = 取空白字节集 (16)
.计次循环首 (4, 列)
.计次循环首 (4, 行)
字节集替换 (输出块, 列 × 4 + 行 + 1, 1, 到字节集 (状态 [行][列]))
.计次循环尾 ()
.计次循环尾 ()
返回 (输出块)
' ===================== GCM模式核心函数 =====================
' GF(2^128)乘法:GCM专用(a×b mod x^128+x^7+x^2+x+1)
.子程序 GF128_Mul, 字节集, 公开
.参数 a, 字节集, , 16字节
.参数 b, 字节集, , 16字节
.局部变量 结果, 字节集
.局部变量 i, 整数型
.局部变量 j, 整数型
.局部变量 最高位, 逻辑型
结果 = 取空白字节集 (16)
.计次循环首 (16, i)
.计次循环首 (8, j)
' 最低位为1时异或a
.如果真 ((取字节集数据 (b, #字节型, 16 - i + 1) & (1 << (7 - j))) ≠ 0)
结果 = 字节集异或 (结果, a)
.如果真结束
' 结果左移1位
最高位 = (取字节集数据 (结果, #字节型, 1) & 128) ≠ 0
.计次循环首 (15, 行)
字节集替换 (结果, 行, 1, 到字节集 ((取字节集数据 (结果, #字节型, 行) << 1) + (取字节集数据 (结果, #字节型, 行 + 1) >> 7)))
.计次循环尾 ()
字节集替换 (结果, 16, 1, 到字节集 (取字节集数据 (结果, #字节型, 16) << 1))
' 最高位为1时异或不可约多项式
.如果真 (最高位)
结果 = 字节集异或 (结果, 到字节集 ({ 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }))
.如果真结束
.计次循环尾 ()
.计次循环尾 ()
返回 (结果)
' GHASH:GCM认证哈希函数
.子程序 GHASH, 字节集, 公开
.参数 H, 字节集, , 16字节(AES加密全0块的结果)
.参数 数据, 字节集, , 附加数据+密文(已填充到16字节倍数)
.局部变量 结果, 字节集
.局部变量 块数, 整数型
.局部变量 i, 整数型
.局部变量 块, 字节集
结果 = 取空白字节集 (16)
块数 = 取字节集长度 (数据) / 16
.计次循环首 (块数, i)
块 = 取字节集左边 (取字节集右边 (数据, 取字节集长度 (数据) - (i - 1) × 16), 16)
结果 = 字节集异或 (结果, 块)
结果 = GF128_Mul (结果, H)
.计次循环尾 ()
返回 (结果)
' GCTR:GCM计数器模式加密/解密(加密解密逻辑相同)
.子程序 GCTR, 字节集, 公开
.参数 明文, 字节集
.参数 初始计数器, 字节集, , 16字节
.参数 轮密钥, 字节型, 数组, "240"
.局部变量 密文, 字节集
.局部变量 块数, 整数型
.局部变量 剩余字节, 整数型
.局部变量 i, 整数型
.局部变量 计数器, 字节集
.局部变量 加密块, 字节集
.局部变量 明文块, 字节集
密文 = 取空白字节集 (取字节集长度 (明文))
块数 = 取字节集长度 (明文) / 16
剩余字节 = 取字节集长度 (明文) % 16
' 处理完整块
计数器 = 初始计数器
.计次循环首 (块数, i)
' 加密计数器
加密块 = AES256_EncryptBlock (计数器, 轮密钥)
' 取明文块
明文块 = 取字节集左边 (取字节集右边 (明文, 取字节集长度 (明文) - (i - 1) × 16), 16)
' 异或得到密文
字节集替换 (密文, (i - 1) × 16 + 1, 16, 字节集异或 (明文块, 加密块))
' 计数器加1(大端序)
.局部变量 进位, 整数型
进位 = 1
.计次循环首 (16, j)
进位 = 取字节集数据 (计数器, #字节型, 17 - j) + 进位
字节集替换 (计数器, 17 - j, 1, 到字节集 (进位 % 256))
进位 = 进位 / 256
.如果真 (进位 = 0)
跳出循环 ()
.如果真结束
.计次循环尾 ()
.计次循环尾 ()
' 处理剩余字节
.如果真 (剩余字节 > 0)
加密块 = AES256_EncryptBlock (计数器, 轮密钥)
明文块 = 取字节集右边 (明文, 剩余字节)
字节集替换 (密文, 块数 × 16 + 1, 剩余字节, 字节集异或 (明文块, 取字节集左边 (加密块, 剩余字节)))
.如果真结束
返回 (密文)
' ===================== AES-GCM-256主函数 =====================
' AES-GCM-256加密
.子程序 AES_GCM_256_Encrypt, 字节集, 公开, 返回:密文+认证标签
.参数 密钥, 字节集, , 必须32字节(256位)
.参数 IV, 字节集, , 推荐12字节(GCM标准)
.参数 附加数据, 字节集, , 可选(如消息头)
.参数 明文, 字节集, , 待加密数据
.参数 标签长度, 整数型, , 推荐16字节(128位)
.局部变量 轮密钥, 字节型, 数组, "240"
.局部变量 H, 字节集, , GHASH的哈希密钥
.局部变量 初始计数器, 字节集
.局部变量 密文, 字节集
.局部变量 认证数据, 字节集
.局部变量 GHASH结果, 字节集
.局部变量 标签, 字节集
' 参数校验
.如果真 (取字节集长度 (密钥) ≠ 32)
信息框 (“密钥必须为32字节(256位)”, #错误图标, )
返回 ({} )
.如果真结束
.如果真 (标签长度 < 4 或 标签长度 > 16)
信息框 (“标签长度必须为4-16字节”, #错误图标, )
返回 ({} )
.如果真结束
' 1. 密钥扩展
轮密钥 = KeyExpansion (密钥)
' 2. 计算哈希密钥H(AES加密全0块)
H = AES256_EncryptBlock (取空白字节集 (16), 轮密钥)
' 3. 生成初始计数器(IV处理)
.如果真 (取字节集长度 (IV) = 12)
初始计数器 = IV + 到字节集 ({ 0, 0, 0, 1 }) ' GCM标准12字节IV处理
.如果真结束
.如果真 (取字节集长度 (IV) ≠ 12)
' 非12字节IV:GHASH(IV)后填充(简化实现,推荐用12字节IV)
.局部变量 IV填充, 字节集
IV填充 = IV + 取空白字节集 ((16 - 取字节集长度 (IV) % 16) % 16)
初始计数器 = GHASH (H, IV填充)
.如果真结束
' 4. GCTR加密明文得到密文
密文 = GCTR (明文, 初始计数器, 轮密钥)
' 5. 计算认证标签
' 5.1 构造认证数据:附加数据(填充) + 密文(填充) + 长度信息
.局部变量 AD填充, 字节集
AD填充 = 附加数据 + 取空白字节集 ((16 - 取字节集长度 (附加数据) % 16) % 16)
.局部变量 密文填充, 字节集
密文填充 = 密文 + 取空白字节集 ((16 - 取字节集长度 (密文) % 16) % 16)
' 长度信息:附加数据长度(bit) + 密文长度(bit)(各8字节大端序)
.局部变量 长度信息, 字节集
长度信息 = 取空白字节集 (16)
.局部变量 AD长度位, 整数型
AD长度位 = 取字节集长度 (附加数据) × 8
.局部变量 密文长度位, 整数型
密文长度位 = 取字节集长度 (密文) × 8
' 写入AD长度(高8字节)
.计次循环首 (8, i)
字节集替换 (长度信息, 9 - i, 1, 到字节集 (AD长度位 >> ((8 - i) × 8) & 255))
.计次循环尾 ()
' 写入密文长度(低8字节)
.计次循环首 (8, i)
字节集替换 (长度信息, 17 - i, 1, 到字节集 (密文长度位 >> ((8 - i) × 8) & 255))
.计次循环尾 ()
' 拼接认证数据
认证数据 = AD填充 + 密文填充 + 长度信息
' 5.2 计算GHASH
GHASH结果 = GHASH (H, 认证数据)
' 5.3 加密初始计数器(全0)得到J0,异或GHASH结果得到标签
.局部变量 J0, 字节集
J0 = AES256_EncryptBlock (初始计数器, 轮密钥)
标签 = 取字节集左边 (字节集异或 (J0, GHASH结果), 标签长度)
' 6. 返回密文+标签
返回 (密文 + 标签)
' AES-GCM-256解密(包含标签验证)
.子程序 AES_GCM_256_Decrypt, 字节集, 公开, 验证标签成功返回明文,失败返回空
.参数 密钥, 字节集, , 必须32字节(256位)
.参数 IV, 字节集, , 与加密时一致
.参数 附加数据, 字节集, , 与加密时一致
.参数 密文_标签, 字节集, , 密文+认证标签
.参数 标签长度, 整数型, , 与加密时一致(推荐16)
.局部变量 轮密钥, 字节型, 数组, "240"
.局部变量 H, 字节集
.局部变量 初始计数器, 字节集
.局部变量 密文, 字节集
.局部变量 标签, 字节集
.局部变量 计算标签, 字节集
.局部变量 明文, 字节集
' 参数校验
.如果真 (取字节集长度 (密钥) ≠ 32)
信息框 (“密钥必须为32字节(256位)”, #错误图标, )
返回 ({} )
.如果真结束
.如果真 (取字节集长度 (密文_标签) < 标签长度)
信息框 (“密文+标签长度不足”, #错误图标, )
返回 ({} )
.如果真结束
' 分离密文和标签
密文 = 取字节集左边 (密文_标签, 取字节集长度 (密文_标签) - 标签长度)
标签 = 取字节集右边 (密文_标签, 标签长度)
' 1. 密钥扩展
轮密钥 = KeyExpansion (密钥)
' 2. 计算哈希密钥H
H = AES256_EncryptBlock (取空白字节集 (16), 轮密钥)
' 3. 生成初始计数器
.如果真 (取字节集长度 (IV) = 12)
初始计数器 = IV + 到字节集 ({ 0, 0, 0, 1 })
.如果真结束
.如果真 (取字节集长度 (IV) ≠ 12)
.局部变量 IV填充, 字节集
IV填充 = IV + 取空白字节集 ((16 - 取字节集长度 (IV) % 16) % 16)
初始计数器 = GHASH (H, IV填充)
.如果真结束
' 4. GCTR解密密文得到明文(加密解密逻辑相同)
明文 = GCTR (密文, 初始计数器, 轮密钥)
' 5. 验证标签
.局部变量 AD填充, 字节集
AD填充 = 附加数据 + 取空白字节集 ((16 - 取字节集长度 (附加数据) % 16) % 16)
.局部变量 密文填充, 字节集
密文填充 = 密文 + 取空白字节集 ((16 - 取字节集长度 (密文) % 16) % 16)
.局部变量 长度信息, 字节集
长度信息 = 取空白字节集 (16)
.局部变量 AD长度位, 整数型
AD长度位 = 取字节集长度 (附加数据) × 8
.局部变量 密文长度位, 整数型
密文长度位 = 取字节集长度 (密文) × 8
.计次循环首 (8, i)
字节集替换 (长度信息, 9 - i, 1, 到字节集 (AD长度位 >> ((8 - i) × 8) & 255))
.计次循环尾 ()
.计次循环首 (8, i)
字节集替换 (长度信息, 17 - i, 1, 到字节集 (密文长度位 >> ((8 - i) × 8) & 255))
.计次循环尾 ()
.局部变量 认证数据, 字节集
认证数据 = AD填充 + 密文填充 + 长度信息
.局部变量 GHASH结果, 字节集
GHASH结果 = GHASH (H, 认证数据)
.局部变量 J0, 字节集
J0 = AES256_EncryptBlock (初始计数器, 轮密钥)
计算标签 = 取字节集左边 (字节集异或 (J0, GHASH结果), 标签长度)
' 比较标签(恒时间比较,防止侧信道攻击)
.局部变量 验证结果, 整数型
验证结果 = 0
.计次循环首 (标签长度, i)
验证结果 = 验证结果 + 取绝对值 (取字节集数据 (标签, #字节型, i) - 取字节集数据 (计算标签, #字节型, i))
.计次循环尾 ()
.如果真 (验证结果 ≠ 0)
信息框 (“认证标签验证失败!数据可能被篡改”, #错误图标, )
返回 ({} )
.如果真结束
' 6. 返回明文
返回 (明文)
' ===================== 测试示例 =====================
.子程序 测试AES_GCM_256, , 公开
.局部变量 密钥, 字节集
.局部变量 IV, 字节集
.局部变量 附加数据, 字节集
.局部变量 明文, 字节集
.局部变量 密文_标签, 字节集
.局部变量 解密明文, 字节集
' 初始化AES常量
初始化AES常量 ()
' 测试参数(标准测试向量)
密钥 = 到字节集 ({ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F })
IV = 到字节集 ({ 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
附加数据 = 到字节集 (“测试附加数据”)
明文 = 到字节集 (“Hello AES-GCM-256!这是测试明文”)
' 加密
密文_标签 = AES_GCM_256_Encrypt (密钥, IV, 附加数据, 明文, 16)
信息框 (“加密完成,密文+标签长度:” + 到文本 (取字节集长度 (密文_标签)), #信息图标, )
' 解密
解密明文 = AES_GCM_256_Decrypt (密钥, IV, 附加数据, 密文_标签, 16)
.如果真 (取字节集长度 (解密明文) > 0)
信息框 (“解密成功:” + 到文本 (解密明文), #信息图标, )
.如果真结束
|
|