From 513f8312a22db2ae1e194e633a41b60dd2b2206a Mon Sep 17 00:00:00 2001 From: Trevor Xiao Date: Wed, 21 Apr 2021 20:44:30 -0400 Subject: Update lc4 script to include playing card tables --- lc4.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'lc4.py') diff --git a/lc4.py b/lc4.py index 03043a4..4a17c93 100644 --- a/lc4.py +++ b/lc4.py @@ -54,9 +54,10 @@ import argparse version = "v2.8.1 (2018-07-24)" # define alphabet -letters6 = "#_23456789abcdefghijklmnopqrstuvwxyz" -letters7 = "_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()" - +letters6 = "#_23456789abcdefghijklmnopqrstuvwxyz" +letters6card = "#abcdefghijklmnopqrstuvwxyz_23456789" +letters7 = "_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()" +letters7card = "0abcdefghijklmnopqrstuvwxyz_.,-+*/:?!'()123456789" def missing_letters(s,t): return ''.join(sorted(set(c for c in s if c not in t))) @@ -333,6 +334,8 @@ if __name__ == '__main__': mgroup1.add_argument("-6", "--lc4", help="use ElsieFour cipher (6x6 table) (default)", action="store_true") mgroup1.add_argument("-7", "--ls47", help="use LS47 cipher (7x7 table)", action="store_true") + parser.add_argument("-pc", "--playingcard", help="Use the \"playing card\" character tables (default: standard tables)", action="store_true") + mgroup2 = parser.add_mutually_exclusive_group() mgroup2.add_argument("-ks", "--keystring", metavar="STRING", help="use STRING as key") mgroup2.add_argument("-kf", "--keyfile", metavar="FILE", help="read key from FILE") @@ -375,10 +378,16 @@ if __name__ == '__main__': if args.ls47: size = 7 - letters = letters7 + if args.playingcard: + letters = letters7card + else: + letters = letters7 else: size = 6 - letters = letters6 + if args.playingcard: + letters = letters6card + else: + letters = letters6 tiles = list(zip(letters, [(x // size, x % size) for x in range(size * size)])) -- cgit v1.2.3 From 00f89c47c7963c8873bee38a1d003d1cec443c5c Mon Sep 17 00:00:00 2001 From: Trevor Xiao Date: Wed, 21 Apr 2021 20:50:08 -0400 Subject: Fix whitespace --- README.md | 1 - lc4.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'lc4.py') diff --git a/README.md b/README.md index 284f39e..1d24595 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,6 @@ mapped to playing cards, similar to the Solitaire cipher [2]. Using playing cards could be more innocuous and easily explainable to the secret police than a set of peculiar numbered tiles. - ``` 0 a b c d e f g h i j k l m diff --git a/lc4.py b/lc4.py index 4a17c93..5a2785f 100644 --- a/lc4.py +++ b/lc4.py @@ -59,6 +59,7 @@ letters6card = "#abcdefghijklmnopqrstuvwxyz_23456789" letters7 = "_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()" letters7card = "0abcdefghijklmnopqrstuvwxyz_.,-+*/:?!'()123456789" + def missing_letters(s,t): return ''.join(sorted(set(c for c in s if c not in t))) -- cgit v1.2.3 From 2076f1b57b95b00807c8b00020227527bd6fd063 Mon Sep 17 00:00:00 2001 From: Trevor Terris Date: Thu, 22 Apr 2021 18:58:23 -0400 Subject: Change indexing to make card ordering more intuitive Update the indexing so that the table starts at "1". This way the ordered card layout (used for key generation) starts with the Ace of Diamonds and proceeds through the cards and suits as normal. This seems cleaner than awkwardly prepending the 10 of Spades. However, it involves a slight tweak to the key key_derive function to support the change in card order. --- README.md | 29 +++++++++++++++-------------- lc4.py | 8 +++++--- 2 files changed, 20 insertions(+), 17 deletions(-) (limited to 'lc4.py') diff --git a/README.md b/README.md index 1568b5f..9487cfb 100644 --- a/README.md +++ b/README.md @@ -206,16 +206,17 @@ cards could be more innocuous and easily explainable to the secret police than a set of peculiar numbered tiles. ``` -0 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 _ -. , - + * / : -? ! ' ( ) 1 2 -3 4 5 6 7 8 9 +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 _ . +, - + * / : ? +! ' ( ) 1 2 3 +4 5 6 7 8 9 0 ``` -With this layout, the following mapping to playing cards is used: +**This board uses a 1-based index**, so `a=1`, `b=2`, and so on. With this layout, +the following mapping to playing cards is used: | **Character** | Card | Index | **Character** | Card | Index | **Character** | Card | Index | **Character** | Card | Index | |-----------|------|-------|-----------|------|-------|-----------|------|-------|-----------|------|--------| @@ -242,12 +243,12 @@ Heart is left as an exercise for the reader. For LC4, the following board could be used: ``` -# 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 _ 2 3 -4 5 6 7 8 9 +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 _ 2 3 4 +5 6 7 8 9 # ``` The "Hearts" suit would be ommitted from the card mapping table, and the index diff --git a/lc4.py b/lc4.py index 5a2785f..fea2f7a 100644 --- a/lc4.py +++ b/lc4.py @@ -151,9 +151,11 @@ def rotate_marker_down(m, col, n): return ((m[0] + n) % size, m[1]) -def derive_key(password): +def derive_key(password, one_indexed): i = 0 k = letters + # if using one-indexed arrays, moves the zero element to the end + if one_indexed: k = k[1:]+k[0] for c in password: (row, col) = find_ix(c) k = rotate_down(rotate_right(k, i, col), i, row) @@ -295,7 +297,7 @@ def test1(size, fixednonce): else: keyword = 's3cret_p4ssw0rd/31337' szkeyword = keyword # This statement needed to show keyword in printinfo() [don't change args.keywordstring within test1()!] - key = derive_key(keyword) + key = derive_key(keyword, false) else: key = letters initialkey = key @@ -433,7 +435,7 @@ if __name__ == '__main__': if args.keywordfile: args.keywordstring = open(args.keywordfile, 'r').read().rstrip('\r\n') if args.keywordstring: szkeyword = args.keywordstring - key = derive_key(args.keywordstring) + key = derive_key(args.keywordstring, args.playingcard) if args.keyfile: args.keystring = open(args.keyfile, 'r').read().rstrip('\r\n') if args.keystring: key = args.keystring; -- cgit v1.2.3