msoffcrypto.method package#

Subpackages#

Submodules#

msoffcrypto.method.ecma376_agile module#

class msoffcrypto.method.ecma376_agile.ECMA376Agile[source]#

Bases: object

static decrypt(key, keyDataSalt, hashAlgorithm, ibuf)[source]#

Return decrypted data.

>>> key = b'@ f\t\xd9\xfa\xad\xf2K\x07j\xeb\xf2\xc45\xb7B\x92\xc8\xb8\xa7\xaa\x81\xbcg\x9b\xe8\x97\x11\xb0*\xc2'
>>> keyDataSalt = b'\x8f\xc7x"+P\x8d\xdcL\xe6\x8c\xdd\x15<\x16\xb4'
>>> hashAlgorithm = 'SHA512'
static encrypt(key, ibuf, salt_value=None, spin_count=100000)[source]#

Return an OLE compound file buffer (complete with headers) which contains ibuf encrypted into a single stream.

When salt_value is not specified (the default), we generate a random one.

static encrypt_payload(ibuf, params: ECMA376AgileCipherParams, secret_key, salt_value)[source]#

Encrypts a payload using the params and secrets passed in.

Returns the encrypted data as a byte array.

static generate_encryption_parameters(key, salt_value=None, spin_count=100000)[source]#

Generates encryption parameters used to encrypt a payload.

Returns the information + a secret key.

static generate_integrity_parameter(encrypted_data, params: ECMA376AgileCipherParams, secret_key, salt_value)[source]#

Returns the encrypted HmacKey and HmacValue.

static get_encryption_information(info: ECMA376AgileEncryptionInfo, encrypted_data, secretKey)[source]#

Return the content of an EncryptionInfo Stream, including the short header, per the specifications at

https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-offcrypto/87020a34-e73f-4139-99bc-bbdf6cf6fa55

static makekey_from_password(password, saltValue, hashAlgorithm, encryptedKeyValue, spinValue, keyBits)[source]#

Generate intermediate key from given password.

>>> password = 'Password1234_'
>>> saltValue = b'Lr]E\xdca\x0f\x93\x94\x12\xa0M\xa7\x91\x04f'
>>> hashAlgorithm = 'SHA512'
>>> encryptedKeyValue = b"\xa1l\xd5\x16Zz\xb9\xd2q\x11>\xd3\x86\xa7\x8c\xf4\x96\x92\xe8\xe5'\xb0\xc5\xfc\x00U\xed\x08\x0b|\xb9K"
>>> spinValue = 100000
>>> keyBits = 256
>>> expected = b'@ f\t\xd9\xfa\xad\xf2K\x07j\xeb\xf2\xc45\xb7B\x92\xc8\xb8\xa7\xaa\x81\xbcg\x9b\xe8\x97\x11\xb0*\xc2'
>>> ECMA376Agile.makekey_from_password(password, saltValue, hashAlgorithm, encryptedKeyValue, spinValue, keyBits) == expected
True
static makekey_from_privkey(privkey, encryptedKeyValue)[source]#
static verify_integrity(secretKey, keyDataSalt, keyDataHashAlgorithm, keyDataBlockSize, encryptedHmacKey, encryptedHmacValue, stream)[source]#

Return True if the HMAC of the data payload is valid.

static verify_password(password, saltValue, hashAlgorithm, encryptedVerifierHashInput, encryptedVerifierHashValue, spinValue, keyBits)[source]#

Return True if the given password is valid.

>>> password = 'Password1234_'
>>> saltValue = b'\xcb\xca\x1c\x99\x93C\xfb\xad\x92\x07V4\x15\x004\xb0'
>>> hashAlgorithm = 'SHA512'
>>> encryptedVerifierHashInput = b'9\xee\xa5N&\xe5\x14y\x8c(K\xc7qM8\xac'
>>> encryptedVerifierHashValue = b'\x147mm\x81s4\xe6\xb0\xffO\xd8"\x1a|g\x8e]\x8axN\x8f\x99\x9fL\x18\x890\xc3jK)\xc5\xb33`' + \
... b'[\\\xd4\x03\xb0P\x03\xad\xcf\x18\xcc\xa8\xcb\xab\x8d\xeb\xe3s\xc6V\x04\xa0\xbe\xcf\xae\\\n\xd0'
>>> spinValue = 100000
>>> keyBits = 256
>>> ECMA376Agile.verify_password(password, saltValue, hashAlgorithm, encryptedVerifierHashInput, encryptedVerifierHashValue, spinValue, keyBits)
True
class msoffcrypto.method.ecma376_agile.ECMA376AgileCipherParams[source]#

Bases: object

class msoffcrypto.method.ecma376_agile.ECMA376AgileEncryptionInfo[source]#

Bases: object

getEncryptionDescriptorHeader()[source]#
toEncryptionDescriptor()[source]#

Returns an XML description of the encryption information.

msoffcrypto.method.ecma376_extensible module#

class msoffcrypto.method.ecma376_extensible.ECMA376Extensible[source]#

Bases: object

msoffcrypto.method.ecma376_standard module#

