-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchallenge_05.py
59 lines (44 loc) · 1.92 KB
/
challenge_05.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# Repeating-key XOR
from challenge_01 import bytes_to_hex, hex_to_bytes
def encrypt(plaintext: str | bytes, key: str | bytes, rt: type = str) -> str | bytes:
r"""
Encrypt the plaintext with repeated-key XOR.
>>> s = "Burning 'em, if you ain't quick and nimble\nI go crazy when I hear a cymbal"
>>> encrypt(s, "ICE")
'0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f'
>>> encrypt(s, "ICE", rt=bytes)
b'\x0b67\'*+.cb,.ii*#i:*<c$ -b=c4<*&"c$\'\'e\'*(+/ C\ne.,e*1$3:e>+ \'c\x0ci+ (1e(c&0.\'(/'
"""
if isinstance(plaintext, str):
plaintext = plaintext.encode("utf-8")
if isinstance(key, str):
key = key.encode("utf-8")
n = len(key)
res = [(byte ^ key[i % n]) for (i, byte) in enumerate(plaintext)]
if rt is str:
return bytes_to_hex(res)
if rt is bytes:
return bytes(res)
raise ValueError(f"Invalid rt type ({rt}). Only str and bytes are supported.")
def decrypt(
ciphertext: str | bytes | list[int], key: str | bytes, rt: type = str
) -> str | bytes:
r"""
Decrypt the ciphertext with repeated-key XOR.
This is really the same function as `encrypt`.
>>> s = "0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f"
>>> expected = "Burning 'em, if you ain't quick and nimble\nI go crazy when I hear a cymbal"
>>> assert decrypt(s, "ICE") == expected
"""
if isinstance(ciphertext, str):
ciphertext = hex_to_bytes(ciphertext)
if isinstance(key, str):
key = key.encode("utf-8")
n = len(key)
res = [(byte ^ key[i % n]) for (i, byte) in enumerate(ciphertext)]
if rt is str:
return "".join(chr(x) for x in res)
return bytes(res)
if __name__ == "__main__":
import doctest
doctest.testmod()