python Crypto.Cipher.AES 每次加密的结果是不确定的?

2015-10-04 22:21:08 +08:00
 raiz
def aesEncrypt(text, secKey):
    pad = 16 - len(text) % 16
    text = text + pad * b' '  #  chr(pad)
    encryptor = AES.new(secKey, 2, '0102030405060708')   
    ciphertext = encryptor.encrypt(text)  # 加密 text
    print(ciphertext)  
    ciphertext = base64.b64encode(ciphertext)  #
    # return bytes.decode(ciphertext)
    return ciphertext

发现相同的 text , secKey 参数,多次运行 aesEncrypt(), print(ciphertext) 的结果不一样, 这不会是 aes 的特性吧??

5576 次点击
所在节点    Python
14 条回复
xupefei
2015-10-04 22:25:39 +08:00
除了你说的那些参数以外,还有个 initialization vector ,就是常说的 iv 。这个 iv 一半是加密时随即产生的。 iv 不同,加密结果不同。
xupefei
2015-10-04 22:29:03 +08:00
@xupefei *一般是加密时随机产生的。
pynix
2015-10-04 22:36:27 +08:00
这大概是 GFW 拿 ase256 没办法的原因
neilp
2015-10-04 22:52:58 +08:00
py 的 aes 没用过,所以代码没细看。 但是就 aes 算法本身来讲,同一个文本加密的密文一定是一样的。 除非你的 iv 设置的不一样.
如果加密的文本大于一个块, 那么加密得到的密文 还取决于 不同块之间 iv 的 重复利用方式。 也就是所谓的 cipher mode. 即使所谓的 ecb , cbc, cfb 。 以 cbc 为例,加密第一块时, iv 由用户指定,如果用户没指定, 多数平台的 aes 实现会用全零的块作为默认 iv. 在加密第二块时会用第一块加密出来的密文作为新的 iv. 并以此类推。

楼主的情况应该不涉及多块的问题, 所以找找看有没有设置 iv 的接口, 给个固定的 iv 试试。

火车上用手机发的帖子,请海涵
raiz
2015-10-04 23:01:34 +08:00
@xupefei 意思是说 '0102030405060708' 只是 iv 的一半,另一半具有随机性??
> def new(key, *args, **kwargs):
"""Create a new AES cipher

:Parameters:
key : byte string
The secret key to use in the symmetric cipher.
It must be 16 (*AES-128*), 24 (*AES-192*), or 32 (*AES-256*) bytes long.
:Keywords:
mode : a *MODE_** constant
The chaining mode to use for encryption or decryption.
Default is `MODE_ECB`.
IV : byte string
The initialization vector to use for encryption or decryption.
"""

不过,以上的实验室 python3.4 下的, 我又在 python27 底下做相同的实验,发现结果是不变的
xupefei
2015-10-04 23:07:55 +08:00
@raiz
Parameters:
mode (a MODE_* constant) - The chaining mode to use for encryption or decryption. *Default is MODE_ECB.*
IV (byte string) - The initialization vector to use for encryption or decryption.
*It is ignored for MODE_ECB and MODE_CTR.*
raiz
2015-10-04 23:08:48 +08:00
@neilp 谢谢。 AES.new() 的 doc string 显示 AES.new(secKey, 2, '0102030405060708')第三个参数 就是 iv, 所以我认为应该是确定的结果才对, python2.7 下做的实验输出是确定的,前面的实验是 python3.4 下做的,结果是几种可能性中随机的一种,很怪
xupefei
2015-10-04 23:09:50 +08:00
@xupefei 啊,没注意原来 LZ 制定了 MODE_CBC 模式。请无视上面的回复。
我没看过 py 实现的源码,无法给出答案了。
raiz
2015-10-04 23:11:07 +08:00
@xupefei MODE_CBC = 2 ,所以这里是 CBC 模式, IV 没有忽略
fengdra
2015-10-04 23:41:27 +08:00
我这每次执行都是一样的,你是不是同一个 encryptor 用了多次?密文还依赖于这个 encryptor 的历史
raiz
2015-10-04 23:48:08 +08:00
@fengdra 哦哦哦 我知道问题出在哪了 是我的输入是 json.dump() 一个字典,字典的排序是随机的,所以会变。 关注点一直没移开加密过程,没去看输入。 谢谢你
twor2
2015-10-05 01:49:42 +08:00
Pasco
2015-10-05 18:43:09 +08:00
是这样的,解密的结果是对的不就好了~
raiz
2015-10-06 10:22:33 +08:00
@Pasco 是这样,我那时是在调试一个 api , 原来是 python27 的代码,改为 python3 之后响应不对,所以特意设置相同的输入,观察输出的区别,后来发现是 编码转换的用法不同导致。而之所以 python27 每次输出固定是因为 dict 的顺序总是固定的,而 python34 是随机的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/225625

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX