def _decryptio_version1(total_head: bytes, io: IO, encrypt_password: bytes) -> Optional[DecryptIO]: encrypt_password = padding_key(encrypt_password, 32) if len(total_head) < ENCRYPT_HEAD_LEN: return # Version 1 b_mc, magic_code, nonce_or_iv, total_origin_len = parse_head(total_head) b_mc = aes256cbc_decrypt(b_mc, encrypt_password, random_bytes(16, encrypt_password)) total_origin_len = u8x8_to_u64(total_origin_len) if b_mc != BAIDUPCS_PY_CRYPTO_MAGIC_CODE: return if magic_code == SimpleEncryptIO.MAGIC_CODE: return SimpleDecryptIO(io, encrypt_password, b"", total_origin_len) elif magic_code == ChaCha20EncryptIO.MAGIC_CODE: return ChaCha20DecryptIO(io, encrypt_password, nonce_or_iv, total_origin_len) elif magic_code == AES256CBCEncryptIO.MAGIC_CODE: return AES256CBCDecryptIO(io, encrypt_password, nonce_or_iv, total_origin_len) else: logging.warning(f"Unknown magic_code: {magic_code}") return
def to_decryptio(io: IO, encrypt_key: Any): if not encrypt_key: return io encrypt_key = padding_key(encrypt_key, 32) head = io.read(ENCRYPT_HEAD_LEN) if len(head) != ENCRYPT_HEAD_LEN: io.seek(0, 0) return io b_mc, magic_code, nonce_or_iv, total_origin_len = parse_head(head) b_mc = aes265cbc_decrypt(b_mc, encrypt_key, random_bytes(16, encrypt_key)) total_origin_len = u8x8_to_u64(total_origin_len) if b_mc != BAIDUPCS_PY_CRYPTO_MAGIC_CODE: io.seek(0, 0) return io if magic_code == SimpleEncryptIO.MAGIC_CODE: return SimpleDecryptIO(io, encrypt_key, total_origin_len) elif magic_code == ChaCha20EncryptIO.MAGIC_CODE: return ChaCha20DecryptIO(io, encrypt_key, nonce_or_iv, total_origin_len) elif magic_code == AES256CBCEncryptIO.MAGIC_CODE: return AES256CBCDecryptIO(io, encrypt_key, nonce_or_iv, total_origin_len) else: logging.warning(f"Unknown magic_code: {magic_code}") io.seek(0, 0) return io
def __init__(self, io: IO, encrypt_key: Any, nonce_or_iv: Any, 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_key = encrypt_key self._nonce_or_iv = nonce_or_iv # Cryptography # # Instantiated at each subclass, here is for mypy self._crypto: Optional[Cryptography] = None # AES256CBC Encrypt `BAIDUPCS_PY_CRYPTO_MAGIC_CODE` self._encrypted_baidupcs_py_crypto_magic_code = aes265cbc_encrypt( BAIDUPCS_PY_CRYPTO_MAGIC_CODE, self._encrypt_key, random_bytes(16, self._encrypt_key), ) self._total_head_len = len(self.total_head())
def test_random_bytes(): b1 = random_bytes(32, "abc") b2 = random_bytes(32, "abc") assert b1 == b2
def generate_nonce_or_iv(salt: bytes, io: IO) -> bytes: io_len = total_len(io) rg = Random(salt) sample = sample_data(io, rg, 16) return random_bytes(16, salt + sample + str(io_len).encode("utf-8"))