class msoffcrypto.method.ecma376_standard.ECMA376Standard[source]#

Bases: object

static decrypt(key, ibuf)[source]#

Return decrypted data.

static makekey_from_password(password, algId, algIdHash, providerType, keySize, saltSize, salt)[source]#

Generate intermediate key from given password.

>>> password = 'Password1234_'
>>> algId = 0x660e
>>> algIdHash = 0x8004
>>> providerType = 0x18
>>> keySize = 128
>>> saltSize = 16
>>> salt = b'\xe8\x82fI\x0c[\xd1\xee\xbd+C\x94\xe3\xf80\xef'
>>> expected = b'@\xb1:q\xf9\x0b\x96n7T\x08\xf2\xd1\x81\xa1\xaa'
>>> ECMA376Standard.makekey_from_password(password, algId, algIdHash, providerType, keySize, saltSize, salt) == expected
True
static verifykey(key, encryptedVerifier, encryptedVerifierHash)[source]#

Return True if the given intermediate key is valid.

>>> key = b'@\xb1:q\xf9\x0b\x96n7T\x08\xf2\xd1\x81\xa1\xaa'
>>> encryptedVerifier = b'Qos.\x96o\xac\x17\xb1\xc5\xd7\xd8\xcc6\xc9('
>>> encryptedVerifierHash = b'+ah\xda\xbe)\x11\xad+\xd3|\x17Ft\\\x14\xd3\xcf\x1b\xb1@\xa4\x8fNo=#\x88\x08r\xb1j'
>>> ECMA376Standard.verifykey(key, encryptedVerifier, encryptedVerifierHash)
True

msoffcrypto.method.rc4 module#

class msoffcrypto.method.rc4.DocumentRC4[source]#

Bases: object

static decrypt(password, salt, ibuf, blocksize=512)[source]#

Return decrypted data.

static verifypw(password, salt, encryptedVerifier, encryptedVerifierHash)[source]#

Return True if the given password is valid.

>>> password = 'password1'
>>> salt = b'\xe8w,\x1d\x91\xc5j7\x96Ga\xb2\x80\x182\x17'
>>> encryptedVerifier = b'\xc9\xe9\x97\xd4T\x97=1\x0b\xb1\xbap\x14&\x83~'
>>> encryptedVerifierHash = b'\xb1\xde\x17\x8f\x07\xe9\x89\xc4M\xae^L\xf9j\xc4\x07'
>>> DocumentRC4.verifypw(password, salt, encryptedVerifier, encryptedVerifierHash)
True

msoffcrypto.method.rc4_cryptoapi module#

class msoffcrypto.method.rc4_cryptoapi.DocumentRC4CryptoAPI[source]#

Bases: object

static decrypt(password, salt, keySize, ibuf, blocksize=512, block=0)[source]#

Return decrypted data.

static verifypw(password, salt, keySize, encryptedVerifier, encryptedVerifierHash, algId=26625, block=0)[source]#

Return True if the given password is valid.

msoffcrypto.method.xor_obfuscation module#

class msoffcrypto.method.xor_obfuscation.DocumentXOR[source]#

Bases: object

static create_xor_array_method1(password)[source]#
static create_xor_key_method1(password)[source]#
static decrypt(password, ibuf, plaintext, records, base)[source]#

Return decrypted data (DecryptData_Method1)

initial_code = [57840, 7439, 52380, 33984, 4364, 3600, 61902, 12606, 6258, 57657, 54287, 34041, 10252, 43370, 20163]#
pad_array = [187, 255, 255, 186, 255, 255, 185, 128, 0, 190, 15, 0, 191, 15, 0]#
static rol(n, rotations, width)[source]#
static ror(n, rotations, width)[source]#
static verifypw(password, verificationBytes)[source]#

Return True if the given password is valid.

>>> from struct import unpack
>>> password = 'VelvetSweatshop'
>>> (key,) = unpack('<H', b'\x0A\x9A')  # 0x9a0a
>>> DocumentXOR.verifypw(password, key)
True
xor_matrix = [44796, 19929, 39858, 10053, 20106, 40212, 10761, 31585, 63170, 64933, 60267, 50935, 40399, 11199, 17763, 35526, 1453, 2906, 5812, 11624, 23248, 885, 1770, 3540, 7080, 14160, 28320, 56640, 55369, 41139, 20807, 41614, 21821, 43642, 17621, 28485, 56970, 44341, 19019, 38038, 14605, 29210, 60195, 50791, 40175, 10751, 21502, 43004, 24537, 18387, 36774, 3949, 7898, 15796, 31592, 63184, 47201, 24803, 49606, 37805, 14203, 28406, 56812, 17824, 35648, 1697, 3394, 6788, 13576, 27152, 43601, 17539, 35078, 557, 1114, 2228, 4456, 30388, 60776, 51953, 34243, 7079, 14158, 28316, 14128, 28256, 56512, 43425, 17251, 34502, 7597, 13105, 26210, 52420, 35241, 883, 1766, 3532, 4129, 8258, 16516, 33032, 4657, 9314, 18628]#
static xor_ror(byte1, byte2)[source]#

Module contents#