diff options
| author | Mirek Kratochvil <exa.exa@gmail.com> | 2017-10-12 12:37:01 +0200 |
|---|---|---|
| committer | Mirek Kratochvil <exa.exa@gmail.com> | 2017-10-12 12:37:37 +0200 |
| commit | ab443e8ef2259290697bcb1b845861e7af742dc2 (patch) | |
| tree | c180fe1458752dc0ea5b9b9fd1054c5af9bb35f4 /programs | |
| parent | 700fe080c5253bbda79201d32179a499b3a2a0ad (diff) | |
| download | ls47-ab443e8ef2259290697bcb1b845861e7af742dc2.tar.gz ls47-ab443e8ef2259290697bcb1b845861e7af742dc2.tar.bz2 | |
reference the python code
Diffstat (limited to 'programs')
| -rwxr-xr-x | programs/ls47.py | 159 |
1 files changed, 0 insertions, 159 deletions
diff --git a/programs/ls47.py b/programs/ls47.py deleted file mode 100755 index 41a1405..0000000 --- a/programs/ls47.py +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/python2 -# -*- coding: utf-8 -*- - -import random - -letters = "_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()" -tiles = zip(letters, map(lambda x: (x / 7, x % 7), range(7 * 7))) -padding_size = 10 - - -def check_key(key): - if len(key) != len(letters): - raise ValueError('Wrong key size') - cnts = {} - for c in letters: - cnts[c] = 0 - for c in key: - if not c in cnts: - raise ValueError('Letter ' + c + ' not in LS47!') - cnts[c] += 1 - if cnts[c] > 1: - raise ValueError('Letter ' + c + ' duplicated in key!') - - -def find_ix(letter): - m = filter(lambda (l, pos): l == letter, tiles) - if len(m) != 1: - raise ValueError('Letter ' + letter + ' not in LS47!') - for (l, pos) in m: - return pos - - -def find_pos(key, letter): - p = key.find(letter) - if p >= 0 and p < 7 * 7: - return (p / 7, p % 7) - raise ValueError('Letter ' + letter + ' not in key?!') - - -def add_pos((ax, ay), (bx, by)): - return ((ax + bx) % 7, (ay + by) % 7) - - -def sub_pos((ax, ay), (bx, by)): - return ((ax - bx) % 7, (ay - by) % 7) - - -def find_at_pos(key, (row, col)): - return key[col + row * 7] - - -def rotate_right(key, row, n): - mid = key[7 * row:7 * (row + 1)] - n = (7 - n % 7) % 7 - return key[:7 * row] + mid[n:] + mid[:n] + key[7 * (row + 1):] - - -def rotate_down(key, col, n): - lines = map(lambda i: key[i * 7:(i + 1) * 7], range(7)) - lefts = map(lambda l: l[:col], lines) - mids = map(lambda l: l[col], lines) - rights = map(lambda l: l[col + 1:], lines) - n = (7 - n % 7) % 7 - mids = mids[n:] + mids[:n] - return reduce(lambda a, b: a + b, map(lambda i: lefts[i] + mids[i] \ - + rights[i], range(7))) - - -def rotate_marker_right((mrow, mcol), row, n): - if mrow != row: - return (mrow, mcol) - else: - return (mrow, (mcol + n) % 7) - - -def rotate_marker_down((mrow, mcol), col, n): - if mcol != col: - return (mrow, mcol) - else: - return ((mrow + n) % 7, mcol) - - -def derive_key(password): - i = 0 - k = letters - for c in password: - (row, col) = find_ix(c) - k = rotate_down(rotate_right(k, i, col), i, row) - i = (i + 1) % 7 - return k - - -def encrypt(key, plaintext): - check_key(key) - mp = (0, 0) - ciphertext = '' - for p in plaintext: - pp = find_pos(key, p) - mix = find_ix(find_at_pos(key, mp)) - cp = add_pos(pp, mix) - c = find_at_pos(key, cp) - ciphertext += c - - key = rotate_right(key, pp[0], 1) - mp = rotate_marker_right(mp, pp[0], 1) - cp = find_pos(key, c) - key = rotate_down(key, cp[1], 1) - mp = rotate_marker_down(mp, cp[1], 1) - mp = add_pos(mp, find_ix(c)) - return ciphertext - - -def decrypt(key, ciphertext): - check_key(key) - mp = (0, 0) - plaintext = '' - for c in ciphertext: - cp = find_pos(key, c) - mix = find_ix(find_at_pos(key, mp)) - pp = sub_pos(cp, mix) - p = find_at_pos(key, pp) - plaintext += p - - key = rotate_right(key, pp[0], 1) - mp = rotate_marker_right(mp, pp[0], 1) - cp = find_pos(key, c) - key = rotate_down(key, cp[1], 1) - mp = rotate_marker_down(mp, cp[1], 1) - mp = add_pos(mp, find_ix(c)) - return plaintext - - -def encrypt_pad(key, plaintext, signature): - - # TODO it would also be great to randomize the message length. - - check_key(key) - padding = ''.join(map(lambda x: letters[random.randint(0, - len(letters) - 1)], range(padding_size))) - - return encrypt(key, padding + plaintext + '---' + signature) - - -def decrypt_pad(key, ciphertext): - check_key(key) - return decrypt(key, ciphertext)[padding_size:] - - -if __name__ == '__main__': - - # a bit of test! - - key = derive_key('s3cret_p4ssw0rd/31337') - print 'key:', key - enc = encrypt_pad(key, 'conflagrate_the_rose_bush_at_six!', - 'peace-vector-3') - print 'encrypted:', enc - dec = decrypt_pad(key, enc) - print 'decrypted:', dec |
