我需要一个相当简单的Python文件加密/解密器,经过一些研究后,我决定使用tye pynacl库以块读取文件,将它们写回,最后使用Blake2b为文件生成一个签名。每个文件都使用一个唯一的密钥加密,该密钥将沿着加密文件的一侧分发,文件密钥RSA使用预共享密钥对加密,整个消息与ECDSA签署,以验证它来自我。
加密/解密示例代码:
import base64
import struct
import nacl.secret
import nacl.utils
import nacl.hashlib
import nacl.hash
BUFFER_SIZE = 4 * (1024 * 1024)
def read_file_blocks(file, extra_bytes=0):
while True:
data = file.read(BUFFER_SIZE + extra_bytes)
if not data:
break
yield data
def hmac_file(file, key):
blake = nacl.hashlib.blake2b(key=key)
with open(file, 'rb') as in_file:
for block in read_file_blocks(in_file):
blake.update(block)
return blake.hexdigest()
def encrypt_archive(archive_name, encrypted_name):
key = nacl.utils.random(nacl.secret.SecretBox.KEY_SIZE)
#Use 4 bytes less than the nonce size to make room for the block counter
nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE - 4)
block_num = 0
box = nacl.secret.SecretBox(key)
with open(archive_name, 'rb') as in_file, open(encrypted_name, 'wb') as out_file:
for data in read_file_blocks(in_file):
#Append the block counter to the nonce, so each block has a unique nonce
block_nonce = nonce + struct.pack(">I", block_num)
block = box.encrypt(data, block_nonce)
out_file.write(block.ciphertext)
block_num += 1
hmac_key = nacl.hash.sha256(key + nonce, encoder=nacl.encoding.RawEncoder)
output = {}
output['key'] = base64.b64encode(key + nonce)
output['signature'] = hmac_file(encrypted_name, hmac_key)
return output
def decrypt_archive(encrypted_name, archive_name, key_info):
key_bytes = base64.b64decode(key_info['key'])
key = key_bytes[:nacl.secret.SecretBox.KEY_SIZE]
nonce = key_bytes[nacl.secret.SecretBox.KEY_SIZE:]
extra_bytes = nacl.secret.SecretBox.MACBYTES
hmac_key = nacl.hash.sha256(key_bytes, encoder=nacl.encoding.RawEncoder)
hmac = hmac_file(encrypted_name, hmac_key)
if hmac != key_info['signature']:
print('hmac mismatch')
return
block_num = 0
box = nacl.secret.SecretBox(key)
with open(encrypted_name, 'rb') as in_file, open(archive_name, 'wb') as out_file:
# nacl adds a MAC to each block, when reading the file in, this needs to be taken into account
for data in read_file_blocks(in_file, extra_bytes=extra_bytes):
block_nonce = nonce + struct.pack(">I", block_num)
block = box.decrypt(data, block_nonce)
out_file.write(block)
block_num += 1
key_info = encrypt_archive("C:\\temp\\test.csv", "C:\\temp\\test.enc")
print(key_info)
decrypt_archive("C:\\temp\\test.enc", "C:\\temp\\test.enc.csv", key_info)除了一般的错误,我所做的两件事我并不完全确定是正确的:
发布于 2020-03-02 00:57:59
代码部分下的代码/协议注释。
def read_file_blocks(file, extra_bytes=0):
while True:
data = file.read(BUFFER_SIZE + extra_bytes)至少要指定使用额外字节的原因,并记录extra-bytes参数的含义。
def hmac_file(file, key):为什么要遍历整个文件,然后只释放读取的字节来执行HMAC?你刚刚处理了内存中的所有块!为什么blake2b而不是一个更常见的SHA-2散列呢?
#Use 4 bytes less than the nonce size to make room for the block counter我敢打赌这不是必需的,毫无疑问,柜台已经包括在内了。也许你可以指出一个特定的要求,包括一个块计数器每4MiB?
hmac_key = nacl.hash.sha256(key + nonce, encoder=nacl.encoding.RawEncoder)至少使用HMAC代替哈希来派生密钥,这是一个可怜的人的KDF。
output['key'] = base64.b64encode(key + nonce)抱歉,输出什么?钥匙?
output['signature'] = hmac_file(encrypted_name, hmac_key)CryptoBox使用经过验证的密码。根本不需要再来一次。
算法详细信息: 加密: Salsa20流cipher身份验证: Poly1305 MAC
https://codereview.stackexchange.com/questions/220536
复制相似问题