From 3f1ff2332bd10a627a2ec5801046615e80e3bd58 Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Tue, 12 Sep 2017 09:29:41 +0200 Subject: [PATCH] initial state --- LS47.scad | 103 ++++++++++++++++++++++++++++++++++++++++++++ README.md | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 LS47.scad create mode 100644 README.md diff --git a/LS47.scad b/LS47.scad new file mode 100644 index 0000000..9b426d3 --- /dev/null +++ b/LS47.scad @@ -0,0 +1,103 @@ +// text_on_cube.scad - Example for text() usage in OpenSCAD + +echo(version=version()); + +//font = "URW Bookman L"; +font = "Monospace"; +font2 = "Droid Sans Mono"; +//TODO: kulaty rohy + +tilesize=25.4; + +off=tilesize*1.05; +tileheight=tilesize/8; + +module tilec(letter, x, y, c) { + translate([x*off,(6-y)*off,0]) { + difference() { + color(c) + cube([tilesize,tilesize,tileheight]); + color(c) + translate([tilesize*.4,tilesize*.4,tileheight*.51]) + linear_extrude (height=tileheight/2) + text(letter, font=font, size=tilesize*.5, + halign="center", valign="baseline"); + color(c) + translate([tilesize*.83, tilesize/2, tileheight*.76]) + linear_extrude(height=tileheight/4) + text(str(x), font=font2, size=tilesize*.2, + halign="center", valign="center"); + color(c) + translate([tilesize/2, tilesize*.14, tileheight*.76]) + linear_extrude(height=tileheight/4) + text(str(y), font=font2, size=tilesize*.2, + halign="center", valign="center"); + } + } +} + +//tiles + +module tile(letter,x,y) { + tilec(letter,x,y,"darkgray"); +} + +tile("_",0,0); +tile("A",1,0); +tile("B",2,0); +tile("C",3,0); +tile("D",4,0); +tile("E",5,0); +tile("F",6,0); +tile("G",0,1); +tile("H",1,1); +tile("I",2,1); +tile("J",3,1); +tile("K",4,1); +tile("L",5,1); +tile("M",6,1); +tile("N",0,2); +tile("O",1,2); +tile("P",2,2); +tile("Q",3,2); +tile("R",4,2); +tile("S",5,2); +tile("T",6,2); +tile("U",0,3); +tile("V",1,3); +tile("W",2,3); +tile("X",3,3); +tile("Y",4,3); +tile("Z",5,3); +tile(".",6,3); +tile("0",0,4); +tile("1",1,4); +tile("2",2,4); +tile("3",3,4); +tile("4",4,4); +tile("5",5,4); +tile("6",6,4); +tile("7",0,5); +tile("8",1,5); +tile("9",2,5); +tile(",",3,5); +tile("-",4,5); +tile("+",5,5); +tile("*",6,5); +tile("/",0,6); +tile(":",1,6); +tile("?",2,6); +tile("!",3,6); +tile("'",4,6); +tile("(",5,6); +tile(")",6,6); + + +//the token +translate([-off/2,off/2,0]) { + color("red") difference() { + cylinder(h=tileheight, d=tilesize*.7); + translate([0,0,-.1]) + cylinder(h=tileheight*1.2, d=tilesize*.7-tileheight); + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..9333fb4 --- /dev/null +++ b/README.md @@ -0,0 +1,126 @@ + +# LS47 hand-computable cipher + +This is a slight improvement of the ElsieFour cipher as described by Alan Kaminsky [1]. We use 7x7 characters instead of previous (barely fitting) 6x6 to be able to encrypt some structured information and add a simple key-expansion algorithm. Similar security considerations hold. + +There's 3D-printable SCAD model of the whole thing. + +### Character board + +We have added some real punctuation, basic stuff for writing a bit of markdown, +and quotes&parens for writing structured information. The letters of the board +now look like this: + +``` +_ a b c d e f +g h i j k l m +n o p q r s t +u v w x y z . +0 1 2 3 4 5 6 +7 8 9 , - + * +/ : ? ! ' ( ) +``` + +Zoomed in, it's nice to have extra position information written on the tiles: + +``` +/-----\ /-----\ /-----\ /-----\ /-----\ +| | | | | | | | | | +| _ 0| | a 1| | b 2| | c 3| | d 4| ... +| 0 | | 0 | | 0 | | 0 | | 0 | +\-----/ \-----/ \-----/ \-----/ \-----/ + +/-----\ /-----\ +| | | | +| g 0| | h 1| ... +| 1 | | 1 | +\-----/ \-----/ + . . + . . + . . +``` + +You also need some kind of a marker (e.g. a small shiny stone, bolt nut or similar kinds of well-shaped trash). + +## How-To + +You may as well see the paper [1], there are also pictures. This is somewhat more concentrated: + +### Encryption + +1. The symmetric key is the initial state of the board. Arrange your tiles to 7x7 square according to the key. +2. Put the marker on (0,0). +3. Find the next letter you want to encrypt on the board, its position is `P`. +4. Look at the marker; numbers written on the marked tile are coordinates `M`. +5. Compute position of the ciphertext as `C := P + M mod (7,7)`. Output the letter found on position `C` as ciphertext. +6. Rotate the row that contains the plaintext letter one position to the right, carry the marker if present. +7. Rotate the column that now (after the first rotation) contains the ciphertext letter one position down, carry the marker if present. +8. Update the position of the marker: `M := M + C' mod (7,7)` where `C'` are the numbers written on the ciphertext tile. +9. Repeat from 3 as many times as needed to encrypt the whole plaintext. + +### Decryption + +Decryption procedure is basically the same, except that in step 5 you know `C` +and `M`, and need to produce `P` by subtraction: `P := C - M mod (7,7)`. +Otherwise (except that you input ciphertext and output plaintext) everything +stays the same. + +### Key generation + +Grab a bag full of tiles and randomly draw them one by one. Key is the 49-item permutation of them. + +### Key expansion from a password + +Remembering 49-position random permutation that includes weird characters is +not very handy. You can instead derive the keys from an arbitrary string of +sufficient length. + +"Sufficient" means "provides enough entropy". Full keys store around 208 bits +of entropy. To reach that, your password should have: + +- at least around 61 decimal digits if made only from random decimal digits +- at least around 44 letters if made only from completely random letters +- at least around 40 alphanumeric characters if made randomly only from them + +To have the "standard" 128 bits of entropy, the numbers reduce to roughly 39, +28 and 25, respectively. + +Note that you can save the expanded tile board for later if you don't want to +expand the passwords before each encryption/decryption. + +The actual expansion can be as simple as this: + +1. initialize `I:=0`, put the tiles on the board sorted by their numbers (i.e. as on the picture above) +2. Take the first letter of the password and see the numbers on its tile; mark them `Px, Py`. +3. Rotate `I`-th row `Px` positions right +4. Rotate `I`th column `Py` positions down +5. `I := I + 1 mod 7`, repeat from 2 with next letter of the password. +6. Resulting tile positions are the expanded key + +### Undistinguishable ciphertexts + +To get a different ciphertext even if the same plaintext is encrypted; prepend +it with a nonce. A nonce is a completely random sequence of letters of a +pre-negotiated length (at least 10 tiles drawn randomly from a bag is +adviseable). + +You may also want to add a random number of spaces to the end of the ciphertext +-- it prevents the enemy from seeing the difference between ciphertexts for +'yes please' and 'no', which would otherwise encrypt to easily measurable +gibberish like `qwc3w_cs'(` and `+v`. + +### Authenticated encryption + +Because ciphertext may be altered in the transfer or during the error-prone +human processing, it is advised to append a simple "signature" to the end of +the message; e.g. a simple string `__YourHonorableNameHere`. If the signature +doesn't match expectations (which happens with overwhelming probability if +there was any error in the process), you discard the message and ask the sender +to re-transmit. + +This works because the cipher output is message-dependent: Having a wrong bit +somewhere in the middle causes avalanche effect and breaks the signature. + +## References + +[1] *Kaminsky, Alan. "ElsieFour: A Low-Tech Authenticated Encryption Algorithm For Human-to-Human Communication." IACR Cryptology ePrint Archive 2017 (2017): 339.*