def __init__(self, io: IO, encrypt_password: bytes, total_origin_len: int): self._io = io # The length of unencrypted content of `self._io` self._io_len = total_len(self._io) # The offset of encrypted content of `self._io` self._offset = 0 # The total length of all original (decrypted) content # # Only define it at __init__ self._total_origin_len = total_origin_len self._encrypt_password = encrypt_password self._salt_for_head = generate_salt() self._encrypt_key_for_head, self._iv_for_head = generate_key_iv( encrypt_password, self._salt_for_head, 32, 16) # `self._encrypt_key`,`self._nonce_or_iv` is for cryptography self._salt = generate_salt() self._encrypt_key, self._nonce_or_iv = generate_key_iv( encrypt_password, self._salt, 32, 16) # Cryptography # # Instantiated at each subclass, here is for mypy self._crypto: Optional[Cryptography] = None self._total_head = None self._total_head_len = len(self.total_head)
def test_generate_key_iv(): pwd = b"test" salt = b"\xf6\x81\x8c\xae\x13\x18r\xbd" key, iv = generate_key_iv(pwd, salt, 32, 16) assert ( key == b"l\x04\xcb\xae\xc4\xd7\xa05^\x04\x93\xa2M\xe5\x0ee\\?\xc1C;\xca\xab|Z\xda\x98\xe8\xdb\x01\xdb\xa0" ) assert iv == b"\x8b\xe2\x02\x8e\xee6j\x1cLv\xa2&\xa2\x8a\x1d\xfd"
def _decryptio_version3(total_head: bytes, io: IO, encrypt_password: bytes) -> Optional[DecryptIO]: if len(total_head) < PADDED_ENCRYPT_HEAD_WITH_SALT_LEN: return enc_head, salt_for_head = ( total_head[:PADDED_ENCRYPT_HEAD_LEN], total_head[PADDED_ENCRYPT_HEAD_LEN:], ) encrypt_key_for_head, iv_for_head = generate_key_iv( encrypt_password, salt_for_head, 32, 16) head = aes256cbc_decrypt(enc_head, encrypt_key_for_head, iv_for_head) b_mc, magic_code, padding_salt, total_origin_len = parse_head(head) total_origin_len = u8x8_to_u64(total_origin_len) salt = padding_salt[:8] encrypt_key, nonce_or_iv = generate_key_iv(encrypt_password, salt, 32, 16) if b_mc != BAIDUPCS_PY_CRYPTO_MAGIC_CODE: return eio = None if magic_code == SimpleEncryptIO.MAGIC_CODE: eio = SimpleDecryptIO(io, encrypt_key, nonce_or_iv, total_origin_len) elif magic_code == ChaCha20EncryptIO.MAGIC_CODE: eio = ChaCha20DecryptIO(io, encrypt_key, nonce_or_iv, total_origin_len) elif magic_code == AES256CBCEncryptIO.MAGIC_CODE: eio = AES256CBCDecryptIO(io, encrypt_key, nonce_or_iv, total_origin_len) else: logging.warning(f"Unknown magic_code: {magic_code}") return eio._total_head_len = PADDED_ENCRYPT_HEAD_WITH_SALT_LEN return eio