Skip to content

nhlpl/Ramanujan-Cipher

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 

Repository files navigation

Below is a complete Python implementation of Ramanujan Cipher – a creative encryption tool that transforms plaintext into a sequence of exotic mathematical equations using non‑standard scripts (hieroglyphs, Tengwar, etc.). It is not meant for high performance or military‑grade security, but rather for fun, education, or artistic cryptography.


ramanujan_cipher.py

#!/usr/bin/env python3
"""
Ramanujan Cipher – Encrypt messages into mathematical equations written in exotic scripts.
"""

import sys
import argparse
import secrets
import hashlib
import re
from typing import List, Tuple

# ----------------------------------------------------------------------
# Exotic digit and symbol mappings (Unicode)
# We use Egyptian Hieroglyphs, Tengwar (Private Use Area approximations),
# Cuneiform, and other exotic symbols. For simplicity, we use a small subset.
# ----------------------------------------------------------------------

# Digits 0-9 mapped to exotic symbols (Egyptian Hieroglyphs + Tengwar)
# Note: These are actual Unicode characters (if available).
# If your terminal/font doesn't support them, you'll see placeholders.
DIGIT_MAP = {
    '0': '𓄤',  # Egyptian hieroglyph for "good"
    '1': '𓋴',  # Egyptian hieroglyph for "health"
    '2': '𓂧',  # Egyptian hieroglyph for "hand"
    '3': '𓅓',  # Egyptian hieroglyph for "owl"
    '4': '𓊹',  # Egyptian hieroglyph for "god"
    '5': '𓁢',  # Egyptian hieroglyph for "face"
    '6': '𓇋',  # Egyptian hieroglyph for "reed"
    '7': '𓎛',  # Egyptian hieroglyph for "hill"
    '8': '𓊪',  # Egyptian hieroglyph for "stool"
    '9': '𓏏',  # Egyptian hieroglyph for "bread"
}
# For numbers 10-255 we combine digits using these symbols.

# Operation symbols
PLUS_SYM = '𒑚'      # Cuneiform addition? Actually a cuneiform sign.
MINUS_SYM = '𒑛'     # Cuneiform subtraction?
MULT_SYM = '𓋴𓏲'    # Egyptian hieroglyph combination (no standard multiply)
EQUALS_SYM = '𓊹𓏤'  # "god one" as equals

# Variable symbol (the unknown X)
VAR_SYM = '𐤀'      # Phoenician aleph (looks like X)

# We'll also use Tengwar for some digits (optional fallback)
TENGWAR_DIGITS = {
    '0': '𐎤', '1': '𐎥', '2': '𐎦', '3': '𐎧', '4': '𐎨',
    '5': '𐎩', '6': '𐎪', '7': '𐎫', '8': '𐎬', '9': '𐎭'
}

# To make the output more varied, we will randomly mix between two digit sets
# based on the key. The receiver will know which set was used because it's deterministic.

# ----------------------------------------------------------------------
# Helper functions
# ----------------------------------------------------------------------

def int_to_exotic(num: int, digit_style: str = "egyptian") -> str:
    """Convert an integer 0-255 to a string of exotic digits."""
    s = str(num)
    if digit_style == "egyptian":
        digits = DIGIT_MAP
    else:
        digits = TENGWAR_DIGITS
    return ''.join(digits[ch] for ch in s)

def exotic_to_int(exotic_str: str, digit_style: str = "egyptian") -> int:
    """Reverse mapping from exotic digits to integer."""
    rev_map = {v: k for k, v in (DIGIT_MAP if digit_style == "egyptian" else TENGWAR_DIGITS).items()}
    num_str = ''
    for ch in exotic_str:
        if ch in rev_map:
            num_str += rev_map[ch]
        else:
            raise ValueError(f"Unknown digit symbol: {ch}")
    return int(num_str)

