10. Implémentation du mode CBC

10. Implémentation du mode CBC

Implement CBC mode

CBC mode is a block cipher mode that allows us to encrypt irregularly-sized messages, despite the fact that a block cipher natively only transforms individual blocks.
In CBC mode, each ciphertext block is added to the next plaintext block before the next call to the cipher core.
The first plaintext block, which has no associated previous ciphertext block, is added to a "fake 0th ciphertext block" called the initialization vector, or IV.
Implement CBC mode by hand by taking the ECB function you wrote earlier, making it encrypt instead of decrypt (verify this by decrypting whatever you encrypt to test), and using your XOR function from the previous exercise to combine them.
The file here is intelligible (somewhat) when CBC decrypted against "YELLOW SUBMARINE" with an IV of all ASCII 0 (\x00\x00\x00 &c)

Don't cheat.
Do not use OpenSSL's CBC code to do CBC mode, even to verify your results. What's the point of even doing this stuff if you aren't going to learn from it?

Miroir du fichier texte

Le concept du chiffrement CBC (Cipher Block Chaining) est la séparation du texte en block de taille fixe. Un IV (vecteur d'initialisation) est appliqué en XOR sur le premier bloc, puis celui-ci est chiffré env utilisant AES en mode ECB. Le résultat est appliqué par XOR sur le second bloc, puis celui-ci est chiffré, etc.

Voici un schéma représentant clairement l'enchainement des opérations:

Schéma CBC Source Wikimedia

Chiffrement et déchiffrement ECB

Comme indiqué dans l'énoncé, la première partie de cette exercice est de transformer notre code de l'exercice 7 pour s'assurer qu'il puisse déchiffrer un texte chiffré avec AES en mode ECB.

Cela est relativement trivial en continuant à utiliser la bibliothèque Crypto:

from Crypto.Cipher import AES

def ecb_encrypt(text, key):
    aes_object = AES.new(key, AES.MODE_ECB)
    return aes_object.encrypt(text)

def ecb_decrypt(cipher_text, key):
    aes_object = AES.new(key, AES.MODE_ECB)
    return aes_object.decrypt(cipher_text)

Chiffrement et déchiffrement CBC

Idem, l'implémentation du chiffrement CBC n'est pas très compliqué.

Pour le chiffrement de texte, il suffit de coder une fonction qui prend un texte en clair en paramètre, qui XOR chaque bloc de texte avec un masque (qui sera l'IV ou le vecteur d'initialisation pour le premier bloc), puis qui chiffre avec ECB ce bloc. Le résultat sera utilisé comme masque pour le bloc suivant et ainsi de suite:

def cbc_encrypt(text, key, mask):
    block_size = len(IV)
    blocks = [text[i:i+block_size] for i in range(0, len(text), block_size)]
    result = b""
    for block in blocks:
        mask = ecb_encrypt(xor(block, mask), key)
        result += mask
    return result

A l'inverse, pour le déchiffrement, on a :

def cbc_decrypt(cipher_text, key, mask):
    block_size = len(IV)
    blocks = [cipher_text[i:i+block_size] for i in range(0, len(cipher_text), block_size)]
    result = b""
    for block in blocks:
        result += xor(ecb_decrypt(block, key), mask)
        mask = block
    return result

Dans les deux cas le paramêtre mask de ces fonctions a pour valeur l'IV.

Ainsi, mis bout à bout on obtient le code suivant:

from Crypto.Cipher import AES
from base64 import b64decode

def xor(var, key):
    return bytes(a ^ b for a, b in zip(var, key))

def ecb_encrypt(text, key):
    aes_object = AES.new(key, AES.MODE_ECB)
    return aes_object.encrypt(text)

def ecb_decrypt(cipher_text, key):
    aes_object = AES.new(key, AES.MODE_ECB)
    return aes_object.decrypt(cipher_text)

def cbc_encrypt(text, key, mask):
    block_size = len(mask)
    blocks = [text[i:i+block_size] for i in range(0, len(text), block_size)]
    result = b""
    for block in blocks:
        mask = ecb_encrypt(xor(block, mask), key)
        result += mask
    return result

def cbc_decrypt(cipher_text, key, mask):
    block_size = len(mask)
    blocks = [cipher_text[i:i+block_size] for i in range(0, len(cipher_text), block_size)]
    result = b""
    for block in blocks:
        result += xor(ecb_decrypt(block, key), mask)
        mask = block
    return result

file = open('10.txt', 'r')
cipher_text = b64decode("".join(file.read().splitlines()))
key = b"YELLOW SUBMARINE"
IV = b"\x00"*16
print(cbc_decrypt(cipher_text, key, IV).decode())

Le résultat est :

I'm back and I'm ringin' the bell
A rockin' on the mike while the fly girls yell
In ecstasy in the back of me
Well that's my DJ Deshay cuttin' all them Z's
Hittin' hard and the girlies goin' crazy
Vanilla's on the mike, man I'm not lazy.

I'm lettin' my drug kick in
It controls my mouth and I begin
To just let it flow, let my concepts go
My posse's to the side yellin', Go Vanilla Go!

Smooth 'cause that's the way I will be
And if you don't give a damn, then
Why you starin' at me
So get off 'cause I control the stage
There's no dissin' allowed
I'm in my own phase
The girlies sa y they love me and that is ok
And I can dance better than any kid n' play

Stage 2 -- Yea the one ya' wanna listen to
It's off my head so let the beat play through
So I can funk it up and make it sound good
1-2-3 Yo -- Knock on some wood
For good luck, I like my rhymes atrocious
Supercalafragilisticexpialidocious
I'm an effect and that you can bet
I can take a fly girl and make her wet.

I'm like Samson -- Samson to Delilah
There's no denyin', You can try to hang
But you'll keep tryin' to get my style
Over and over, practice makes perfect
But not if you're a loafer.

You'll get nowhere, no place, no time, no girls
Soon -- Oh my God, homebody, you probably eat
Spaghetti with a spoon! Come on and say it!

VIP. Vanilla Ice yep, yep, I'm comin' hard like a rhino
Intoxicating so you stagger like a wino
So punks stop trying and girl stop cryin'
Vanilla Ice is sellin' and you people are buyin'
'Cause why the freaks are jockin' like Crazy Glue
Movin' and groovin' trying to sing along
All through the ghetto groovin' this here song
Now you're amazed by the VIP posse.

Steppin' so hard like a German Nazi
Startled by the bases hittin' ground
There's no trippin' on mine, I'm just gettin' down
Sparkamatic, I'm hangin' tight like a fanatic
You trapped me once and I thought that
You might have it
So step down and lend me your ear
'89 in my time! You, '90 is my year.

You're weakenin' fast, YO! and I can tell it
Your body's gettin' hot, so, so I can smell it
So don't be mad and don't be sad
'Cause the lyrics belong to ICE, You can call me Dad
You're pitchin' a fit, so step back and endure
Let the witch doctor, Ice, do the dance to cure
So come up close and don't be square
You wanna battle me -- Anytime, anywhere

You thought that I was weak, Boy, you're dead wrong
So come on, everybody and sing this song

Say -- Play that funky music Say, go white boy, go white boy go
play that funky music Go white boy, go white boy, go
Lay down and boogie and play that funky music till you die.

Play that funky music Come on, Come on, let me hear
Play that funky music white boy you say it, say it
Play that funky music A little louder now
Play that funky music, white boy Come on, Come on, Come on
Play that funky music