• Python Crypto AES加密模式踩坑记


    前言

      demo code使用的lib 版本为 :pycryptodome 3.10.1
      写了一小段AES加密的demo code, 运行起来错误不断,花费了半天时间逐一解决。分享出来,希望能对大家有所帮助!
      同时,关于AES 加密模式的说明可以参考这篇文章,讲的很清晰:https://blog.csdn.net/slslslyxz/article/details/111232040

    问题一:decrypt() cannot be called after encrypt()

      运行时报告:Exception has occurred: TypeError, decrypt() cannot be called after encrypt()
      出现这个问题的原因,在encrypt / decrypt函数中有说明,由于encrypt / decrypt是stateful,不能用加密的对象再去解蜜; 
      A cipher object is stateful: once you have encrypted a message , you cannot encrypt (or decrypt) another message using the same object. 

      解决方法就是重新new一个对象用来处理解密

    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad
    from Crypto.Util.Padding import unpad
    
    key=b'1234567890123456'cipher=AES.new(key,AES.MODE_CBC)
    
    text=b'secret text'
    padtext=pad(text,16,style='pkcs7')
    cipherText=cipher.encrypt(padtext)
    print(padtext)
    print(cipherText)
    
    plaintext=cipher.decrypt(cipherText)  #can't use same object to decrypt
    print(plaintext)
    

     问题二:Data must be padded to 16 byte boundary in CBC mode

      这个是AES加密算法模式导致的。 AES只能以Block的模式加密, 且Block大小为16Byte.  加密的key大小为:16,24,32,对应到128bit, 192bit, 256bit加密

      # Size of a data block (in bytes)
      block_size = 16
      # Size of a key (in bytes)
      key_size = (16, 24, 32)
      解决方法就是将需要加密的数据Padding到16Byte的整数倍; 
    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad
    from Crypto.Util.Padding import unpad
    
    key=b'1234567890123456'cipher=AES.new(key,AES.MODE_CBC)
    
    text=b'secret text'
    padtext=pad(text,16,style='pkcs7')
    cipherText=cipher.encrypt(padtext)
    print(padtext)
    print(cipherText)
    
    decrypter=AES.new(key,AES.MODE_CBC)
    plaintext=decrypter.decrypt(cipherText)
    print(plaintext)
    

    问题三:每次加密得到的结果不一样

      这个问题的原因是AES CBC_MODE需要初始化向量。如果不指定初始化向量,则AES会在初始化时随机生成一个。这样就导致了每次加密得到的密文不一样;
            解决方法就是指定一个固定的初始化向量,同时也要注意解密时也使用同样的向量。

    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad
    from Crypto.Util.Padding import unpad
    
    key=b'1234567890123456'
    iv=b'abcdefghijklmnop'
    cipher=AES.new(key,AES.MODE_CBC,iv)
    
    text=b'secret text'
    padtext=pad(text,16,style='pkcs7')
    cipherText=cipher.encrypt(padtext)
    print(padtext)
    print(cipherText)
    
    decrypter=AES.new(key,AES.MODE_CBC,iv)
    plaintext=decrypter.decrypt(cipherText)
    print(plaintext)

    问题四:解密无法得到原始明文数据

      上面的程序运行出来发现后面还是跟着之前Paddding的数据,这是因为decrypt并不会将Padding的数据去掉。
      解决办法就是将解密的数据再进行unpad得到原始数据

    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad
    from Crypto.Util.Padding import unpad
    
    key=b'1234567890123456'
    iv=b'abcdefghijklmnop'
    cipher=AES.new(key,AES.MODE_CBC,iv)
    
    text=b'secret text'
    padtext=pad(text,16,style='pkcs7')
    cipherText=cipher.encrypt(padtext)
    print(padtext)
    print(cipherText)
    
    decrypter=AES.new(key,AES.MODE_CBC,iv)
    plaintext=decrypter.decrypt(cipherText)
    unpadtext=unpad(plaintext,16,'pkcs7')
    print(plaintext)
    print(unpadtext)

    经过上面的一系列的错误修正后,运行程序后可以得到正确的结果了

    原始数据:secret text
    padding数据:b'secret textx05x05x05x05x05'
    加密数据:b'xb0xb0xd4hxbcx85xd3xd1>x13xdfxa7AE(8'
    解密后数据:b'secret text'


     

  • 相关阅读:
    3、看源码MVC中的Controllr的Json方法
    2、MVC+IOC容器+ORM结合
    1、看源码MVC如何实例化控制器?
    6、UnityConfig实现AOP
    5、动态代理AOP实现-DynamicProxy模式
    1、面向切面编程
    通过js看类似C#中的回掉
    C#新开一个线程取到数据,如何更新到主线程UI上面
    2.C#自定义Attribute
    1.C#中几个简单的内置Attribute
  • 原文地址:https://www.cnblogs.com/linuxcat/p/14494630.html
Copyright © 2020-2023  润新知