5. Implémentation XOR à clef redondante
Implement repeating-key XOR
Here is the opening stanza of an important work of the English language:
Burning 'em, if you ain't quick and nimble
I go crazy when I hear a cymbal
Encrypt it, under the key "ICE", using repeating-key XOR.
In repeating-key XOR, you'll sequentially apply each byte of the key; the first byte of plaintext will be XOR'd against I, the next C, the next E, then I again for the 4th byte, and so on.
It should come out to:
0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272
a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f
Encrypt a bunch of stuff using your repeating-key XOR function. Encrypt your mail. Encrypt your password file. Your .sig file. Get a feel for it. I promise, we aren't wasting your time with this.
Notre utilisation du chiffrement XOR évolue dans cette exercice : au lieu de se limiter à une clef à un seul caractère, nous allons implémenter une solution de chiffrement XOR avec plusieurs caractères. Pour illustrer le concept : si l'on a la chaine de caractère cryptopals challenge
et la clef de chiffrement clef
, il faudra concaténer la répétition de cette dernière de manière à pouvoir effectuer l'opération suivante:
cryptopals challenge
⊕ clefclefclefclefclef
Pour résoudre cet exercice nous n'avons qu'à créer une fonction qui permette d'effectuer une opération XOR entre deux chaînes de caratères :
def xor_string(string, key):
key_length = len(key)
result = []
for i in range(len(string)):
result.append(chr(ord(string[i]) ^ ord(key[i%key_length])))
return "".join(result).encode().hex()
text = """Burning 'em, if you ain't quick and nimble
I go crazy when I hear a cymbal"""
key = "ICE"
print(xor_string(text, key))
Après l'exécution du script nous obtenons le résultat :
0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f
Notez que pour vérifier que notre fonction chiffre de manière correcte, nous pouvons chiffrer le résultat avec la même clef et s'assurer que nous obtenons la phrase d'origine (grâce aux propriétés de commutativité et d'associassivité de XOR ; soit la relation A ⊕ B = C et B ⊕ C = A):
answer = xor_string(text, key)
reverse = xor_string(bytearray.fromhex(answer).decode(), key)
print(bytearray.fromhex(reverse).decode())
Ce qui nous donne le résultat :
Burning 'em, if you ain't quick and nimble
I go crazy when I hear a cymbal