ERIKO-CHAN cipher Nov 14, 2010

ERIKO-CHAN is an obscure and weak symmetric stream cipher. The only reason I know of its existence is first through novalis's writeup in this node, and then a handful of messages about it on a cryptography mailing list. Was it created by a paranoid or mathematically-inclined Japanophile fangirl or boy? Did e intend to erode the foundations of our dichotic gender paradigm through eir transgression, following in the tradition of the great Alan Turing? How many vampires still live in Transylvania? This is becoming a digression.

Operation

Key: a twenty digit (or more) random number (whose square root is irrational)

Encipher the message with a standard 6x6 Polybius square (see that node for an example, but in short: A-Z and 0-9, in six lines horizontally) with the rows and columns labelled from 0 to 5.

Calculate the square root of the key and, beginning at the first digit after the decimal place, copy each digit which is within the range 0-5 until you have the same number of digits as in your message.

Add (modulo 6) the message and key streams. This is the ciphertext to be sent to your partner in crime.

Notes

Layer on a transposition cipher to make it more secure.

Don't use the same key more than once. Subtracting two ciphertexts encrypted with the same key yields two plaintexts mashed together, which is not difficult to crack.

I don't know why keys of the form A^n/B^m might be bad, as novalis suggests. As long as their square roots are irrational, they should work fine, right?

It may be possible to recover the key by knowing a short stretch of the square root stream and then using continued fractions. I have no idea if that's true.

Conclusion

This is probably kid sister encryption.

ERIKO-CHAN in Python

OldMiner points out that Python has built-in support for taking the square root to arbitrary precision, so here's a full implementation of ERIKO-CHAN. (See also my original sqrt function below.)

import decimal, re

def encrypt(message, key): return erikochan(message, key, True)
def decrypt(message, key): return erikochan(message, key, False)

def erikochan(input, key, encrypt):
	# normalize the input
	input = re.sub(r'[^0-9a-z]+', '', input.lower())
	
	# get the key stream
	k = 1
	keystream = []
	while len(keystream) < len(input) * 2:
		k += 1
		decimal.getcontext().prec = len(input) * 2 * k
		keystream = str(decimal.Decimal(key).sqrt()).split('.')[1]
		keystream = map(int, re.sub(r'[6-9]+', '', keystream))
	
	# encrypt
	k = 0
	output = ''
	for c in input:
		if c in '0123456789': c = ord(c) - ord('0') + 26
		else: c = ord(c) - ord('a')
		a = c / 6
		b = c % 6
		if encrypt:
			a = (a + keystream[k]) % 6
			b = (b + keystream[k+1]) % 6
		else:
			a = (a - keystream[k]) % 6
			b = (b - keystream[k+1]) % 6
		k += 2
		c = a * 6 + b
		if c < 26: c = chr(c + ord('a'))
		else: c = chr(c - 26 + ord('0'))
		output += c
	return output

Taking the Square Root to Arbitrary Precision in Python (the hard way)

import re

def sqrt(n):
	'yields the number before the decimal place,\
	followed by one yield for each digit afterward'
	
	n = str(n)
	assert re.match(r'[0-9]*(\.[0-9]*)?$', n), 'number too funky---pass it as a string without scientific notation, like "123456789.0123456789"'
	
	if '.' in n: a, b = n.split('.')
	else: a, b = n, ''
	if len(a) % 2: a = '0' + a
	if len(b) % 2: b += '0'
	lst = map(int, re.findall('..', a) + re.findall('..', b))
	dec = len(a) / 2  # decimal pt is before this element in lst
	i = 0
	r = 0
	p = 0
	while 1:
		if i >= len(lst): c = r * 100
		else: c = r * 100 + lst[i]
		i += 1
		
		y = [(x, (20 * p + x) * x) for x in range(10)]
		# get largest y not exceeding c
		x, y = [(x, y) for x, y in y if y <= c][-1]
		
		p = 10 * p + x
		r = c - y
		
		if i == dec: yield p
		elif i > dec: yield x
		if r == 0 and i >= len(lst): return

def example():
	import math
	n = 12345678901234567890
	g = sqrt(n)
	print n
	print math.sqrt(n)
	for i in range(20): print g.next(),
	print

See Also