我最近碰到the following code sample来到了一个SHA256 HMAC认证和验证与加密AES-256 CBC文件:HMAC-SHA256使用AES-256 CBC模式
aes_key, hmac_key = self.keys
# create a PKCS#7 pad to get us to `len(data) % 16 == 0`
pad_length = 16 - len(data) % 16
data = data + (pad_length * chr(pad_length))
# get IV
iv = os.urandom(16)
# create cipher
cipher = AES.new(aes_key, AES.MODE_CBC, iv)
data = iv + cipher.encrypt(data)
sig = hmac.new(hmac_key, data, hashlib.sha256).digest()
# return the encrypted data (iv, followed by encrypted data, followed by hmac sig):
return data + sig
因为在我的情况下, ,我加密更不是一个字符串,而是一个相当大的文件,我修改了代码执行以下操作:
aes_key, hmac_key = self.keys
iv = os.urandom(16)
cipher = AES.new(aes_key, AES.MODE_CBC, iv)
with open('input.file', 'rb') as infile:
with open('output.file', 'wb') as outfile:
# write the iv to the file:
outfile.write(iv)
# start the loop
end_of_line = True
while True:
input_chunk = infile.read(64 * 1024)
if len(input_chunk) == 0:
# we have reached the end of the input file and it matches `% 16 == 0`
# so pad it with 16 bytes of PKCS#7 padding:
end_of_line = True
input_chunk += 16 * chr(16)
elif len(input_chunk) % 16 > 0:
# we have reached the end of the input file and it doesn't match `% 16 == 0`
# pad it by the remainder of bytes in PKCS#7:
end_of_line = True
input_chunk_remainder = 16 - (len(input_chunk) & 16)
input_chunk += input_chunk_remainder * chr(input_chunk_remainder)
# write out encrypted data and an HMAC of the block
outfile.write(cipher.encrypt(input_chunk) + hmac.new(hmac_key, data,
hashlib.sha256).digest())
if end_of_line:
break
简单地说,这种读取64KB的块输入文件的时间和加密这些块使用加密数据的SHA-256生成HMAC,并附加该HMAC每块后。解密将通过读取64KB + 32B块并计算前64KB的HMAC并将其与占用块中最后32个字节的SHA-256总数进行比较来实现。
这是使用HMAC的正确方法吗?它是否确保数据未经修改且使用正确密钥解密的安全性和身份验证?
仅供参考,AES和HMAC密钥都是由通过SHA-512运行输入文本,然后再通过bcrypt,然后再通过SHA-512生成的相同密码派生的。然后将最终SHA-512的输出分成两个块,一个用于AES密码,另一个用于HMAC。
对于点编号1,如果密码不正确,我需要在解密数据时很快失败。所以,我基本上应该在进入循环之前创建一个HMAC实例,然后使用update将输入数据转储到HMAC实例中,然后在每个块之后调用digest来存储散列,对吧?然后,每个块将成为它之前的数据的累积散列,从而确保不仅一个块没有被篡改,而且还确保整个文件是有序的并与散列匹配。这是否解决了这个问题? – 2013-02-23 00:03:41
对于点编号2,我使用盐作为我的密钥派生。上面的代码过于简化,但salt会与头文件一起存储以提高安全性。我还使用盐中的高迭代次数来增加安全性,使得难以强制密码。 – 2013-02-23 00:05:52
对于最后一点,我需要找到一种解决此问题的方法,因为我将通过网络套接字读取文件。 – 2013-02-23 00:06:46