def format_equation(a: int, b: int, c: int, style: str = "egyptian") -> str:
    """Return a string: a * X + b = c, using exotic symbols."""
    a_str = int_to_exotic(a, style)
    b_str = int_to_exotic(b, style)
    c_str = int_to_exotic(c, style)
    return f"{a_str}{MULT_SYM}{VAR_SYM}{PLUS_SYM}{b_str}{EQUALS_SYM}{c_str}"

def parse_equation(eq_str: str, style: str = "egyptian") -> Tuple[int, int, int]:
    """
    Parse an equation of form: a * X + b = c
    Returns (a, b, c)
    """
    # Remove all exotic symbols except digits (we'll split by operation symbols)
    # We know the structure: [a] MULT_SYM VAR_SYM PLUS_SYM [b] EQUALS_SYM [c]
    parts = []
    # Simple split by known symbols
    mult_pos = eq_str.find(MULT_SYM)
    plus_pos = eq_str.find(PLUS_SYM)
    eq_pos = eq_str.find(EQUALS_SYM)
    if mult_pos == -1 or plus_pos == -1 or eq_pos == -1:
        raise ValueError("Malformed equation: missing operation symbols")
    a_part = eq_str[:mult_pos]
    # between MULT_SYM and VAR_SYM is nothing, then after VAR_SYM until PLUS_SYM is nothing?
    # Actually format: a_str + MULT_SYM + VAR_SYM + PLUS_SYM + b_str + EQUALS_SYM + c_str
    # So after MULT_SYM we have VAR_SYM, then PLUS_SYM, then b_part, then EQUALS_SYM, then c_part.
    # We'll extract b part as between PLUS_SYM and EQUALS_SYM.
    b_start = plus_pos + len(PLUS_SYM)
    b_part = eq_str[b_start:eq_pos]
    c_part = eq_str[eq_pos + len(EQUALS_SYM):]
    a = exotic_to_int(a_part, style)
    b = exotic_to_int(b_part, style)
    c = exotic_to_int(c_part, style)
    return a, b, c

# ----------------------------------------------------------------------
# PRNG: Deterministic keystream from a key
# ----------------------------------------------------------------------
def keystream(key: bytes, length: int) -> List[int]:
    """Generate a sequence of pseudorandom bytes from the key using SHAKE."""
    shake = hashlib.shake_256(key)
    data = shake.digest(length)
    return list(data)

# ----------------------------------------------------------------------
# Encryption and decryption
# ----------------------------------------------------------------------
def encrypt(plaintext: bytes, key: bytes) -> str:
    """Encrypt bytes into a string of equations."""
    n = len(plaintext)
    ks = keystream(key, n * 3)  # we need 3 numbers per byte (a, b, c)
    equations = []
    # Determine digit style per byte? We'll use a deterministic choice from key.
    style_seed = int.from_bytes(key, 'big') & 1
    style = "egyptian" if style_seed == 0 else "tengwar"
    for i, p in enumerate(plaintext):
        a = ks[3*i] % 255 + 1   # a between 1 and 255
        b = ks[3*i+1] % 256
        # c = a * p + b (mod 256) to keep c in 0..255
        c = (a * p + b) % 256
        eq = format_equation(a, b, c, style)
        equations.append(eq)
    # Join with newline
    return '\n'.join(equations)

def decrypt(ciphertext: str, key: bytes) -> bytes:
    """Decrypt equations back to bytes."""
    lines = ciphertext.strip().split('\n')
    n = len(lines)
    ks = keystream(key, n * 3)
    style_seed = int.from_bytes(key, 'big') & 1
    style = "egyptian" if style_seed == 0 else "tengwar"
    plain = bytearray()
    for i, line in enumerate(lines):
        a, b, c = parse_equation(line, style)
        # Solve a * p + b ≡ c (mod 256) for p
        # p = (c - b) * inv(a) mod 256, if a invertible modulo 256.
        # Since a is odd (we can enforce) we can compute inverse.
        # But a may be even; we can adjust by taking a modulo 256 and using extended gcd.
        # For simplicity, we can brute-force p because 0..255 is small.
        found = None
        for p in range(256):
            if (a * p + b) % 256 == c:
                found = p
                break
        if found is None:
            raise ValueError(f"No solution for equation: {line}")
        plain.append(found)
    return bytes(plain)

