Source code for src.ch04.challenge.c2_encode_rail
"""Encode message with a 3-rail fence cipher."""
from src.ch04.challenge.c1_encode_route import format_plaintext
[docs]def split_rails(plaintext: str) -> str:
"""Split plaintext into 3 rails for encryption.
Split the rails where the top rail is every 4th letter, the middle rail
is every other letter starting at 1, and the bottom rail is every 4th
letter starting at 2. After splitting, concatenate each rail and
return the result.
Args:
plaintext (str): Plain text message without spaces or punctuation.
Returns:
String with message encrypted using 3 rail fence cipher.
"""
top = plaintext[::4]
middle = plaintext[1::2]
bottom = plaintext[2::4]
return top + middle + bottom
[docs]def encode_rail(plaintext: str, split: int = 5) -> str:
"""Encode rail fence cipher.
Encode **plaintext** with a 3-rail fence cipher. Scrub the plaintext with
:func:`~src.ch04.challenge.c1_encode_route.format_plaintext`, then encrypt
it with :func:`split_rails`.
Args:
plaintext (str): Message to encrypt with 3-rail fence cipher.
split (int): How many letter segments to split message into. Defaults
to ``5``.
Returns:
String with encrypted message split into **split** chunks for easier
transmission.
"""
ciphertext = split_rails(''.join(format_plaintext(plaintext)))
return ' '.join(ciphertext[i:i + split] for i in
range(0, len(ciphertext), split))
[docs]def main():
"""Demonstrate 3-rail fence cipher encoder."""
print('I can encode a message using a 3-rail fence cipher. Don\'t get '
'too\nexcited - it\'s trivial to brute-force; however, one can '
'dream... one\ncan dream...')
message = ('There is a fresh batch of cookies in the cereal box above\n'
'the refrigerator. Keep them away from Debbie!')
print(f'\nEncoding:\n{message}')
print(f'\nEncrypted message:\n{encode_rail(message, 6)}')
if __name__ == '__main__':
main()