我有两个函数:由AES实现的加密/解密
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
DEFAULT_MODE = modes.ECB()
def encrypt(data, key):
encryptor = Cipher(algorithms.AES(key), DEFAULT_MODE, backend=default_backend()).encryptor()
return encryptor.update(data) + encryptor.finalize()
def decrypt(data, key):
if len(data) == 0 or len(data)%16 != 0:
raise ValueError
decryptor = Cipher(algorithms.AES(key), DEFAULT_MODE, backend=default_backend()).decryptor()
return decryptor.update(data)
代码可按以下方式执行:
>>> encrypt(b'a'*16, b'I_got_one_key_in_32bytes_length.')
'\xab\x07\x9d\xa0\xf0\xa0g\x9ae\xd9\x10\x9e\xea2\xb4\x17'
>>> decrypt(b'\xab\x07\x9d\xa0\xf0\xa0g\x9ae\xd9\x10\x9e\xea2\xb4\x17', b'I_got_one_key_in_32bytes_length.')
'aaaaaaaaaaaaaaaa'
这里的任务是change the mode
从欧洲央行到其他国家,比如说GCM。你知道吗
DEFAULT_MODE = modes.GCM('iv')
代码仍可以在以下位置执行:
>>> encrypt(b'a'*16, b'I_got_one_key_in_32bytes_length.')
'Y5y\xbe\xeeK\xb9\x10\xcdf\x99\xa6\x1d\xf2\xa0\x1e'
>>> decrypt(b'Y5y\xbe\xeeK\xb9\x10\xcdf\x99\xa6\x1d\xf2\xa0\x1e', b'I_got_one_key_in_32bytes_length.')
'aaaaaaaaaaaaaaaa'
然而,由于这些加密/解密功能已经广泛使用了一段时间,因此提出了一个问题:如何在不影响原始加密数据的情况下迁移到新模式?
PS:我的想法是这样的:如果可能的话,在GCM模式下解密数据,否则在ECB模式下解密;然后在GCM模式下加密所有数据。但是,这个想法行不通,因为我没有办法提出错误。通过这种方法,可以知道加密数据的AES模式吗?
def decrypt(data, key):
try:
# decrypt data by key in GCM
except GCMDecryptFailedError:
# decrypt data by key in ECB
return decrypted_data
这里的错误是直接使用加密算法,而不指定特定的协议和协议版本号。幸运的是,有办法解决这个问题,并指定一个特定的协议。你知道吗
密码学使用的技巧之一是,不可能随机生成特定内容,因为生成特定值的几率每降低一位。所以你能做的就是给你的密文加上前缀,比如128/16字节的比特值。在密文开始时生成该值的概率是2到128的幂次方(如果消息本身不是随机的,则对于特定密钥的概率较小)。换言之,这种可能性低至猜测一个AES-128密钥;我们称这种可能性为“可忽略不计”。这个技巧当然取决于ECB加密的输出,使用的随机密钥也是随机的。你知道吗
但是,将来可能需要包含一个或多个字节作为协议版本指示符。因此,您可以发送例如字节值
01
作为新版本,然后是16字节的魔术值,接着是GCM的随机nonce、密文和GCM身份验证标记(如果GCM密文中还没有包含)。一旦您摆脱了协议的ECB版本(消息中未指明的版本00
),那么您就可以摆脱魔法,将消息的协议头中的16个字节重新用于协议2或更高版本。你知道吗如果您想生成一个漂亮的魔术,那么您可以使用任何类型的16字节字符串,比如ASCII中的
"Protocol 1, GCM:"
(不带引号)。如果要使用更大的字符串,还可以使用哈希最左边的128位。你知道吗所以一开始你的逻辑是,在伪代码中:
当然,这仍然是一个非常基本的协议。但至少你以后可以改变它。您可能希望查看更完整的协议规范,例如Fernet、CMS或-当然-TLS,而不仅仅是AES-GCM。你知道吗
无论你做什么:在一个单独的文档中写下你的协议,并从你的代码中引用它。您可以在源代码中引用您的简单协议,以便于查找。你知道吗
相关问题 更多 >
编程相关推荐