#!/usr/bin/env python '''A CipherSaber-2 implementation by Magnus Lie Hetland , 5 Feb 2002, based on an original CipherSaber-1 implementation by by Ka-Ping Yee . Unlike the original, ASCII armour is used, and getpass is used to read the password if it is not supplied on the commandline. Therefore explicit filenames are used instead of stdin and stdout. For more information about CipherSaber, see http://ciphersaber.gurus.com For a list of implementations, see http://www.xs4all.nl/~cg/ciphersaber''' import sys, random, getpass def arcfour(input, key, n=20): '''Perform the ARCFOUR algorithm on a given input list of bytes with a key given as a list of bytes, and return the output as a list of bytes.''' i, j, state = 0, 0, range(256) for k in range(n): for i in range(256): j = (j + state[i] + key[i % len(key)]) % 256 state[i], state[j] = state[j], state[i] i, j, output = 0, 0, [] for byte in input: i = (i + 1) % 256 j = (j + state[i]) % 256 state[i], state[j] = state[j], state[i] n = (state[i] + state[j]) % 256 output.append(byte ^ state[n]) return output def b2a(text): 'Given a string of binary data, return an "armoured" string.' lines = [] words = ['%02x' % o for o in map(ord, text)] while words: lines.append(' '.join(words[:23])) del words[:23] return '\n'.join(lines) def a2b(text): 'Given an "armoured" string, return a string of binary data.' return ''.join(map(chr, [int(w, 16) for w in text.split()])) def encipher(plaintext, key, iv=""): 'Given a plaintext string and key, return an enciphered string.' while len(iv) < 10: iv = iv + chr(random.randrange(256)) bytes = arcfour(map(ord, plaintext), map(ord, key + iv)) return iv + ''.join(map(chr, bytes)) def decipher(ciphertext, key): 'Given a ciphertext string and key, return the deciphered string.' iv, ciphertext = ciphertext[:10], ciphertext[10:] bytes = arcfour(map(ord, ciphertext), map(ord, key + iv)) return ''.join(map(chr, bytes)) if __name__ == "__main__": if len(sys.argv) < 4 or sys.argv[1] not in ["-d", "-e"]: sys.stderr.write("usage: %s [-d | -e] [[] ] \n" % sys.argv[0]) sys.exit(1) if len(sys.argv) == 6: n = int(sys.argv[2]) else: n = 20 if len(sys.argv) > 4: key = sys.argv[-3] else: key = getpass.getpass('Key: ') output = open(sys.argv[-1], 'w') if sys.argv[1] == "-d": output.write(decipher(a2b(open(sys.argv[-2]).read()), key)) elif sys.argv[1] == "-e": output.write(b2a(encipher(open(sys.argv[-2]).read(), key))) output.close()