diff --git a/msoffcrypto/method/container/ecma376_encrypted.py b/msoffcrypto/method/container/ecma376_encrypted.py index b363d75..a5818de 100644 --- a/msoffcrypto/method/container/ecma376_encrypted.py +++ b/msoffcrypto/method/container/ecma376_encrypted.py @@ -182,13 +182,28 @@ def write_header_to(self, obuf): Write 128 bytes header in the output buffer. The Name property needs to be converted to UTF-16; Content is _not_ written out by this method. """ - name16 = self.Name.encode("UTF-16-LE") # Write in Little Endian; omit the BOM at the start of the output + name16 = self.Name.encode( + "UTF-16-LE" + ) # Write in Little Endian; omit the BOM at the start of the output directoryNameSize = len(name16) + 2 # Count the null terminator in the size - obuf.write(name16 + b"\0" * 2) # Specs calls for us to store the null-terminator - obuf.write(b"\0" * (64 - directoryNameSize)) # Pad name to 64 bytes (thus max 31 chars + \x00\x00) + obuf.write( + name16 + b"\0" * 2 + ) # Specs calls for us to store the null-terminator + obuf.write( + b"\0" * (64 - directoryNameSize) + ) # Pad name to 64 bytes (thus max 31 chars + \x00\x00) obuf.write(pack(" 2 else 0)) - obuf.write(pack(" 1: raise ValueError("Unexpected layout size; too large") @@ -598,7 +689,9 @@ def _set_sector_locations_of_streams(self, layout: ECMA376EncryptedLayout): layout.miniFatSectors = miniFatSectors layout.directoryEntrySectorNum = self._get_block_num(len(self._dirs), 4) - layout.encryptionPackageSectorNum = self._get_block_num(len(self._dirs[DSPos.iEncryptionPackage].Content), layout.sectorSize) + layout.encryptionPackageSectorNum = self._get_block_num( + len(self._dirs[DSPos.iEncryptionPackage].Content), layout.sectorSize + ) def _get_MiniFAT_sector_number(self, size): return self._get_block_num(size, 64) diff --git a/msoffcrypto/method/ecma376_agile.py b/msoffcrypto/method/ecma376_agile.py index dcc5a3c..783b936 100644 --- a/msoffcrypto/method/ecma376_agile.py +++ b/msoffcrypto/method/ecma376_agile.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import base64 import functools import hmac @@ -26,7 +28,9 @@ } blkKey_VerifierHashInput = bytearray([0xFE, 0xA7, 0xD2, 0x76, 0x3B, 0x4B, 0x9E, 0x79]) -blkKey_encryptedVerifierHashValue = bytearray([0xD7, 0xAA, 0x0F, 0x6D, 0x30, 0x61, 0x34, 0x4E]) +blkKey_encryptedVerifierHashValue = bytearray( + [0xD7, 0xAA, 0x0F, 0x6D, 0x30, 0x61, 0x34, 0x4E] +) blkKey_encryptedKeyValue = bytearray([0x14, 0x6E, 0x0B, 0xE7, 0xAB, 0xAC, 0xD0, 0xD6]) blkKey_dataIntegrity1 = bytearray([0x5F, 0xB2, 0xAD, 0x01, 0x0C, 0xB9, 0xE1, 0xF6]) blkKey_dataIntegrity2 = bytearray([0xA0, 0x67, 0x7F, 0x02, 0xB2, 0x2C, 0x84, 0x33]) @@ -85,9 +89,11 @@ def _encrypt_aes_cbc_padded(data, key, iv, blockSize): def _get_salt(salt_value=None, salt_size=16): - if not salt_value is None: + if salt_value is not None: if len(salt_value) != salt_size: - raise exceptions.EncryptionError(f"Invalid salt value size, should be {salt_size}") + raise exceptions.EncryptionError( + f"Invalid salt value size, should be {salt_size}" + ) return salt_value @@ -103,7 +109,7 @@ def __init__(self): self.blockSize = 16 self.keyBits = 256 self.hashSize = 64 - self.saltValue = None + self.saltValue: bytes | None = None def _enc64(b): @@ -114,13 +120,13 @@ class ECMA376AgileEncryptionInfo: def __init__(self): self.spinCount = 100000 self.keyData = ECMA376AgileCipherParams() - self.encryptedHmacKey = None - self.encryptedHmacValue = None + self.encryptedHmacKey: bytes | None = None + self.encryptedHmacValue: bytes | None = None self.encryptedKey = ECMA376AgileCipherParams() - self.encryptedVerifierHashInput = None - self.encryptedVerifierHashValue = None - self.encryptedKeyValue = None + self.encryptedVerifierHashInput: bytes | None = None + self.encryptedVerifierHashValue: bytes | None = None + self.encryptedKeyValue: bytes | None = None def getEncryptionDescriptorHeader(self): # https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-offcrypto/87020a34-e73f-4139-99bc-bbdf6cf6fa55 @@ -161,7 +167,9 @@ def __init__(self): pass @staticmethod - def _derive_iterated_hash_from_password(password, saltValue, hashAlgorithm, spinValue): + def _derive_iterated_hash_from_password( + password, saltValue, hashAlgorithm, spinValue + ): r""" Do a partial password-based hash derivation. Note the block key is not taken into consideration in this function. @@ -215,7 +223,9 @@ def decrypt(key, keyDataSalt, hashAlgorithm, ibuf): totalSize = totalSize[0] logger.debug("totalSize: {}".format(totalSize)) remaining = totalSize - for i, buf in enumerate(iter(functools.partial(ibuf.read, SEGMENT_LENGTH), b"")): + for i, buf in enumerate( + iter(functools.partial(ibuf.read, SEGMENT_LENGTH), b"") + ): saltWithBlockKey = keyDataSalt + pack(">> ECMA376Standard.makekey_from_password(password, algId, algIdHash, providerType, keySize, saltSize, salt) == expected True """ - logger.debug([password, hex(algId), hex(algIdHash), hex(providerType), keySize, saltSize, salt]) - xor_bytes = lambda a, b: bytearray([p ^ q for p, q in zip(bytearray(a), bytearray(b))]) # bytearray() for Python 2 compat. + logger.debug( + [ + password, + hex(algId), + hex(algIdHash), + hex(providerType), + keySize, + saltSize, + salt, + ] + ) + xor_bytes = lambda a, b: bytearray( + [p ^ q for p, q in zip(bytearray(a), bytearray(b))] + ) # bytearray() for Python 2 compat. # https://msdn.microsoft.com/en-us/library/dd925430(v=office.12).aspx ITER_COUNT = 50000 diff --git a/msoffcrypto/method/rc4_cryptoapi.py b/msoffcrypto/method/rc4_cryptoapi.py index 184a5ae..1666a20 100644 --- a/msoffcrypto/method/rc4_cryptoapi.py +++ b/msoffcrypto/method/rc4_cryptoapi.py @@ -32,7 +32,15 @@ def __init__(self): pass @staticmethod - def verifypw(password, salt, keySize, encryptedVerifier, encryptedVerifierHash, algId=0x00006801, block=0): + def verifypw( + password, + salt, + keySize, + encryptedVerifier, + encryptedVerifierHash, + algId=0x00006801, + block=0, + ): r""" Return True if the given password is valid. """