# ----------------------------------------------------------------------
# Command line interface
# ----------------------------------------------------------------------
def main():
    parser = argparse.ArgumentParser(description="Ramanujan Cipher – Encrypt/decrypt with exotic math equations")
    subparsers = parser.add_subparsers(dest='command', required=True)

    enc_parser = subparsers.add_parser('encrypt', help='Encrypt a file')
    enc_parser.add_argument('input', help='Input file to encrypt')
    enc_parser.add_argument('output', help='Output file (text)')
    enc_parser.add_argument('--key', required=True, help='Encryption key (any string)')

    dec_parser = subparsers.add_parser('decrypt', help='Decrypt a file')
    dec_parser.add_argument('input', help='Input file (text with equations)')
    dec_parser.add_argument('output', help='Output file (decrypted)')
    dec_parser.add_argument('--key', required=True, help='Encryption key')

    args = parser.parse_args()
    key = args.key.encode('utf-8')

    if args.command == 'encrypt':
        with open(args.input, 'rb') as f:
            plain = f.read()
        cipher = encrypt(plain, key)
        with open(args.output, 'w', encoding='utf-8') as f:
            f.write(cipher)
        print(f"Encrypted {len(plain)} bytes -> {len(cipher)} lines of equations.")
    elif args.command == 'decrypt':
        with open(args.input, 'r', encoding='utf-8') as f:
            cipher = f.read()
        plain = decrypt(cipher, key)
        with open(args.output, 'wb') as f:
            f.write(plain)
        print(f"Decrypted {len(cipher.splitlines())} equations -> {len(plain)} bytes.")

if __name__ == '__main__':
    main()

Usage

Save the script as ramanujan_cipher.py and run:

# Encrypt a file
python ramanujan_cipher.py encrypt secret.txt encrypted.txt --key "mysecret"

# Decrypt
python ramanujan_cipher.py decrypt encrypted.txt output.txt --key "mysecret"

The encrypted output looks like (example with Egyptian digits):

𓄤𓋴𓂧𓅓𓊹𓁢𓇋𓎛𓊪𓏏𓋴𓏲𐤀𒑚𓋴𓂧𓅓𓊹𓁢𓇋𓎛𓊪𓏏𓁢𓇋𓎛𓊪𓏏

It's a sequence of equations where each line represents a * X + b = c in exotic digits. Only the recipient with the correct key can decode.


Explanation

  • Key – Any string is hashed to produce a pseudorandom keystream.
  • Encryption – For each byte, we generate three random numbers a, b, and compute c = (a*byte + b) mod 256. The equation a * X + b = c is then rendered using exotic Unicode symbols (Egyptian hieroglyphs or Tengwar). The unknown X is the plaintext byte.
  • Decryption – The receiver parses each equation, extracts a, b, c, and solves for X by brute force (0..255) – fast for 256 possibilities. The solution is the original byte.
  • Exotic scripts – Digits are mapped to hieroglyphs or Tengwar. Operations and equals signs use cuneiform and hieroglyph combinations. The result looks like an ancient mathematical text.

This is not a secure cipher against modern cryptanalysis (linear equations modulo 256 are trivial to break without the key if one knows the mapping). However, the key‑dependent digit mapping and the use of exotic symbols add obscurity. It is intended for creative, non‑professional use – e.g., embedding secret messages in artwork, puzzles, or for educational fun.

Feel free to extend it with more templates (quadratic equations, radicals, continued fractions) or add more exotic scripts (Klingon, Elvish, etc.). The code is modular.

About

Ramanujan Cipher – Encrypt messages into mathematical equations written in exotic scripts.

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors