aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMirek Kratochvil <exa.exa@gmail.com>2017-09-12 09:29:41 +0200
committerMirek Kratochvil <exa.exa@gmail.com>2017-09-12 09:29:41 +0200
commit3f1ff2332bd10a627a2ec5801046615e80e3bd58 (patch)
treed0ddb0278a7aeb7f2d703ce5c4477a81ea34fc84
downloadls47-3f1ff2332bd10a627a2ec5801046615e80e3bd58.tar.gz
ls47-3f1ff2332bd10a627a2ec5801046615e80e3bd58.tar.bz2
initial state
-rw-r--r--LS47.scad103
-rw-r--r--README.md126
2 files changed, 229 insertions, 0 deletions
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.*