Vigenere CBC
CBC is better than ECB mode, because it makes things more secure, right?
Challenge script:
import random
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def generate_iv(block_size):
# generates a random string of block_size letters
# to be used as the initialization vector for the encryption
return "".join(random.choices(alphabet, k=block_size))
def add_key(key, plaintext_block):
key_idxs = [alphabet.index(key_char) for key_char in key]
pt_idxs = [alphabet.index(pt_char) for pt_char in plaintext_block]
# adding the indexes of the key and plaintext together
ct_idxs = [(key_idx + pt_idx) % len(alphabet) for key_idx, pt_idx in zip(key_idxs, pt_idxs)]
# converting it back into an alphabetical string
return "".join([alphabet[idx] for idx in ct_idxs])
def vigenere_block_chaining_encrypt(key, plaintext):
key_length = len(key)
# pads the plaintext
plaintext = pad(key_length, plaintext)
# generates an iv
iv = generate_iv(key_length)
# splits the plaintext into blocks of length key_length
blocks = [plaintext[i:i+key_length] for i in range(0, len(plaintext), key_length)]
previous_block = iv
ciphertext = ""
# refer to https://www.educative.io/answers/what-is-cbc
for block in blocks:
# adds the previous block
# for the first block this will be the random iv
block = add_key(previous_block, block)
# adds the vigenere key (the block cipher encryption)
previous_block = add_key(key, block)
# adds the output to the final ciphertext
ciphertext += previous_block
# give back the plaintext with the iv
return iv, ciphertext
def pad(block_size, plaintext):
# pads the plaintext with X's until the length is a multiple of block_size
plaintext += "X" * (-len(plaintext) % block_size)
return plaintext
SECRET_MESSAGE = "THISISAFAKEMESSAGEYOUNEEDTOUSETHEOUTPUTTOGETTHEREALSECRETMESSAGE"
key = "AFAKEKEY"
assert len(key) == 8
assert all([char in alphabet for char in key])
assert all([char in alphabet for char in SECRET_MESSAGE])
iv, ciphertext = vigenere_block_chaining_encrypt(key, SECRET_MESSAGE)
print("iv =", iv)
print("ciphertext =", ciphertext)
Output:
iv = XCVUSTKK
ciphertext = WYZCAZIXERPEDAJTTMZRCHVVOIEWJXCFMCGHDHKDDMQWDKVRVCCAWNHOWDXHTUTCXPGLDXVQXEIESEITZUQIYHTTZJWKZVUTXKCHLWOCFWGVRQMPFILDXIULREEPMOWJFYGZJFYYFNMRCQWUEZQSOWYITZTWJVMWEACAQJKJLBMOWNSWSMRWCSFZDCOWIUZYNSDCUAXEYYFTRGFMTSVKZMHKSOTOULOGOLGMGRMOVGLTDDIOWBNILNADKNBQRMHXFMGUBLOWUNECFVALJGRYMLEHDMPYDQMRNDFZKCYBFGPMJUZFECEQKMAJYUOJVEBJMCHMSVOTNDXREBMIYNGEFCGPTIMWZVTHHQHANYEWVCJNYTCJKCNRCLEHROHKCORLATGHSKIE
3