• Python:SM4


    SM4

    即国家密码管理局发布的无线局域网产品使用的SMS4密码算法
    SM4.0(原名SMS4.0)是中华人民共和国政府采用的一种分组密码标准

    实现

    程序运行说明

    根据上方文档说明:

    • 该算法的分组长度为 128 比特,密钥长度为 128 比特。加密算法与密钥扩展算法都采用 32 轮非线性迭代结构。解密算法与加密算法的结构相同,只是轮密钥 rk 的使用顺序相反,解密轮密钥是加密轮密钥的逆序。
    • 最终调用函数 enc() 即可
    • 程序中注释仅用于验证算法的正确性,不影响最终结果

    参数

    • 输入:十六进制表示的明文字符串(最大长度为128bit即字符串最大长度为16)和十六进制表示的加密密钥字符串mk(最大长度同样为128bit即字符串最大长度为16)
    • 输出:十六进制密文字符串
    • 其余函数及常量请参考上面的官方文档

    代码

    def sbox(a):
        s=['d690e9fecce13db716b614c228fb2c05',
           '2b679a762abe04c3aa44132649860699',
           '9c4250f491ef987a33540b43edcfac62',
           'e4b31ca9c908e89580df94fa758f3fa6',
           '4707a7fcf37317ba83593c19e6854fa8',
           '686b81b27164da8bf8eb0f4b70569d35',
           '1e240e5e6358d1a225227c3b01217887',
           'd40046579fd327524c3602e7a0c4c89e',
           'eabf8ad240c738b5a3f7f2cef96115a1',
           'e0ae5da49b341a55ad933230f58cb1e3',
           '1df6e22e8266ca60c02923ab0d534e6f',
           'd5db3745defd8e2f03ff6a726d6c5b51',
           '8d1baf92bbddbc7f11d95c411f105ad8',
           '0ac13188a5cd7bbd2d74d012b8e5b4b0',
           '8969974a0c96777e65b9f109c56ec684',
           '18f07dec3adc4d2079ee5f3ed7cb3948']
        b=''
        for i in range(4):
            r=int(a[2*i],16)
            c=int(a[2*i+1],16)
            b=b+s[r][c*2:(c+1)*2]
        return int(b,16)
    
    def cl(x,i):#Cycle left
        x='{:032b}'.format(x)
        i=i%32
        x=x[i:]+x[:i]
        return int(x,2)
    
    fk=[int('A3B1BAC6',16),int('56AA3350',16),int('677D9197',16),int('B27022DC',16)]
    ck=[]
    for i in range(32):
        cki=[]
        for j in range(4):
            cki.append('{:02x}'.format(((4*i+j)*7)%256))
        ck.append(int(''.join(cki),16))
    '''
    ck=['00070e15','1c232a31','383f464d','545b6269',
        '70777e85','8c939aa1','a8afb6bd','c4cbd2d9',
        'e0e7eef5','fc030a11','181f262d','343b4249',
        '50575e65','6c737a81','888f969d','a4abb2b9',
        'c0c7ced5','dce3eaf1','f8ff060d','141b2229',
        '30373e45','4c535a61','686f767d','848b9299',
        'a0a7aeb5','bcc3cad1','d8dfe6ed','f4fb0209',
        '10171e25','2c333a41','484f565d','646b7279']
    '''
    def f(x,rk,i):
        return x[i]^t(x[i+1]^x[i+2]^x[i+3]^rk)
    
    def t(x):
        return l(tau(x))
    def t_(x):#t'
        return l_(tau(x))
    
    def tau(a):
        a='{:08x}'.format(a)
        b=sbox(a)
        return b
    
    def l(b):
        c=b^cl(b, 2)^cl(b, 10)^cl(b, 18)^cl(b, 24)
        return c
    def l_(b):#l'
        c=b^cl(b, 13)^cl(b, 23)
        return c
    
    def enc(x,mk):
        if len(x)!=32:
            x=(32-len(x))*'0'+x
        p=[x[:8],x[8:16],x[16:24],x[24:]]
        x=p
        for i in range(len(x)):
            x[i]=int(x[i],16)
        rk=kea(mk, fk, ck)
        for i in range(32):
            #print('rk['+'{:02d}'.format(i)+'] = '+'{:08x}'.format(rk[i]),end='   ')
            x.append(f(x,rk[i],i))
            #print('x['+'{:02d}'.format(i)+'] = '+'{:08x}'.format(x[-1]))
        #print()
        y=x[32:][::-1]
        for i in range(len(y)):
            y[i]='{:08x}'.format(y[i])
        y=''.join(y)
        return y
    
    def kea(mk,fk,ck):#Key extension algorithm
        if len(mk)!=32:
            mk=(32-len(mk))*'0'+mk
        p=[mk[:8],mk[8:16],mk[16:24],mk[24:]]
        mk=p
        for i in range(len(mk)):
            mk[i]=int(mk[i],16)
        k=[]
        for i in range(4):
            k.append(mk[i]^fk[i])
        for i in range(32):
            k.append(k[i]^t_(k[i+1]^k[i+2]^k[i+3]^ck[i]))
        rk=k[4:]
        return rk
    
    if __name__=='__main__':
        p=input('Your plaintext(hex):')
        mk=input('Your encryption key(hex):')
        print()
        y=enc(p, mk)
        print('Ciphertext:',end=(' '))
        for i in range(4):
            print(y[i*8:(i+1)*8],end=' ')
        print()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110

    运行效果

    按照文档中的示例:
    验证时将明文及加密密钥中的空格去掉
    过程参数输出在注释

    • 示例一
      对一组明文用密钥加密一次
      明——文:01234567 89abcdef fedcba98 76543210
      加密密钥:01234567 89abcdef fedcba98 76543210
      并输出轮密钥 rk[i] 与每轮输出状态 x[i]

      最后得到密文:681edf34 d206965e 86b3e94f 536e4246
      过程相关参数以及结果均与文档一致

    • 示例二
      利用相同加密密钥对一组明文反复加密1000000次
      明——文:01234567 89abcdef fedcba98 76543210
      加密密钥:01234567 89abcdef fedcba98 76543210

      得到密文:595298c7 c6fd271f 0402f804 c33d3f66

  • 相关阅读:
    项目管理之生命周期管理
    零基础入门多媒体音频(7)-AAOS audio
    【开发日记】MySQL TIMESTAMP 类型建表异常
    云原生是整个信息化行业的未来,一文彻底搞懂云原生
    3.Octree相关
    java的基础用法和常见错误
    【RocketMQ 一】MQ概述
    二、CANdelaStudio入门-版本介绍
    ME1W隐式增强 增加字段学习
    【电脑使用】iPad or Android快速访问Windows文件
  • 原文地址:https://blog.csdn.net/qq_33439662/article/details/125461587