【答案】交行IT精英-第一题

本文详细介绍了交行IT精英赛第一题的解密算法设计思路,包括left()和right()函数实现,modular_Reduction()与str_xor()功能,以及在加密过程中的关键步骤如left_move()、select_inv()、get_K()和roundd()。通过这些函数处理,实现了密钥计算、位移操作和逆元求解,最终生成密文。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设计思路:

在设计算法之前,我们先编写一些功能模块。

  • 定义函数left()right(),通过参数传递,分别返回参数的first and last
def left(Str):

    return Str[:int(len(Str) / 2)]

def right(Str):

    return Str[int(len(Str) / 2):]
  • LRL⊗R运算即L×R mod RCiF24L×R mod RCi∈F24,我们通过函数modular_Reduction()实现该功能,最后返回四位二进制位
def modular_Reduction(str1, str2, px="10011"):

    # 两个二进制相乘的结果 考虑系数偶数次为0
    res = "00000000"
    for i in range(len(str2)):
        if int(str2[i]) == 1:
            str1_temp = str1
            for j in range(len(str2)-i-1):
                str1_temp = str1_temp+"0"
            res = str_xor(str1=res, str2=str1_temp, len=8)
    # 获得乘积 接下里进行模约减
    for i in range(int(len(res)/2)):
        if int(res[i]) == 0:
            res = res
        else:
            j = len(res) - i - 5
            px_temp = px
            for k in range(j):
                px_temp = px_temp + "0"
            res = str_xor(str1=res, str2=px_temp, len=8)
    return res[-4:] 
  • LRL⊕R运算即LLR按位异或运算,我们通过函数str_xor()实现该功能;
def str_xor(str1, str2, len=4):

    num1 = int(str1, base=2)
    num2 = int(str2, base=2)
    return int2bin(int(bin(num1 ^ num2), 2), len)
  • 由于题目中大多数是八位二进制位,因此十进制转为二进制后当前位数小于8时,我们通过函数int2bin()用0补齐:
def int2bin(n, count=8):

    return "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)])
  • 在求K值过程中,Round的第一步即W<<<3W<<<3,通过函数left_move()实现:
def left_move(Str, n):

    return Str[n:] + Str[:n]
  • SubBytes环节中,有一项求解当前参数在mod p(x)mod p(x)下的逆元,理论上应用扩展欧几里得算法可以求解,但是涉及到F24F24算法难度会有所提升,切考虑到目标参数是四位二进制位,仅有24=1624=16种可能解,因此我们通过函数select_inv()暴力求解:
def select_inv(Str):
    dict = {'0000': '0000', '0001': '0001', '0010': '1001','0011': '1110',
    '0100': '1101','0101': '1011','0110': '0111','0111': '0110',
    '1000': '1111','1001': '0010','1010': '1100','1011': '0101',
    '1100': '1010','1101': '0100','1110': '0100','1111': '1000'}
    return dict[Str]

在六轮加密中,分别用到了密钥K0-K5,因此在正式加密过程中,我们第一步要先求出密钥。利用初始密钥K,通过函数get_K()计算出K0-K5。

