TIL but its from tweets(Luhn, caesar, vigenere cipher)

TIL but its from tweets(Luhn, caesar, vigenere cipher)

So I this tweet early morning and was intrigued by this tweet. Had no idea what a Lugn algorithm and vigenere cipher was and had forgotten about caesar cipher. Its as good as a day to start learning as any other day, so I decided to code these things up.

Luhn Algorithm

So essentially this algorithm was created by an IBM scientist Hans Peter Luhn. Its also called the mod 10 algorithm. It essentially works out to check for errors in digits of IMEI or credit card number and so on. It is not an algorithm against malicious attacks, it just something that is used to ensure accidental error while typing card number. If you try to pay by credit card and after typing it out if there is a mistake there then it says you have typed the wrong credit number.

This is a fake American express card number I took from https://developers.bluesnap.com/reference/test-credit-cards.

Now if I change one of the number in this:

How does Luhn work

Let me take the same 374245455400126 as the example credit card number.

  • Starting from the rightmost digit, start doubling every second digit

  • If after a sum the value is greater than 9, then sum the digits(this can also be done by just subtracting by 9 which is easier in code)

  • Sum all the values now

  • The sum has to be a multiple of 10, which is the case here.

python code for Luhn

def luhn(number):
    sum = 0
    card_number = str(number)
    is__num_len_even = len(card_number)%2==0
    for i, digit in enumerate(card_number):
        digit = int(digit)
        # this is because we are enummerating from first digit from left
        # and if length is even then when we start from the rightmost digit
        # we end the first digit from left, if len is off we end up at the 
        # second digit from left.
        if(i%2==(0 if is__num_len_even else 1)):
            digit*=2
            if digit>9:
                digit-=9
        sum+=digit
    return sum%10==0
print(luhn(374245455400126))

Caesar cipher

Caesar cipher is an encoding scheme where we shift the letters in a phrase by a fixed number for all. A cipher with fixed number as 3 would shift A to D, C to F and so on. As it seems like from the name, it is attributed to Julius Caesar itself, it is said that he used this cipher to share information with his generals. The cipher said to be used had a fixed number of 3. It is also said that Augustus used this as well with 1 as the fixed number, the difference being that instead of wrapping around at end, in the sense that A for Z, they used AA instead.

Of course given there are only 26 letters so only 25 different ways of encoding, brute force is usually enough to break the cipher. Although when it was prominent this method was not as feasible making it harder to crack.

Example ciphering

Assuming a fixed number of 3, this is how caesar cipher would shift it to different letters.

How to code this

def caesar_encrypt(text, shift):
    result = ""
    for char in text:
        if char.isalpha():
            # we have to do all this calculation is because we need the shit to wrap around
            # when character is "x" and we need to shit it by 3, it should be "a" but if we do
            # not use the modulo calculation to wrap around we will "{"" instead 
            base = ord('a') if char.islower() else ord('A')
            result += chr((ord(char) - base + shift)%26 + base)
        else:
            result+=char
    return result

def caesar_decrypt(text, shift):
    return caesar_encrypt(text, -shift)


text = "Hello, World!"
shift = 3
encrypted_text = caesar_encrypt(text, shift)
decrypted_text = caesar_decrypt(encrypted_text, shift)

print("Original:", text)
print("Encrypted:", encrypted_text)
print("Decrypted:", decrypted_text)

Vigenère cipher

This is another type of method to encrypt data, in this we choose a keyword whatever that might be and shift the each letter of keyword based on corresponding letter of the text. A Vigenère table is generally used to do this:

Vigenere Cipher table | Download Scientific Diagram

There are of courses cases where the keyword is shorter than the text, in that case we keep repeating the keyword until it matches the length of the text. For instance if the text is "hello world" and the keyword is "lmnop" then we keep repeating "lmnop" until it matches, so in this case that would be "lmnoplmnop". If we take a look at the table, the other way of looking at this is we shift the keyword with the ordinal value of letter in text subtracted by one. So ordinal value of 'h' is 7, so we shift 'l' by 7 so it should become 's'.

Example cipher

Code

def vigenere_cipher(text, keyword, decrypt=False):
    result = ""
    keyword = keyword.upper()
    key_index = 0
    for char in text:
        if char.isalpha():
            key = ord(keyword[key_index % len(keyword)]) - ord('A')
            base = ord('a') if char.islower() else ord('A')
            shift = key if not decrypt else -key
            result += chr((ord(char) - base + shift) % 26 + base)
            key_index += 1
        else:
            result += char
    return result

# Example usage
text = "Hello World"
keyword = "lmnop"
encrypted_text = vigenere_cipher(text, keyword)
decrypted_text = vigenere_cipher(encrypted_text, keyword, decrypt=True)

print("Original:", text)
print("Encrypted:", encrypted_text)
print("Decrypted:", decrypted_text)