AES-128算法的量子电路实现
使用 Python 对 AES-128 的量子电路实现进行模拟,量子电路实现与经典实现的不同之处在于,其量子电路使用的是量子门,而非经典实现中的运算门,同时其核心在于比特级运算,这对于以字为运算单位的 AES 算法来说,实现起来并不简单。
量子算法的原理这里就不过多介绍,具体可通过量子算法导论学习。
在实现之前,可以通过 AES-128 算法的经典实现 了解 AES 算法的原理。
下面直接开始算法的实现。
本文基于 pipeline 结构的 NCT(NOT + CNOT + Toffoli)量子电路来实现 AES-128 算法。
- pipeline 结构:基于 out-place 结构所需量子比特数较大线路深度更低
- round-in-place 结构:基于 in-place 结构所需量子比特数较少线路深度更高
因为使用 pipeline 结构,所以需要保存每一轮的量子比特。
首先同样是定义一些常量和工具方法。
# 轮常数 省略第一轮
RC = [0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000]
# CNOT NOT Toffoli 三个门电路的模拟实现
def CNOT(qubit_a, qubit_b):
return qubit_a, qubit_b ^ qubit_a
def NOT(qubit):
return qubit ^ 1
def TOFF(qubit_a, qubit_b, qubit_c):
return qubit_a, qubit_b, qubit_c ^ (qubit_a * qubit_b)
# SWAP门的模拟实现 即等于3个CNOT门
def SWAP(qubit_a, qubit_b):
qubit_a, qubit_b = CNOT(qubit_a, qubit_b) # a = a, b = a ^ b
qubit_b, qubit_a = CNOT(qubit_b, qubit_a) # b = a ^ b, a = a ^ b ^ a = b
qubit_a, qubit_b = CNOT(qubit_a, qubit_b) # a = b, b = a ^ b ^ b = a
return qubit_a, qubit_b # a = b b = a
# 取消计算 将辅助比特释放
def uncompute():
pass
"""
工具类
"""
# 将输入的十六进制字符串转换为128比特的量子比特列表
def hex_to_qubits(hex_str):
# 将十六进制字符串转换为二进制字符串
bin_str = bin(int(hex_str, 16))[2:].zfill(128)
# 将二进制字符串转换为量子比特列表
qubits = [int(bit) for bit in bin_str]
return qubits
# 将量子比特列表转换为十六进制字符串
def qubits_to_hex(qubits):
# 将量子比特列表转换为二进制字符串
bin_str = ''.join([str(qubit) for qubit in qubits])
# 将二进制字符串转换为十六进制字符串
hex_str = hex(int(bin_str, 2))[2:].zfill(32)
return hex_str.upper()
S 盒字节代换实现。
这一部分的实现使用的是Huang Z, Sun S. Synthesizing quantum circuits of aes with lower t-depth and less qubits [C]//Agrawal S, Lin D. Advances in Cryptology– ASIACRYPT 2022. Cham: Springer Nature Switzerland, 2022: 614-644. 给出的使用8比特输入输出和120辅助量子比特的out-place结构。
因为使用out-place结构所以需要取消计算的过程。
代码如下:
# S盒 8比特输入输出和68辅助量子比特 分16组
def s_box(U, T):
# U输入, T辅助, S输出
S = [0] * 8
S[2], S[5] = CNOT(S[2], S[5])
S[0], S[3] = CNOT(S[0], S[3])
S[6], S[7] = CNOT(S[6], S[7])
S[1], S[4] = CNOT(S[1], S[4])
S[3], S[1] = CNOT(S[3], S[1])
S[1], S[0] = CNOT(S[1], S[0])
S[0], S[7] = CNOT(S[0], S[7])
S[7], S[4] = CNOT(S[7], S[4])
S[4], S[6] = CNOT(S[4], S[6])
S[7], S[2] = CNOT(S[7], S[2])
S[6], S[2] = CNOT(S[6], S[2])
S[0], S[5] = CNOT(S[0], S[5])
S[3], S[7] = CNOT(S[3], S[7])
U[6], U[4] = CNOT(U[6], U[4])
U[2], U[1] = CNOT(U[2], U[1])
U[6], T[4] = CNOT(U[6], T[4])
U[5], T[6] = CNOT(U[5], T[6])
U[1], T[3] = CNOT(U[1], T[3])
U[3], T[8] = CNOT(U[3], T[8])
U[5], T[8] = CNOT(U[5], T[8])
U[0], U[3] = CNOT(U[0], U[3])
U[4], U[2] = CNOT(U[4], U[2])
U[5], U[2] = CNOT(U[5], U[2])
U[6], U[5] = CNOT(U[6], U[5])
U[3], U[4] = CNOT(U[3], U[4])
U[0], T[4] = CNOT(U[0], T[4])
U[1], T[7] = CNOT(U[1], T[7])
U[0], T[6] = CNOT(U[0], T[6])
U[7], U[1] = CNOT(U[7], U[1])
U[3], T[0] = CNOT(U[3], T[0])
U[1], U[0] = CNOT(U[1], U[0])
U[1], U[6] = CNOT(U[1], U[6])
U[4], T[7] = CNOT(U[4], T[7])
U[4], T[1] = CNOT(U[4], T[1])
U[2], T[3] = CNOT(U[2], T[3])
U[2], T[9] = CNOT(U[2], T[9])
U[2], T[5] = CNOT(U[2], T[5])
U[1], U[2] = CNOT(U[1], U[2])
U[4], T[9] = CNOT(U[4], T[9])
U[3], T[2] = CNOT(U[3], T[2])
U[5], T[0] = CNOT(U[5], T[0])
U[0], U[5] = CNOT(U[0], U[5])
U[0], U[3] = CNOT(U[0], U[3])
U[7], U[4] = CNOT(U[7], U[4])
U[4], U[5], T[10] = TOFF(U[4], U[5], T[10])
U[3], U[7], T[11] = TOFF(U[3], U[7], T[11])
U[1], U[6], T[12] = TOFF(U[1], U[6], T[12])
U[0], U[2], T[13] = TOFF(U[0], U[2], T[13])
T[0], T[1], T[14] = TOFF(T[0], T[1], T[14])
T[2], T[3], T[15] = TOFF(T[2], T[3], T[15])
T[4], T[5], T[16] = TOFF(T[4], T[5], T[16])
T[6], T[7], T[17] = TOFF(T[6], T[7], T[17])
T[8], T[9], T[18] = TOFF(T[8], T[9], T[18])
U[0], T[13] = CNOT(U[0], T[13])
T[4], T[0] = CNOT(T[4], T[0])
T[15], T[17] = CNOT(T[15], T[17])
T[9], T[10] = CNOT(T[9], T[10])
T[35], T[22] = CNOT(T[35], T[22])
T[7], T[14] = CNOT(T[7], T[14])
T[19], U[5] = CNOT(T[19], U[5])
U[3], T[3] = CNOT(U[3], T[3])
T[31], T[2] = CNOT(T[31], T[2])
T[5], T[1] = CNOT(T[5], T[1])
T[8], T[23] = CNOT(T[8], T[23])
T[24], T[37] = CNOT(T[24], T[37])
U[2], U[4] = CNOT(U[2], U[4])
T[6], T[25] = CNOT(T[6], T[25])
T[4], U[0] = CNOT(T[4], U[0])
T[16], T[13] = CNOT(T[16], T[13])
T[15], T[18] = CNOT(T[15], T[18])
T[8], T[0] = CNOT(T[8], T[0])
U[1], T[35] = CNOT(U[1], T[35])
T[6], T[14] = CNOT(T[6], T[14])
T[7], U[7] = CNOT(T[7], U[7])
T[19], T[33] = CNOT(T[19], T[33])
T[9], T[32] = CNOT(T[9], T[32])
T[38], T[3] = CNOT(T[38], T[3])
T[5], T[30] = CNOT(T[5], T[30])
T[17], T[13] = CNOT(T[17], T[13])
U[0], U[6] = CNOT(U[0], U[6])
T[8], T[10] = CNOT(T[8], T[10])
T[4], T[12] = CNOT(T[4], T[12])
T[18], T[16] = CNOT(T[18], T[16])
T[0], T[29] = CNOT(T[0], T[29])
T[34], T[35] = CNOT(T[34], T[35])
T[9], U[7] = CNOT(T[9], U[7])
T[6], U[3] = CNOT(T[6], U[3])
T[7], T[30] = CNOT(T[7], T[30])
U[2], T[32] = CNOT(U[2], T[32])
T[5], T[36] = CNOT(T[5], T[36])
U[0], U[5] = CNOT(U[0], U[5])
T[13], U[7] = CNOT(T[13], U[7])
T[12], T[16] = CNOT(T[12], T[16])
T[10], T[18] = CNOT(T[10], T[18])
T[0], U[4] = CNOT(T[0], U[4])
T[11], T[17] = CNOT(T[11], T[17])
T[5], T[34] = CNOT(T[5], T[34])
T[8], U[3] = CNOT(T[8], U[3])
T[6], T[2] = CNOT(T[6], T[2])
T[9], T[36] = CNOT(T[9], T[36])
T[7], T[38] = CNOT(T[7], T[38])
T[4], T[23] = CNOT(T[4], T[23])
U[2], T[30] = CNOT(U[2], T[30])
U[0], T[1] = CNOT(U[0], T[1])
T[13], U[1] = CNOT(T[13], U[1])
T[14], T[18] = CNOT(T[14], T[18])
T[16], T[0] = CNOT(T[16], T[0])
T[6], U[5] = CNOT(T[6], U[5])
T[9], T[10] = CNOT(T[9], T[10])
U[2], T[34] = CNOT(U[2], T[34])
T[8], T[2] = CNOT(T[8], T[2])
T[7], U[4] = CNOT(T[7], U[4])
T[4], T[12] = CNOT(T[4], T[12])
U[0], T[20] = CNOT(U[0], T[20])
U[2], T[13] = CNOT(U[2], T[13])
T[14], T[17] = CNOT(T[14], T[17])
T[18], T[19] = CNOT(T[18], T[19])
T[16], U[1] = CNOT(T[16], U[1])
T[6], T[1] = CNOT(T[6], T[1])
T[0], U[4] = CNOT(T[0], U[4])
T[34], T[35] = CNOT(T[34], T[35])
T[8], T[25] = CNOT(T[8], T[25])
T[9], T[38] = CNOT(T[9], T[38])
T[7], T[32] = CNOT(T[7], T[32])
T[4], U[0] = CNOT(T[4], U[0])
T[13], T[31] = CNOT(T[13], T[31])
T[7], T[14] = CNOT(T[7], T[14])
T[18], T[16] = CNOT(T[18], T[16])
T[5], T[0] = CNOT(T[5], T[0])
T[19], U[5] = CNOT(T[19], U[5])
U[1], T[35] = CNOT(U[1], T[35])
T[9], T[1] = CNOT(T[9], T[1])
T[8], T[10] = CNOT(T[8], T[10])
T[38], T[3] = CNOT(T[38], T[3])
T[17], T[21] = CNOT(T[17], T[21])
T[17], T[13] = CNOT(T[17], T[13])
U[0], U[3] = CNOT(U[0], U[3])
T[5], T[16] = CNOT(T[5], T[16])
T[6], T[14] = CNOT(T[6], T[14])
T[0], T[29] = CNOT(T[0], T[29])
T[31], T[2] = CNOT(T[31], T[2])
T[19], T[33] = CNOT(T[19], T[33])
T[35], T[22] = CNOT(T[35], T[22])
T[17], T[18] = CNOT(T[17], T[18])
T[13], T[24] = CNOT(T[13], T[24])
U[3], T[3] = CNOT(U[3], T[3])
T[16], T[27] = CNOT(T[16], T[27])
T[16], T[13] = CNOT(T[16], T[13])
T[17], U[3] = CNOT(T[17], U[3])
T[18], T[26] = CNOT(T[18], T[26])
T[24], T[37] = CNOT(T[24], T[37])
T[18], U[6] = CNOT(T[18], U[6])
T[13], T[28] = CNOT(T[13], T[28])
U[4], U[5], T[39] = TOFF(U[4], U[5], T[39])
U[3], U[7], T[40] = TOFF(U[3], U[7], T[40])
U[1], U[6], T[41] = TOFF(U[1], U[6], T[41])
T[0], T[1], T[42] = TOFF(T[0], T[1], T[42])
T[2], T[3], T[43] = TOFF(T[2], T[3], T[43])
T[19], T[20], T[44] = TOFF(T[19], T[20], T[44])
U[0], T[21], T[45] = TOFF(U[0], T[21], T[45])
T[22], T[23], T[46] = TOFF(T[22], T[23], T[46])
T[24], T[25], T[47] = TOFF(T[24], T[25], T[47])
T[4], T[26], T[48] = TOFF(T[4], T[26], T[48])
T[6], T[27], T[49] = TOFF(T[6], T[27], T[49])
T[8], T[28], T[50] = TOFF(T[8], T[28], T[50])
T[29], T[30], T[51] = TOFF(T[29], T[30], T[51])
T[31], T[32], T[52] = TOFF(T[31], T[32], T[52])
T[33], T[34], T[53] = TOFF(T[33], T[34], T[53])
U[2], T[17], T[54] = TOFF(U[2], T[17], T[54])
T[35], T[36], T[55] = TOFF(T[35], T[36], T[55])
T[37], T[38], T[56] = TOFF(T[37], T[38], T[56])
T[5], T[18], T[57] = TOFF(T[5], T[18], T[57])
T[7], T[16], T[58] = TOFF(T[7], T[16], T[58])
T[9], T[13], T[59] = TOFF(T[9], T[13], T[59])
T[13], T[16] = CNOT(T[13], T[16])
T[18], T[26] = CNOT(T[18], T[26])
T[56], T[57] = CNOT(T[56], T[57])
T[21], T[33] = CNOT(T[21], T[33])
T[41], T[27] = CNOT(T[41], T[27])
T[40], T[25] = CNOT(T[40], T[25])
T[58], T[54] = CNOT(T[58], T[54])
T[47], T[48] = CNOT(T[47], T[48])
T[59], T[53] = CNOT(T[59], T[53])
T[49], T[45] = CNOT(T[49], T[45])
T[50], T[24] = CNOT(T[50], T[24])
T[9], T[38] = CNOT(T[9], T[38])
T[22], T[29] = CNOT(T[22], T[29])
U[2], T[5] = CNOT(U[2], T[5])
T[39], T[31] = CNOT(T[39], T[31])
T[8], T[6] = CNOT(T[8], T[6])
T[55], T[30] = CNOT(T[55], T[30])
T[41], T[13] = CNOT(T[41], T[13])
T[57], T[34] = CNOT(T[57], T[34])
T[40], T[21] = CNOT(T[40], T[21])
T[48], T[26] = CNOT(T[48], T[26])
T[59], T[30] = CNOT(T[59], T[30])
T[16], T[24] = CNOT(T[16], T[24])
T[9], T[36] = CNOT(T[9], T[36])
T[43], T[49] = CNOT(T[43], T[49])
T[52], T[58] = CNOT(T[52], T[58])
T[7], T[38] = CNOT(T[7], T[38])
T[39], T[27] = CNOT(T[39], T[27])
T[4], T[8] = CNOT(T[4], T[8])
T[17], T[29] = CNOT(T[17], T[29])
T[6], T[25] = CNOT(T[6], T[25])
T[41], T[18] = CNOT(T[41], T[18])
T[13], T[31] = CNOT(T[13], T[31])
T[53], T[34] = CNOT(T[53], T[34])
T[54], T[57] = CNOT(T[54], T[57])
T[39], T[40] = CNOT(T[39], T[40])
T[50], T[26] = CNOT(T[50], T[26])
T[45], T[48] = CNOT(T[45], T[48])
T[56], T[30] = CNOT(T[56], T[30])
T[7], T[9] = CNOT(T[7], T[9])
T[17], T[21] = CNOT(T[17], T[21])
T[42], T[24] = CNOT(T[42], T[24])
T[5], T[36] = CNOT(T[5], T[36])
T[16], T[22] = CNOT(T[16], T[22])
T[8], T[23] = CNOT(T[8], T[23])
T[41], T[28] = CNOT(T[41], T[28])
T[13], T[25] = CNOT(T[13], T[25])
T[53], T[54] = CNOT(T[53], T[54])
T[18], T[22] = CNOT(T[18], T[22])
T[40], T[29] = CNOT(T[40], T[29])
T[50], T[45] = CNOT(T[50], T[45])
U[2], T[9] = CNOT(U[2], T[9])
T[51], T[30] = CNOT(T[51], T[30])
T[44], T[26] = CNOT(T[44], T[26])
T[5], T[7] = CNOT(T[5], T[7])
T[47], T[24] = CNOT(T[47], T[24])
T[16], T[37] = CNOT(T[16], T[37])
T[17], T[31] = CNOT(T[17], T[31])
T[18], T[41] = CNOT(T[18], T[41])
T[13], T[21] = CNOT(T[13], T[21])
T[59], T[53] = CNOT(T[59], T[53])
T[16], T[40] = CNOT(T[16], T[40])
T[49], T[50] = CNOT(T[49], T[50])
T[39], T[22] = CNOT(T[39], T[22])
T[9], T[32] = CNOT(T[9], T[32])
T[44], T[45] = CNOT(T[44], T[45])
T[5], T[34] = CNOT(T[5], T[34])
T[46], T[24] = CNOT(T[46], T[24])
U[2], T[36] = CNOT(U[2], T[36])
T[7], T[30] = CNOT(T[7], T[30])
T[13], T[18] = CNOT(T[13], T[18])
T[58], T[59] = CNOT(T[58], T[59])
T[40], T[23] = CNOT(T[40], T[23])
T[46], T[49] = CNOT(T[46], T[49])
T[41], T[33] = CNOT(T[41], T[33])
T[42], T[50] = CNOT(T[42], T[50])
T[22], T[29] = CNOT(T[22], T[29])
T[13], T[28] = CNOT(T[13], T[28])
T[56], T[58] = CNOT(T[56], T[58])
T[47], T[49] = CNOT(T[47], T[49])
T[51], T[59] = CNOT(T[51], T[59])
T[18], T[35] = CNOT(T[18], T[35])
T[40], T[32] = CNOT(T[40], T[32])
T[21], T[33] = CNOT(T[21], T[33])
T[16], T[13] = CNOT(T[16], T[13])
T[40], T[28] = CNOT(T[40], T[28])
T[55], T[58] = CNOT(T[55], T[58])
T[39], T[13] = CNOT(T[39], T[13])
T[21], T[24], T[35] = TOFF(T[21], T[24], T[35])
T[22], T[49], T[65] = TOFF(T[22], T[49], T[65])
T[23], T[50], T[61] = TOFF(T[23], T[50], T[61])
T[25], T[26], T[36] = TOFF(T[25], T[26], T[36])
T[27], T[48], T[62] = TOFF(T[27], T[48], T[62])
T[28], T[45], T[66] = TOFF(T[28], T[45], T[66])
T[29], T[30], T[37] = TOFF(T[29], T[30], T[37])
T[31], T[58], T[67] = TOFF(T[31], T[58], T[67])
T[32], T[59], T[63] = TOFF(T[32], T[59], T[63])
T[33], T[34], T[38] = TOFF(T[33], T[34], T[38])
T[13], T[57], T[64] = TOFF(T[13], T[57], T[64])
T[40], T[54], T[60] = TOFF(T[40], T[54], T[60])
T[60], S[0] = CNOT(T[60], S[0])
T[61], S[1] = CNOT(T[61], S[1])
T[62], S[2] = CNOT(T[62], S[2])
T[63], S[3] = CNOT(T[63], S[3])
T[64], S[4] = CNOT(T[64], S[4])
T[65], S[5] = CNOT(T[65], S[5])
T[66], S[6] = CNOT(T[66], S[6])
T[67], S[7] = CNOT(T[67], S[7])
T[35], S[1] = CNOT(T[35], S[1])
T[38], S[0] = CNOT(T[38], S[0])
T[38], S[4] = CNOT(T[38], S[4])
S[3], S[7] = CNOT(S[3], S[7])
T[35], S[5] = CNOT(T[35], S[5])
S[0], S[5] = CNOT(S[0], S[5])
T[37], S[3] = CNOT(T[37], S[3])
S[6], S[2] = CNOT(S[6], S[2])
S[7], S[2] = CNOT(S[7], S[2])
S[4], S[6] = CNOT(S[4], S[6])
S[7], S[4] = CNOT(S[7], S[4])
S[0], S[7] = CNOT(S[0], S[7])
S[1], S[0] = CNOT(S[1], S[0])
T[36], S[6] = CNOT(T[36], S[6])
S[3], S[1] = CNOT(S[3], S[1])
S[1], S[4] = CNOT(S[1], S[4])
S[6], S[7] = CNOT(S[6], S[7])
S[0], S[3] = CNOT(S[0], S[3])
S[2], S[5] = CNOT(S[2], S[5])
S[1] = NOT(S[1])
S[2] = NOT(S[2])
S[6] = NOT(S[6])
S[7] = NOT(S[7])
T[40], T[54], T[60] = TOFF(T[40], T[54], T[60])
T[13], T[57], T[64] = TOFF(T[13], T[57], T[64])
T[33], T[34], T[38] = TOFF(T[33], T[34], T[38])
T[32], T[59], T[63] = TOFF(T[32], T[59], T[63])
T[31], T[58], T[67] = TOFF(T[31], T[58], T[67])
T[29], T[30], T[37] = TOFF(T[29], T[30], T[37])
T[28], T[45], T[66] = TOFF(T[28], T[45], T[66])
T[27], T[48], T[62] = TOFF(T[27], T[48], T[62])
T[25], T[26], T[36] = TOFF(T[25], T[26], T[36])
T[23], T[50], T[61] = TOFF(T[23], T[50], T[61])
T[22], T[49], T[65] = TOFF(T[22], T[49], T[65])
T[21], T[24], T[35] = TOFF(T[21], T[24], T[35])
T[39], T[13] = CNOT(T[39], T[13])
T[55], T[58] = CNOT(T[55], T[58])
T[40], T[28] = CNOT(T[40], T[28])
T[16], T[13] = CNOT(T[16], T[13])
T[21], T[33] = CNOT(T[21], T[33])
T[40], T[32] = CNOT(T[40], T[32])
T[18], T[35] = CNOT(T[18], T[35])
T[51], T[59] = CNOT(T[51], T[59])
T[47], T[49] = CNOT(T[47], T[49])
T[56], T[58] = CNOT(T[56], T[58])
T[13], T[28] = CNOT(T[13], T[28])
T[22], T[29] = CNOT(T[22], T[29])
T[42], T[50] = CNOT(T[42], T[50])
T[41], T[33] = CNOT(T[41], T[33])
T[46], T[49] = CNOT(T[46], T[49])
T[40], T[23] = CNOT(T[40], T[23])
T[58], T[59] = CNOT(T[58], T[59])
T[13], T[18] = CNOT(T[13], T[18])
T[7], T[30] = CNOT(T[7], T[30])
U[2], T[36] = CNOT(U[2], T[36])
T[46], T[24] = CNOT(T[46], T[24])
T[5], T[34] = CNOT(T[5], T[34])
T[44], T[45] = CNOT(T[44], T[45])
T[9], T[32] = CNOT(T[9], T[32])
T[39], T[22] = CNOT(T[39], T[22])
T[49], T[50] = CNOT(T[49], T[50])
T[16], T[40] = CNOT(T[16], T[40])
T[59], T[53] = CNOT(T[59], T[53])
T[13], T[21] = CNOT(T[13], T[21])
T[18], T[41] = CNOT(T[18], T[41])
T[17], T[31] = CNOT(T[17], T[31])
T[16], T[37] = CNOT(T[16], T[37])
T[47], T[24] = CNOT(T[47], T[24])
T[5], T[7] = CNOT(T[5], T[7])
T[44], T[26] = CNOT(T[44], T[26])
T[51], T[30] = CNOT(T[51], T[30])
U[2], T[9] = CNOT(U[2], T[9])
T[50], T[45] = CNOT(T[50], T[45])
T[40], T[29] = CNOT(T[40], T[29])
T[18], T[22] = CNOT(T[18], T[22])
T[53], T[54] = CNOT(T[53], T[54])
T[13], T[25] = CNOT(T[13], T[25])
T[41], T[28] = CNOT(T[41], T[28])
T[8], T[23] = CNOT(T[8], T[23])
T[16], T[22] = CNOT(T[16], T[22])
T[5], T[36] = CNOT(T[5], T[36])
T[42], T[24] = CNOT(T[42], T[24])
T[17], T[21] = CNOT(T[17], T[21])
T[7], T[9] = CNOT(T[7], T[9])
T[56], T[30] = CNOT(T[56], T[30])
T[45], T[48] = CNOT(T[45], T[48])
T[50], T[26] = CNOT(T[50], T[26])
T[39], T[40] = CNOT(T[39], T[40])
T[54], T[57] = CNOT(T[54], T[57])
T[53], T[34] = CNOT(T[53], T[34])
T[13], T[31] = CNOT(T[13], T[31])
T[41], T[18] = CNOT(T[41], T[18])
T[6], T[25] = CNOT(T[6], T[25])
T[17], T[29] = CNOT(T[17], T[29])
T[4], T[8] = CNOT(T[4], T[8])
T[39], T[27] = CNOT(T[39], T[27])
T[7], T[38] = CNOT(T[7], T[38])
T[52], T[58] = CNOT(T[52], T[58])
T[43], T[49] = CNOT(T[43], T[49])
T[9], T[36] = CNOT(T[9], T[36])
T[16], T[24] = CNOT(T[16], T[24])
T[59], T[30] = CNOT(T[59], T[30])
T[48], T[26] = CNOT(T[48], T[26])
T[40], T[21] = CNOT(T[40], T[21])
T[57], T[34] = CNOT(T[57], T[34])
T[41], T[13] = CNOT(T[41], T[13])
T[55], T[30] = CNOT(T[55], T[30])
T[8], T[6] = CNOT(T[8], T[6])
T[39], T[31] = CNOT(T[39], T[31])
U[2], T[5] = CNOT(U[2], T[5])
T[22], T[29] = CNOT(T[22], T[29])
T[9], T[38] = CNOT(T[9], T[38])
T[50], T[24] = CNOT(T[50], T[24])
T[49], T[45] = CNOT(T[49], T[45])
T[59], T[53] = CNOT(T[59], T[53])
T[47], T[48] = CNOT(T[47], T[48])
T[58], T[54] = CNOT(T[58], T[54])
T[40], T[25] = CNOT(T[40], T[25])
T[41], T[27] = CNOT(T[41], T[27])
T[21], T[33] = CNOT(T[21], T[33])
T[56], T[57] = CNOT(T[56], T[57])
T[18], T[26] = CNOT(T[18], T[26])
T[13], T[16] = CNOT(T[13], T[16])
T[9], T[13], T[59] = TOFF(T[9], T[13], T[59])
T[7], T[16], T[58] = TOFF(T[7], T[16], T[58])
T[5], T[18], T[57] = TOFF(T[5], T[18], T[57])
T[37], T[38], T[56] = TOFF(T[37], T[38], T[56])
T[35], T[36], T[55] = TOFF(T[35], T[36], T[55])
U[2], T[17], T[54] = TOFF(U[2], T[17], T[54])
T[33], T[34], T[53] = TOFF(T[33], T[34], T[53])
T[31], T[32], T[52] = TOFF(T[31], T[32], T[52])
T[29], T[30], T[51] = TOFF(T[29], T[30], T[51])
T[8], T[28], T[50] = TOFF(T[8], T[28], T[50])
T[6], T[27], T[49] = TOFF(T[6], T[27], T[49])
T[4], T[26], T[48] = TOFF(T[4], T[26], T[48])
T[24], T[25], T[47] = TOFF(T[24], T[25], T[47])
T[22], T[23], T[46] = TOFF(T[22], T[23], T[46])
U[0], T[21], T[45] = TOFF(U[0], T[21], T[45])
T[19], T[20], T[44] = TOFF(T[19], T[20], T[44])
T[2], T[3], T[43] = TOFF(T[2], T[3], T[43])
T[0], T[1], T[42] = TOFF(T[0], T[1], T[42])
U[1], U[6], T[41] = TOFF(U[1], U[6], T[41])
U[3], U[7], T[40] = TOFF(U[3], U[7], T[40])
U[4], U[5], T[39] = TOFF(U[4], U[5], T[39])
T[13], T[28] = CNOT(T[13], T[28])
T[18], U[6] = CNOT(T[18], U[6])
T[24], T[37] = CNOT(T[24], T[37])
T[18], T[26] = CNOT(T[18], T[26])
T[17], U[3] = CNOT(T[17], U[3])
T[16], T[13] = CNOT(T[16], T[13])
T[16], T[27] = CNOT(T[16], T[27])
U[3], T[3] = CNOT(U[3], T[3])
T[13], T[24] = CNOT(T[13], T[24])
T[17], T[18] = CNOT(T[17], T[18])
T[35], T[22] = CNOT(T[35], T[22])
T[19], T[33] = CNOT(T[19], T[33])
T[31], T[2] = CNOT(T[31], T[2])
T[0], T[29] = CNOT(T[0], T[29])
T[6], T[14] = CNOT(T[6], T[14])
T[5], T[16] = CNOT(T[5], T[16])
U[0], U[3] = CNOT(U[0], U[3])
T[17], T[13] = CNOT(T[17], T[13])
T[17], T[21] = CNOT(T[17], T[21])
T[38], T[3] = CNOT(T[38], T[3])
T[8], T[10] = CNOT(T[8], T[10])
T[9], T[1] = CNOT(T[9], T[1])
U[1], T[35] = CNOT(U[1], T[35])
T[19], U[5] = CNOT(T[19], U[5])
T[5], T[0] = CNOT(T[5], T[0])
T[18], T[16] = CNOT(T[18], T[16])
T[7], T[14] = CNOT(T[7], T[14])
T[13], T[31] = CNOT(T[13], T[31])
T[4], U[0] = CNOT(T[4], U[0])
T[7], T[32] = CNOT(T[7], T[32])
T[9], T[38] = CNOT(T[9], T[38])
T[8], T[25] = CNOT(T[8], T[25])
T[34], T[35] = CNOT(T[34], T[35])
T[0], U[4] = CNOT(T[0], U[4])
T[6], T[1] = CNOT(T[6], T[1])
T[16], U[1] = CNOT(T[16], U[1])
T[18], T[19] = CNOT(T[18], T[19])
T[14], T[17] = CNOT(T[14], T[17])
U[2], T[13] = CNOT(U[2], T[13])
U[0], T[20] = CNOT(U[0], T[20])
T[4], T[12] = CNOT(T[4], T[12])
T[7], U[4] = CNOT(T[7], U[4])
T[8], T[2] = CNOT(T[8], T[2])
U[2], T[34] = CNOT(U[2], T[34])
T[9], T[10] = CNOT(T[9], T[10])
T[6], U[5] = CNOT(T[6], U[5])
T[16], T[0] = CNOT(T[16], T[0])
T[14], T[18] = CNOT(T[14], T[18])
T[13], U[1] = CNOT(T[13], U[1])
U[0], T[1] = CNOT(U[0], T[1])
U[2], T[30] = CNOT(U[2], T[30])
T[4], T[23] = CNOT(T[4], T[23])
T[7], T[38] = CNOT(T[7], T[38])
T[9], T[36] = CNOT(T[9], T[36])
T[6], T[2] = CNOT(T[6], T[2])
T[8], U[3] = CNOT(T[8], U[3])
T[5], T[34] = CNOT(T[5], T[34])
T[11], T[17] = CNOT(T[11], T[17])
T[0], U[4] = CNOT(T[0], U[4])
T[10], T[18] = CNOT(T[10], T[18])
T[12], T[16] = CNOT(T[12], T[16])
T[13], U[7] = CNOT(T[13], U[7])
U[0], U[5] = CNOT(U[0], U[5])
T[5], T[36] = CNOT(T[5], T[36])
U[2], T[32] = CNOT(U[2], T[32])
T[7], T[30] = CNOT(T[7], T[30])
T[6], U[3] = CNOT(T[6], U[3])
T[9], U[7] = CNOT(T[9], U[7])
T[34], T[35] = CNOT(T[34], T[35])
T[0], T[29] = CNOT(T[0], T[29])
T[18], T[16] = CNOT(T[18], T[16])
T[4], T[12] = CNOT(T[4], T[12])
T[8], T[10] = CNOT(T[8], T[10])
U[0], U[6] = CNOT(U[0], U[6])
T[17], T[13] = CNOT(T[17], T[13])
T[5], T[30] = CNOT(T[5], T[30])
T[38], T[3] = CNOT(T[38], T[3])
T[9], T[32] = CNOT(T[9], T[32])
T[19], T[33] = CNOT(T[19], T[33])
T[7], U[7] = CNOT(T[7], U[7])
T[6], T[14] = CNOT(T[6], T[14])
U[1], T[35] = CNOT(U[1], T[35])
T[8], T[0] = CNOT(T[8], T[0])
T[15], T[18] = CNOT(T[15], T[18])
T[16], T[13] = CNOT(T[16], T[13])
T[4], U[0] = CNOT(T[4], U[0])
T[6], T[25] = CNOT(T[6], T[25])
U[2], U[4] = CNOT(U[2], U[4])
T[24], T[37] = CNOT(T[24], T[37])
T[8], T[23] = CNOT(T[8], T[23])
T[5], T[1] = CNOT(T[5], T[1])
T[31], T[2] = CNOT(T[31], T[2])
U[3], T[3] = CNOT(U[3], T[3])
T[19], U[5] = CNOT(T[19], U[5])
T[7], T[14] = CNOT(T[7], T[14])
T[35], T[22] = CNOT(T[35], T[22])
T[9], T[10] = CNOT(T[9], T[10])
T[15], T[17] = CNOT(T[15], T[17])
T[4], T[0] = CNOT(T[4], T[0])
U[0], T[13] = CNOT(U[0], T[13])
T[8], T[9], T[18] = TOFF(T[8], T[9], T[18])
T[6], T[7], T[17] = TOFF(T[6], T[7], T[17])
T[4], T[5], T[16] = TOFF(T[4], T[5], T[16])
T[2], T[3], T[15] = TOFF(T[2], T[3], T[15])
T[0], T[1], T[14] = TOFF(T[0], T[1], T[14])
U[0], U[2], T[13] = TOFF(U[0], U[2], T[13])
U[1], U[6], T[12] = TOFF(U[1], U[6], T[12])
U[3], U[7], T[11] = TOFF(U[3], U[7], T[11])
U[4], U[5], T[10] = TOFF(U[4], U[5], T[10])
U[7], U[4] = CNOT(U[7], U[4])
U[0], U[3] = CNOT(U[0], U[3])
U[0], U[5] = CNOT(U[0], U[5])
U[5], T[0] = CNOT(U[5], T[0])
U[3], T[2] = CNOT(U[3], T[2])
U[4], T[9] = CNOT(U[4], T[9])
U[1], U[2] = CNOT(U[1], U[2])
U[2], T[5] = CNOT(U[2], T[5])
U[2], T[9] = CNOT(U[2], T[9])
U[2], T[3] = CNOT(U[2], T[3])
U[4], T[1] = CNOT(U[4], T[1])
U[4], T[7] = CNOT(U[4], T[7])
U[1], U[6] = CNOT(U[1], U[6])
U[1], U[0] = CNOT(U[1], U[0])
U[3], T[0] = CNOT(U[3], T[0])
U[7], U[1] = CNOT(U[7], U[1])
U[0], T[6] = CNOT(U[0], T[6])
U[1], T[7] = CNOT(U[1], T[7])
U[0], T[4] = CNOT(U[0], T[4])
U[3], U[4] = CNOT(U[3], U[4])
U[6], U[5] = CNOT(U[6], U[5])
U[5], U[2] = CNOT(U[5], U[2])
U[4], U[2] = CNOT(U[4], U[2])
U[0], U[3] = CNOT(U[0], U[3])
U[5], T[8] = CNOT(U[5], T[8])
U[3], T[8] = CNOT(U[3], T[8])
U[1], T[3] = CNOT(U[1], T[3])
U[5], T[6] = CNOT(U[5], T[6])
U[6], T[4] = CNOT(U[6], T[4])
U[2], U[1] = CNOT(U[2], U[1])
U[6], U[4] = CNOT(U[6], U[4])
return S
由于比特运算,所以 S 盒代码代码很长。
密钥扩展实现。
这一部分实现使用的是Jaques S, Naehrig M, Roetteler M, et al. Implementing grover oracles for quantum key search on aes and lowmc [J]. 2019. 给出的in-place结构。
# 密钥扩展 生成11轮子密钥
def key_expansion(key_qubits):
round_keys = [[] for _ in range(11)] # 创建11轮子密钥的二维列表
round_keys[0] = key_qubits.copy() # 第一轮子密钥
# 剩下10轮子密钥 循环生成
for i in range(10):
w0 = key_qubits[:32]
w1 = key_qubits[32:64]
w2 = key_qubits[64:96]
w3 = key_qubits[96:128]
old_w3 = w3.copy()
# w3 循环左移1位 用swap实现
for j in range(8):
w3[j], w3[j+8] = SWAP(w3[j], w3[j+8])
w3[j+8], w3[j+16] = SWAP(w3[j+8], w3[j+16])
w3[j+16], w3[j+24] = SWAP(w3[j+16], w3[j+24])
# S盒 字节代换
T = [0] * 68 * 4 # 可通过取消计算 减少比特消耗
for j in range(4):
w3[8*j:8*j+8] = s_box(w3[8*j:8*j+8], T[68*j:68*j+68])
# w3与RC逐位异或
for j in range(32):
if (RC[i] >> j) & 1 == 1: # 手动判断
w3[31-j] = NOT(w3[31-j])
# 异或生成w4 w5 w6 w7
w4 = [0] * 32
w5 = [0] * 32
w6 = [0] * 32
w7 = [0] * 32
for j in range(32):
_, w4[j] = CNOT(w0[j], w3[j])
_, w5[j] = CNOT(w1[j], w4[j])
_, w6[j] = CNOT(w2[j], w5[j])
_, w7[j] = CNOT(old_w3[j], w6[j])
key_qubits = w4 + w5 + w6 + w7
round_keys[i+1] = key_qubits.copy() # 存储当前轮次的密钥
return round_keys
行移位实现。
这一步可以使用SWAP门实现,即等于3个CNOT门。后续也可以通过“换线”等高级操作来实现。
使用比特表示 AES 的运算矩阵,如下所示。
0-7 32-39 64-71 96-103
8-15 40-47 72-79 104-111
16-23 48-55 80-87 112-119
24-31 56-63 88-95 120-127
# 行移位 输入128bit
def shift_rows(X):
# 104-111 与 8-15 交换, 8-15 与 40-47 交换, 40-47 与 72-79 交换
for i in range(8):
X[104+i], X[8+i] = SWAP(X[104+i], X[8+i])
X[8+i], X[40+i] = SWAP(X[8+i], X[40+i])
X[40+i], X[72+i] = SWAP(X[40+i], X[72+i])
# 16-23 与 80-87 交换, 48-55 与 112-119 交换
for i in range(8):
X[16+i], X[80+i] = SWAP(X[16+i], X[80+i])
X[48+i], X[112+i] = SWAP(X[48+i], X[112+i])
# 24-31 与 120-127 交换, 120-127 与 88-95 交换, 88-95 与 56-63 交换
for i in range(8):
X[24+i], X[120+i] = SWAP(X[24+i], X[120+i])
X[120+i], X[88+i] = SWAP(X[120+i], X[88+i])
X[88+i], X[56+i] = SWAP(X[88+i], X[56+i])
return X
列混淆实现。
同样使用的是Huang论文中的实现方法。
代码如下:
# 列混淆 输入32bit 分4组
def mix_columns(X):
X[7], X[23] = CNOT(X[7], X[23])
X[6], X[22] = CNOT(X[6], X[22])
X[5], X[21] = CNOT(X[5], X[21])
X[4], X[20] = CNOT(X[4], X[20])
X[3], X[19] = CNOT(X[3], X[19])
X[2], X[18] = CNOT(X[2], X[18])
X[1], X[17] = CNOT(X[1], X[17])
X[0], X[16] = CNOT(X[0], X[16])
X[15], X[31] = CNOT(X[15], X[31])
X[14], X[30] = CNOT(X[14], X[30])
X[13], X[29] = CNOT(X[13], X[29])
X[12], X[28] = CNOT(X[12], X[28])
X[11], X[27] = CNOT(X[11], X[27])
X[10], X[26] = CNOT(X[10], X[26])
X[9], X[25] = CNOT(X[9], X[25])
X[8], X[24] = CNOT(X[8], X[24])
X[7], X[15] = CNOT(X[7], X[15])
X[6], X[14] = CNOT(X[6], X[14])
X[5], X[13] = CNOT(X[5], X[13])
X[4], X[12] = CNOT(X[4], X[12])
X[3], X[11] = CNOT(X[3], X[11])
X[2], X[10] = CNOT(X[2], X[10])
X[1], X[9] = CNOT(X[1], X[9])
X[0], X[8] = CNOT(X[0], X[8])
X[23], X[31] = CNOT(X[23], X[31])
X[22], X[30] = CNOT(X[22], X[30])
X[21], X[29] = CNOT(X[21], X[29])
X[20], X[28] = CNOT(X[20], X[28])
X[19], X[27] = CNOT(X[19], X[27])
X[18], X[26] = CNOT(X[18], X[26])
X[17], X[25] = CNOT(X[17], X[25])
X[16], X[24] = CNOT(X[16], X[24])
X[8], X[3] = CNOT(X[8], X[3])
X[8], X[4] = CNOT(X[8], X[4])
X[8], X[6] = CNOT(X[8], X[6])
X[15], X[6] = CNOT(X[15], X[6])
X[14], X[5] = CNOT(X[14], X[5])
X[13], X[4] = CNOT(X[13], X[4])
X[12], X[3] = CNOT(X[12], X[3])
X[11], X[2] = CNOT(X[11], X[2])
X[10], X[1] = CNOT(X[10], X[1])
X[9], X[0] = CNOT(X[9], X[0])
X[8], X[7] = CNOT(X[8], X[7])
X[23], X[14] = CNOT(X[23], X[14])
X[22], X[13] = CNOT(X[22], X[13])
X[21], X[12] = CNOT(X[21], X[12])
X[20], X[11] = CNOT(X[20], X[11])
X[19], X[10] = CNOT(X[19], X[10])
X[18], X[9] = CNOT(X[18], X[9])
X[17], X[8] = CNOT(X[17], X[8])
X[16], X[15] = CNOT(X[16], X[15])
X[31], X[7] = CNOT(X[31], X[7])
X[30], X[6] = CNOT(X[30], X[6])
X[29], X[5] = CNOT(X[29], X[5])
X[28], X[4] = CNOT(X[28], X[4])
X[27], X[3] = CNOT(X[27], X[3])
X[26], X[2] = CNOT(X[26], X[2])
X[25], X[1] = CNOT(X[25], X[1])
X[24], X[0] = CNOT(X[24], X[0])
X[24], X[22] = CNOT(X[24], X[22])
X[16], X[14] = CNOT(X[16], X[14])
X[24], X[20] = CNOT(X[24], X[20])
X[16], X[12] = CNOT(X[16], X[12])
X[24], X[19] = CNOT(X[24], X[19])
X[16], X[11] = CNOT(X[16], X[11])
X[31], X[22] = CNOT(X[31], X[22])
X[30], X[21] = CNOT(X[30], X[21])
X[29], X[20] = CNOT(X[29], X[20])
X[28], X[19] = CNOT(X[28], X[19])
X[27], X[18] = CNOT(X[27], X[18])
X[26], X[17] = CNOT(X[26], X[17])
X[25], X[16] = CNOT(X[25], X[16])
X[24], X[23] = CNOT(X[24], X[23])
X[7], X[23] = CNOT(X[7], X[23])
X[6], X[22] = CNOT(X[6], X[22])
X[5], X[21] = CNOT(X[5], X[21])
X[4], X[20] = CNOT(X[4], X[20])
X[3], X[19] = CNOT(X[3], X[19])
X[2], X[18] = CNOT(X[2], X[18])
X[1], X[17] = CNOT(X[1], X[17])
X[0], X[16] = CNOT(X[0], X[16])
X[15], X[31] = CNOT(X[15], X[31])
X[14], X[30] = CNOT(X[14], X[30])
X[13], X[29] = CNOT(X[13], X[29])
X[12], X[28] = CNOT(X[12], X[28])
X[11], X[27] = CNOT(X[11], X[27])
X[10], X[26] = CNOT(X[10], X[26])
X[9], X[25] = CNOT(X[9], X[25])
X[8], X[24] = CNOT(X[8], X[24])
X[7], X[15] = CNOT(X[7], X[15])
X[6], X[14] = CNOT(X[6], X[14])
X[5], X[13] = CNOT(X[5], X[13])
X[4], X[12] = CNOT(X[4], X[12])
X[3], X[11] = CNOT(X[3], X[11])
X[2], X[10] = CNOT(X[2], X[10])
X[1], X[9] = CNOT(X[1], X[9])
X[0], X[8] = CNOT(X[0], X[8])
X[23], X[31] = CNOT(X[23], X[31])
X[22], X[30] = CNOT(X[22], X[30])
X[21], X[29] = CNOT(X[21], X[29])
X[20], X[28] = CNOT(X[20], X[28])
X[19], X[27] = CNOT(X[19], X[27])
X[18], X[26] = CNOT(X[18], X[26])
X[17], X[25] = CNOT(X[17], X[25])
X[16], X[24] = CNOT(X[16], X[24])
return X
轮密钥加实现。
这一步只需要 CNOT 门就可以实现。
# 轮密钥加
def add_round_key(state_qubits, key_qubits):
for i in range(128):
_, state_qubits[i] = CNOT(key_qubits[i], state_qubits[i])
return state_qubits
最后就是加密函数和测试代码。
# 加密
def encrypt(plaintext_qubits, key_qubits):
round_keys = key_expansion(key_qubits)
# R0
state_qubits = add_round_key(plaintext_qubits, round_keys[0])
# R1 - R10
for i in range(1, 11):
# 字节代换
T = [0] * 68 * 16
for j in range(16):
state_qubits[8*j:8*j+8] = s_box(state_qubits[8*j:8*j+8], T[68*j:68*j+68])
# 行移位
state_qubits = shift_rows(state_qubits)
# 列混淆
if i != 10:
for j in range(4):
state_qubits[32*j:32*j+32] = mix_columns(state_qubits[32*j:32*j+32])
# 轮密钥加
state_qubits = add_round_key(state_qubits, round_keys[i])
return state_qubits
"""
加密测试用例
"""
def encrypt_test():
try:
# test case 1
plaintext = hex_to_qubits("00112233445566778899AABBCCDDEEFF")
key = hex_to_qubits("2B7E151628AED2A6ABF7158809CF4F3C")
ciphertext = encrypt(plaintext, key)
assert qubits_to_hex(ciphertext) == "8DF4E9AAC5C7573A27D8D055D6E4D64B"
# test case 2
plaintext = hex_to_qubits("34F61A19C754110DA892362BAC078B99")
key = hex_to_qubits("0123456789ABCDEF0123456789ABCDEF")
ciphertext = encrypt(plaintext, key)
assert qubits_to_hex(ciphertext) == "5CFB2FD936BB4F0E372A8246044183E2"
# test case 3
plaintext = hex_to_qubits("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
key = hex_to_qubits("11111111111111111111111111111111")
ciphertext = encrypt(plaintext, key)
assert qubits_to_hex(ciphertext) == "24E08A84E6D1C9FD104A2BEB32D783D5"
# test case 4
plaintext = hex_to_qubits("12345678123456781234567812345678")
key = hex_to_qubits("12345678123456781234567812345678")
ciphertext = encrypt(plaintext, key)
assert qubits_to_hex(ciphertext) == "D7EEEE18C420FAF0DC7DB5CA73A2B817"
# test case 5
plaintext = hex_to_qubits("3243F6A8885A308D313198A2E0370734")
key = hex_to_qubits("2B7E151628AED2A6ABF7158809CF4F3C")
ciphertext = encrypt(plaintext, key)
assert qubits_to_hex(ciphertext) == "3925841D02DC09FBDC118597196A0B32"
except AssertionError:
print("X encrypt test failed X")
else:
print("√ encrypt test passed √")