Skip to content

Instantly share code, notes, and snippets.

@erjiang
Created May 1, 2020 19:58
Show Gist options
  • Save erjiang/5ba01d43922fdf8c62818ce23e2e2b86 to your computer and use it in GitHub Desktop.
Save erjiang/5ba01d43922fdf8c62818ce23e2e2b86 to your computer and use it in GitHub Desktop.
import secrets
import string
from typing import Sequence
"""
This is a set of functions for demonstrating one-time pad
encryption using a twenty-six letter alphabet.
This code is a companion to the article at
https://notes.ericjiang.com/posts/1051
"""
def add_text(text1: str, text2: str) -> str:
"""
>>> add_text('HELLO', 'ABCDE')
'HFNOS'
"""
return "".join([
number_to_char(
(char_to_number(c1) + char_to_number(c2)) % 26
)
for c1, c2 in zip(text1, text2)])
def subtract_text(text1: str, text2: str) -> str:
"""
Given two strings of equal length, subtract each letter in `text2`
from the corresponding letter in `text1`.
>>> subtract_text('HELLO', 'ABCDE')
'HDJIK'
"""
return "".join([
number_to_char(
(char_to_number(c1) - char_to_number(c2)) % 26
)
for c1, c2 in zip(text1, text2)])
def strip_spaces(text: str) -> str:
"""
Removes all space characters from a string.
>>> strip_spaces("Hello world")
'Helloworld'
"""
return text.replace(" ", "")
def random_key(length: int) -> str:
"""
Creates a random string of letters of `length` characters.
>>> random_key(5)
'CKMML'
"""
return ''.join(secrets.choice(string.ascii_uppercase) for _ in range(length))
def char_to_number(char: str) -> int:
char = char.upper()
if ord(char) < ord('A') or ord(char) > ord('Z'):
raise ValueError("character out of range")
return ord(char) - ord('A')
def number_to_char(num: int) -> str:
if num < 0 or num > 25:
raise ValueError("number out of range")
return chr(num + ord('A'))
def text_to_nums(text: str) -> Sequence[int]:
return [char_to_number(x) for x in text]
def nums_to_text(nums: Sequence[int]) -> str:
return "".join([number_to_char(x) for x in nums])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment