xst*_*ter 10 python cryptography aes encryption-symmetric pycrypto
我正在编写一段代码来使用对称加密来加密文本.但它没有以正确的结果回归......
from Crypto.Cipher import AES
import os
crypto = AES.new(os.urandom(32), AES.MODE_CTR, counter = lambda : os.urandom(16))
encrypted = crypto.encrypt("aaaaaaaaaaaaaaaa")
print crypto.decrypt(encrypted)
Run Code Online (Sandbox Code Playgroud)
这里,解密的文本与原始文本不同.
我对密码学的了解并不多,所以请耐心等待.我理解CTR模式需要一个"计数器"功能来每次提供一个随机计数器,但为什么当我的密钥是32字节时它需要它是16个字节并且它坚持我的消息也是16字节的倍数?这是正常的吗?
我猜它没有回到原始消息,因为计数器在加密和解密之间发生了变化.但那么,它究竟应该在理论上如何运作呢?我究竟做错了什么?无论如何,我被迫回到欧洲央行,直到我弄明白:(
Ale*_*lli 12
在counter必须返回相同的解密,因为它没有加密,你直觉,所以,一个(不安全AT ALL)的方式来做到这一点是:
>>> secret = os.urandom(16)
>>> crypto = AES.new(os.urandom(32), AES.MODE_CTR, counter=lambda: secret)
>>> encrypted = crypto.encrypt("aaaaaaaaaaaaaaaa")
>>> print crypto.decrypt(encrypted)
aaaaaaaaaaaaaaaa
Run Code Online (Sandbox Code Playgroud)
CTR是一个分组密码,所以看起来让你感到惊讶的"16-at-a-time"约束非常自然.
当然,在每次通话中返回相同值的所谓"计数器" 是非常不安全的.做得不好,例如...:
import array
class Secret(object):
def __init__(self, secret=None):
if secret is None: secret = os.urandom(16)
self.secret = secret
self.reset()
def counter(self):
for i, c in enumerate(self.current):
self.current[i] = c + 1
if self.current: break
return self.current.tostring()
def reset(self):
self.current = array.array('B', self.secret)
secret = Secret()
crypto = AES.new(os.urandom(32), AES.MODE_CTR, counter=secret.counter)
encrypted = crypto.encrypt(16*'a' + 16*'b' + 16*'c')
secret.reset()
print crypto.decrypt(encrypted)
Run Code Online (Sandbox Code Playgroud)
AES是一种分组密码:它是一种算法(更精确地说是一对算法),它采用密钥和消息块,并对该块进行加密或解密。无论密钥大小如何,块的大小始终为16个字节。
点击率是一种运作方式。这是一对基于块密码的算法,用于生成流密码,该流密码可以加密和解密任意长度的消息。
CTR通过将连续的消息块与计数器连续值的加密相结合来工作。计数器的大小必须为一个块,以便它是块密码的有效输入。
'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'。但是,如果密钥被多次使用,则第二条消息将不允许重用第一条消息使用的任何计数器值,而最简单的方法是确保随机生成初始计数器值(2 ^ 128)空间,发生碰撞的机会可以忽略不计)。通过让调用者选择一个计数器功能,PyCrypto库为您提供了很多绳索来吊死自己。您不仅应该使用Crypto.Util.Counter,如文档所述那样“获得更好的性能”,还应该使用,因为构建安全的东西要比自己想出的东西容易。即使这样,也要小心使用随机的初始值,这不是默认值。
import binascii
import os
from Crypto.Cipher import AES
from Crypto.Util import Counter
def int_of_string(s):
return int(binascii.hexlify(s), 16)
def encrypt_message(key, plaintext):
iv = os.urandom(16)
ctr = Counter.new(128, initial_value=int_of_string(iv))
aes = AES.new(key, AES.MODE_CTR, counter=ctr)
return iv + aes.encrypt(plaintext)
def decrypt_message(key, ciphertext):
iv = ciphertext[:16]
ctr = Counter.new(128, initial_value=int_of_string(iv))
aes = AES.new(key, AES.MODE_CTR, counter=ctr)
return aes.decrypt(ciphertext[16:])
Run Code Online (Sandbox Code Playgroud)