def get_K(k):

    w0 = k[:8]
    w1 = k[8:16]
    w2 = k[16:24]
    w3 = k[24:]
    RC1 = "00000011"
    RC2 = "00000110"
    RC3 = "00001100"
    RC4 = "00001011"
    RC5 = "00000101"
    k0 = get_Matrix_K(w0, w1, w2, w3)

    # get K1
    T = left_move(w3, 3)
    T = subBytes(T[:4]) + subBytes(T[4:])
    T = str_xor(T, RC1, len=8)
    w4 = str_xor(w0, T, len=8)
    w5 = str_xor(w1, w4, len=8)
    w6 = str_xor(w2, w5, len=8)
    w7 = str_xor(w3, w6, len=8)
    k1 = get_Matrix_K(w4, w5, w6, w7)

    # get K2
    T = left_move(w7, 3)
    T = subBytes(T[:4]) + subBytes(T[4:])
    T = str_xor(T, RC2, len=8)
    w8 = str_xor(w4, T, len=8)
    w9 = str_xor(w5, w8, len=8)
    w10 = str_xor(w6, w9, len=8)
    w11 = str_xor(w7, w10, len=8)
    k2 = get_Matrix_K(w8, w9, w10, w11)

    # get K3
    T = left_move(w11, 3)
    T = subBytes(T[:4]) + subBytes(T[4:])
    T = str_xor(T, RC3, len=8)
    w12 = str_xor(w8, T, len=8)
    w13 = str_xor(w9, w12, len=8)
    w14 = str_xor(w10, w13, len=8)
    w15 = str_xor(w11, w14, len=8)
    k3 = get_Matrix_K(w12, w13, w14, w15)

    # get K4
    T = left_move(w15, 3)
    T = subBytes(T[:4]) + subBytes(T[4:])
    T = str_xor(T, RC4, len=8)
    w16 = str_xor(w12, T, len=8)
    w17 = str_xor(w13, w16, len=8)
    w18 = str_xor(w14, w17, len=8)
    w19 = str_xor(w15, w18, len=8)
    k4 = get_Matrix_K(w16, w17, w18, w19)

    # get K5
    T = left_move(w19, 3)
    T = subBytes(T[:4]) + subBytes(T[4:])
    T = str_xor(T, RC5, len=8)
    w20 = str_xor(w16, T, len=8)
    w21 = str_xor(w17, w20, len=8)
    w22 = str_xor(w18, w21, len=8)
    w23 = str_xor(w19, w22, len=8)
    k5 = get_Matrix_K(w20, w21, w22, w23)

    return k0, k1, k2, k3, k4, k5

其中函数SubBytes()定义如下:

def subBytes(Str):

    tmp = select_inv(Str)
    x3 = str_xor(str(int(tmp[3], base=2) & 1), "1", len=1)
    x2 = str_xor(str(int(tmp[3], base=2) & 1), str(int(tmp[2], base=2) & 1), len=1)
    x1 = str_xor(str_xor(tmp[0], tmp[1], len=1), str_xor(tmp[2], tmp[3], len=1), len=1)
    x0 = str_xor(str_xor(tmp[1], tmp[2], len=1), str_xor(tmp[0], "1", len=1), len=1)
    return x0 + x1 + x2 + x3

函数get_Matrix_K()定义如下:

def get_Matrix_K(w0, w1, w2, w3):

    K_00 = str_xor(str_xor(modular_Reduction(left(w0), right(w0)), left(w0)), right(w0))
    K_10 = str_xor(str_xor(modular_Reduction(left(w1), right(w1)), left(w1)), right(w1))
    K_01 = str_xor(str_xor(modular_Reduction(left(w2), right(w2)), left(w2)), right(w2))
    K_11 = str_xor(str_xor(modular_Reduction(left(w3), right(w3)), left(w3)), right(w3))
    return K_00, K_01, K_10, K_11

  在该过程中,由于题中规定RCi=xi+3(modx4+x+1)RCi=xi+3(modx4+x+1),即RC1,,RC5RC1,…,RC5固定不变,虽然可以通过代码计算,但是性价比不高,因此直接在代码里人工初始化RC1,,RC5RC1,…,RC5
   获得密钥K0K5K0−K5后,通过函数roundd()分别计算中间变量L1 R1L6 R6L1 R1−L6 R6:

def roundd(l, r, k):

    # SubBytes
    res = subBytes(r[:4]) + subBytes(r[8:12]) + subBytes(r[4:8]) + subBytes(r[12:])

    # MultRoundKey
    mrk00 = str_xor(modular_Reduction(k[0], res[:4], px="10011"), modular_Reduction(k[1], res[8:12], px="10011"), len=4)
    mrk01 = str_xor(modular_Reduction(k[0], res[4:8], px="10011"), modular_Reduction(k[1], res[12:], px="10011"), len=4)
    mrk10 = str_xor(modular_Reduction(k[2], res[:4], px="10011"), modular_Reduction(k[3], res[8:12], px="10011"), len=4)
    mrk11 = str_xor(modular_Reduction(k[2], res[4:8], px="10011"), modular_Reduction(k[3], res[12:], px="10011"), len=4)

    # MixColumns
    mc00 = str_xor(modular_Reduction("0011", mrk00, px="10011"), modular_Reduction("0111", mrk10, px="10011"), len=4)
    mc01 = str_xor(modular_Reduction("0011", mrk01, px="10011"), modular_Reduction("0111", mrk11, px="10011"), len=4)
    mc10 = str_xor(modular_Reduction("0100", mrk00, px="10011"), modular_Reduction("0011", mrk10, px="10011"), len=4)
    mc11 = str_xor(modular_Reduction("0100", mrk01, px="10011"), modular_Reduction("0011", mrk11, px="10011"), len=4)

    # ShiftRows # 变换状态矩阵
    a = mc00 + mc01 + mc11 + mc10

    l1 = r
    r1 = str_xor(l, mc00 + mc11 + mc01 + mc10, len=16)

    return a, l1, r1

  得到L6 R6L6 R6后,整合上面函数为ek,继而得到密文C:

def ek(iv, k):

    K0, K1, K2, K3, K4, K5 = get_K(k)
    L0 = iv[:16]
    R0 = iv[16:]

    # round0
    print("Round 0:")
    A, L1, R1 = roundd(L0, R0, K0)
    print("L1:", L1)
    print("R1:", R1)
    # round1
    print("Round 1:")
    A, L2, R2 = roundd(L1, R1, K1)
    print("L2:", L2)
    print("R2:", R2)
    # round2
    print("Round 2:")
    A, L3, R3 = roundd(L2, R2, K2)
    print("L3:", L3)
    print("R3:", R3)
    # round3
    print("Round 3:")
    A, L4, R4 = roundd(L3, R3, K3)
    print("L4:", L4)
    print("R4:", R4)
    # round4
    print("Round 4:")
    A, L5, R5 = roundd(L4, R4, K4)
    print("L5:", L5)
    print("R5:", R5)
    # round5
    print("Round 5:")
    A, L6, R6 = roundd(L5, R5, K5)
    print("L6:", L6)
    print("R6:", R6)
    return R6 + L6

  Main()中重复上述步骤得到后续密文:

if __name__ == "__main__":
    M = input("Please input M:")
    K = input("Please input K:")
    if len(K) != 32:
        print("Error K!")
    IV = input("Please input IV:")
    if len(IV) != 32:
        print("Error IV!")
    if len(M) == 96:
        M1 = M[:32]
        M2 = M[32:64]
        M3 = M[64:]
        print()
        print("Ek(IV)...")
        ek_IV = ek(IV, K)
        c1 = str_xor(ek_IV, M1, len=32)
        print()
        print("Ek(C1)...")
        ek_c1 = ek(c1, K)
        c2 = str_xor(ek_c1, M2, len=32)
        print()
        print("Ek(C2)...")
        ek_c2 = ek(c2, K)
        c3 = str_xor(ek_c2, M3, len=32)
        print()
        print("C1||C2||C3:", c1, "||", c2, "||", c3)
    elif len(M) == 128:
        M1 = M[:32]
        M2 = M[32:64]
        M3 = M[64:96]
        M4 = M[96:]
        print()
        print("Ek(IV)...")
        ek_IV = ek(IV, K)
        c1 = str_xor(ek_IV, M1, len=32)
        print()
        print("Ek(C1)...")
        ek_c1 = ek(c1, K)
        c2 = str_xor(ek_c1, M2, len=32)
        print()
        print("Ek(C2)...")
        ek_c2 = ek(c2, K)
        c3 = str_xor(ek_c2, M3, len=32)
        print()
        print("Ek(C3)...")
        ek_c3 = ek(c3, K)
        c4 = str_xor(ek_c3, M4, len=32)
        print()
        print("C1||C2||C3||C4:", c1, "||", c2, "||", c3, "||", c4)
    elif len(M) == 160:
        M1 = M[:32]
        M2 = M[32:64]
        M3 = M[64:96]
        M4 = M[96:128]
        M5 = M[128:]
        print()
        print("Ek(IV)...")
        ek_IV = ek(IV, K)
        c1 = str_xor(ek_IV, M1, len=32)
        print()
        print("Ek(C1)...")
        ek_c1 = ek(c1, K)
        c2 = str_xor(ek_c1, M2, len=32)
        print()
        print("Ek(C2)...")
        ek_c2 = ek(c2, K)
        c3 = str_xor(ek_c2, M3, len=32)
        print()
        print("Ek(C3)...")
        ek_c3 = ek(c3, K)
        c4 = str_xor(ek_c3, M4, len=32)
        print()
        print("Ek(C4)...")
        ek_c4 = ek(c4, K)
        c5 = str_xor(ek_c4, M5, len=32)
        print()
        print("C1||C2||C3||C4||C5:", c1, "||", c2, "||", c3, "||", c4, "||", c5)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值