Python 中 cryptography.hazmat 的 AES 128 CTR 随机访问解密
AES 128 CTR random access decryption with cryptography.hazmat in Python
理论上 CTR 模式下的 AES 加密允许在任何块索引处解密(也就是说,如果您只想从某个特定的位置解密,则不必从头开始解密整个加密数据 position/block指数)。您只需将所需的块索引添加到计数器的初始值,然后使用这个更新的计数器就可以开始解密了。
在实践中,我试图在 Python 中使用 cryptography.hazmat 库执行此操作,但我无法执行此操作。
我设法使用 pycryptodome 模块完成此操作,方法是为完整文件加密指定 initial_value=0
,并在构造用于在指定 AES 块索引处解密的密码时指定 inital_value=desiredAESBlockIndex
。
这是我的代码(使用密码模块):
import os
import sys
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
def tstFullFileCryptography(aFilePath, aKey, aIV):
fileRawData = b''
with open(aFilePath, 'rb') as file:
fileRawData = file.read()
cipher = Cipher(algorithms.AES(aKey), modes.CTR(aIV))
encryptor = cipher.encryptor()
encryptedData = encryptor.update(fileRawData) + encryptor.finalize()
with open(aFilePath + ".cry", 'wb') as file:
file.write(encryptedData)
######### test #############
decryptor = cipher.decryptor()
decryptedData = decryptor.update(encryptedData) + decryptor.finalize()
if decryptedData == fileRawData:
print("OK - cryptography: full encryption")
else:
print("ERROR - cryptography: full encryption")
def tstCryptographyFromIndex(aFilePath, aKey, aIV):
algAES = algorithms.AES(aKey)
# the desired AES block index and size of data to decrypt
tstAESBlockIndex = 1
tstSizeInBytes = 16 * 13
tstRaw = b''
with open(aFilePath, 'rb') as file:
file.seek(tstAESBlockIndex * algAES.block_size)
tstRaw = file.read(tstSizeInBytes)
tstEncryptedData = b''
with open(aFilePath + ".cry", 'rb') as file:
file.seek(tstAESBlockIndex * algAES.block_size)
tstEncryptedData = file.read(tstSizeInBytes)
print(f"\ntstEncryptedData: {tstEncryptedData}\n")
################ decrypt from desired block index; advance iv
ivNum = int.from_bytes(aIV, byteorder=sys.byteorder)
incrementedIVNum = ivNum + tstAESBlockIndex
incrementedIV = incrementedIVNum.to_bytes(16, byteorder=sys.byteorder)
decryptor = Cipher(algAES, modes.CTR(incrementedIV)).decryptor()
tstDecryptedData = decryptor.update(tstEncryptedData) + decryptor.finalize()
print(f"tstDecryptedData: {tstDecryptedData}\n")
if tstRaw == tstDecryptedData:
print("OK - cryptography: index decryption")
else:
print("ERROR - cryptography: index decryption")
def main():
key = os.urandom(32)
iv = os.urandom(16)
tstFullFileCryptography("C:\work\python\tstdata\video.mp4", key, iv)
tstCryptographyFromIndex("C:\work\python\tstdata\video.mp4", key, iv)
return 0
if __name__ == "__main__":
main()
这是修复后的代码您的代码中有 2 个错误导致您的解密和文件查找不正确。
import os
import sys
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
def tstFullFileCryptography(aFilePath, aKey, aIV):
fileRawData = b''
with open(aFilePath, 'rb') as file:
fileRawData = file.read()
cipher = Cipher(algorithms.AES(aKey), modes.CTR(aIV))
encryptor = cipher.encryptor()
encryptedData = encryptor.update(fileRawData) + encryptor.finalize()
with open(aFilePath + ".cry", 'wb') as file:
file.write(encryptedData)
######### test #############
decryptor = cipher.decryptor()
decryptedData = decryptor.update(encryptedData) + decryptor.finalize()
if decryptedData == fileRawData:
print("OK - cryptography: full encryption")
else:
print("ERROR - cryptography: full encryption")
def tstCryptographyFromIndex(aFilePath, aKey, aIV):
algAES = algorithms.AES(aKey)
# the desired AES block index and size of data to decrypt
tstAESBlockIndex = 1
tstSizeInBytes = 16 * 13
tstRaw = b''
with open(aFilePath, 'rb') as file:
file.seek(tstAESBlockIndex * 16)
tstRaw = file.read(tstSizeInBytes)
tstEncryptedData = b''
with open(aFilePath + ".cry", 'rb') as file:
file.seek(tstAESBlockIndex * 16)
tstEncryptedData = file.read(tstSizeInBytes)
print(f"\ntstEncryptedData: {tstEncryptedData}\n")
################ decrypt from desired block index; advance iv
ivNum = int.from_bytes(aIV, byteorder="big")
incrementedIVNum = ivNum + tstAESBlockIndex
incrementedIV = incrementedIVNum.to_bytes(16, byteorder="big")
decryptor = Cipher(algAES, modes.CTR(incrementedIV)).decryptor()
tstDecryptedData = decryptor.update(tstEncryptedData) + decryptor.finalize()
print(f"tstDecryptedData: {tstDecryptedData}\n")
if tstRaw == tstDecryptedData:
print("OK - cryptography: index decryption")
else:
print("ERROR - cryptography: index decryption")
def main():
key = os.urandom(32)
iv = os.urandom(16)
tstFullFileCryptography("text", key, iv)
tstCryptographyFromIndex("text", key, iv)
return 0
if __name__ == "__main__":
main()
第一个错误是您使用了不正确的 block_size
来查找,因为查找是按字节级别进行的,而 block_size
在您的情况下是位级别 = 128
。
第二个错误是 sys.byte_order
如果您使用 x86 处理器而所有加密操作都是以大字节顺序完成的,那么您基本上是在反转字节导致不正确的解密修复这两个错误,现在让我成功解密.
理论上 CTR 模式下的 AES 加密允许在任何块索引处解密(也就是说,如果您只想从某个特定的位置解密,则不必从头开始解密整个加密数据 position/block指数)。您只需将所需的块索引添加到计数器的初始值,然后使用这个更新的计数器就可以开始解密了。 在实践中,我试图在 Python 中使用 cryptography.hazmat 库执行此操作,但我无法执行此操作。
我设法使用 pycryptodome 模块完成此操作,方法是为完整文件加密指定 initial_value=0
,并在构造用于在指定 AES 块索引处解密的密码时指定 inital_value=desiredAESBlockIndex
。
这是我的代码(使用密码模块):
import os
import sys
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
def tstFullFileCryptography(aFilePath, aKey, aIV):
fileRawData = b''
with open(aFilePath, 'rb') as file:
fileRawData = file.read()
cipher = Cipher(algorithms.AES(aKey), modes.CTR(aIV))
encryptor = cipher.encryptor()
encryptedData = encryptor.update(fileRawData) + encryptor.finalize()
with open(aFilePath + ".cry", 'wb') as file:
file.write(encryptedData)
######### test #############
decryptor = cipher.decryptor()
decryptedData = decryptor.update(encryptedData) + decryptor.finalize()
if decryptedData == fileRawData:
print("OK - cryptography: full encryption")
else:
print("ERROR - cryptography: full encryption")
def tstCryptographyFromIndex(aFilePath, aKey, aIV):
algAES = algorithms.AES(aKey)
# the desired AES block index and size of data to decrypt
tstAESBlockIndex = 1
tstSizeInBytes = 16 * 13
tstRaw = b''
with open(aFilePath, 'rb') as file:
file.seek(tstAESBlockIndex * algAES.block_size)
tstRaw = file.read(tstSizeInBytes)
tstEncryptedData = b''
with open(aFilePath + ".cry", 'rb') as file:
file.seek(tstAESBlockIndex * algAES.block_size)
tstEncryptedData = file.read(tstSizeInBytes)
print(f"\ntstEncryptedData: {tstEncryptedData}\n")
################ decrypt from desired block index; advance iv
ivNum = int.from_bytes(aIV, byteorder=sys.byteorder)
incrementedIVNum = ivNum + tstAESBlockIndex
incrementedIV = incrementedIVNum.to_bytes(16, byteorder=sys.byteorder)
decryptor = Cipher(algAES, modes.CTR(incrementedIV)).decryptor()
tstDecryptedData = decryptor.update(tstEncryptedData) + decryptor.finalize()
print(f"tstDecryptedData: {tstDecryptedData}\n")
if tstRaw == tstDecryptedData:
print("OK - cryptography: index decryption")
else:
print("ERROR - cryptography: index decryption")
def main():
key = os.urandom(32)
iv = os.urandom(16)
tstFullFileCryptography("C:\work\python\tstdata\video.mp4", key, iv)
tstCryptographyFromIndex("C:\work\python\tstdata\video.mp4", key, iv)
return 0
if __name__ == "__main__":
main()
这是修复后的代码您的代码中有 2 个错误导致您的解密和文件查找不正确。
import os
import sys
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
def tstFullFileCryptography(aFilePath, aKey, aIV):
fileRawData = b''
with open(aFilePath, 'rb') as file:
fileRawData = file.read()
cipher = Cipher(algorithms.AES(aKey), modes.CTR(aIV))
encryptor = cipher.encryptor()
encryptedData = encryptor.update(fileRawData) + encryptor.finalize()
with open(aFilePath + ".cry", 'wb') as file:
file.write(encryptedData)
######### test #############
decryptor = cipher.decryptor()
decryptedData = decryptor.update(encryptedData) + decryptor.finalize()
if decryptedData == fileRawData:
print("OK - cryptography: full encryption")
else:
print("ERROR - cryptography: full encryption")
def tstCryptographyFromIndex(aFilePath, aKey, aIV):
algAES = algorithms.AES(aKey)
# the desired AES block index and size of data to decrypt
tstAESBlockIndex = 1
tstSizeInBytes = 16 * 13
tstRaw = b''
with open(aFilePath, 'rb') as file:
file.seek(tstAESBlockIndex * 16)
tstRaw = file.read(tstSizeInBytes)
tstEncryptedData = b''
with open(aFilePath + ".cry", 'rb') as file:
file.seek(tstAESBlockIndex * 16)
tstEncryptedData = file.read(tstSizeInBytes)
print(f"\ntstEncryptedData: {tstEncryptedData}\n")
################ decrypt from desired block index; advance iv
ivNum = int.from_bytes(aIV, byteorder="big")
incrementedIVNum = ivNum + tstAESBlockIndex
incrementedIV = incrementedIVNum.to_bytes(16, byteorder="big")
decryptor = Cipher(algAES, modes.CTR(incrementedIV)).decryptor()
tstDecryptedData = decryptor.update(tstEncryptedData) + decryptor.finalize()
print(f"tstDecryptedData: {tstDecryptedData}\n")
if tstRaw == tstDecryptedData:
print("OK - cryptography: index decryption")
else:
print("ERROR - cryptography: index decryption")
def main():
key = os.urandom(32)
iv = os.urandom(16)
tstFullFileCryptography("text", key, iv)
tstCryptographyFromIndex("text", key, iv)
return 0
if __name__ == "__main__":
main()
第一个错误是您使用了不正确的 block_size
来查找,因为查找是按字节级别进行的,而 block_size
在您的情况下是位级别 = 128
。
第二个错误是 sys.byte_order
如果您使用 x86 处理器而所有加密操作都是以大字节顺序完成的,那么您基本上是在反转字节导致不正确的解密修复这两个错误,现在让我成功解密.