diff options
author | Sybren A. Stüvel <sybren@stuvel.eu> | 2011-07-31 22:30:18 +0200 |
---|---|---|
committer | Sybren A. Stüvel <sybren@stuvel.eu> | 2011-07-31 22:30:18 +0200 |
commit | 1d15b0b78c316a4255f40e6a555d3d5198d4496c (patch) | |
tree | 8d045eb65c47bcda854449d5b18cb6e31355fb6b /rsa/cli.py | |
parent | cca6be62e368d889860563b727c7528ce1d54072 (diff) | |
download | rsa-git-1d15b0b78c316a4255f40e6a555d3d5198d4496c.tar.gz |
Added encrypt and decrypt CLI commands
Diffstat (limited to 'rsa/cli.py')
-rw-r--r-- | rsa/cli.py | 149 |
1 files changed, 148 insertions, 1 deletions
@@ -19,6 +19,7 @@ These scripts are called by the executables defined in setup.py. ''' +import abc import sys from optparse import OptionParser @@ -80,4 +81,150 @@ def keygen(): print >>sys.stderr, 'Writing private key to stdout' sys.stdout.write(data) -# vim: foldnestmax=1 + +class CryptoOperation(object): + '''CLI callable that operates with input, output, and a key.''' + + __metaclass__ = abc.ABCMeta + + keyname = 'public' # or 'private' + usage = 'usage: %%prog [options] %(keyname)s_key' + description = None + operation = 'decrypt' + operation_past = 'decrypted' + operation_progressive = 'decrypting' + input_help = 'Name of the file to %(operation)s. Reads from stdin if ' \ + 'not specified.' + output_help = 'Name of the file to write the %(operation_past)s file ' \ + 'to. Written to stdout if this option is not present.' + + key_class = rsa.PublicKey + + def __init__(self): + self.usage = self.usage % self.__class__.__dict__ + self.input_help = self.input_help % self.__class__.__dict__ + self.output_help = self.output_help % self.__class__.__dict__ + + @abc.abstractmethod + def perform_operation(self, indata, key): + '''Performs the program's operation. + + Implement in a subclass. + + :returns: the data to write to the output. + ''' + + def __call__(self): + '''Runs the program.''' + + (cli, cli_args) = self.parse_cli() + + key = self.read_key(cli_args[0], cli.keyform) + + indata = self.read_infile(cli.input) + + print >>sys.stderr, self.operation_progressive.title() + outdata = self.perform_operation(indata, key) + + self.write_outfile(outdata, cli.output) + + def parse_cli(self): + '''Parse the CLI options + + :returns: (cli_opts, cli_args) + ''' + + parser = OptionParser(usage='usage: %prog [options] public_key', + description='Encrypts a file. The file must be shorter than the ' + 'key length in order to be encrypted. For larger files, use the ' + 'pyrsa-encrypt-bigfile command.') + + parser.add_option('--input', type='string', + help='Name of the file to encrypt. Reads from stdin if ' + 'not specified.') + + parser.add_option('--output', type='string', + help='Name of the file to write the encrypted file to. ' + 'Written to stdout if this option is not present.') + + parser.add_option('--keyform', + help='Key format of the key - default PEM', + choices=('PEM', 'DER'), default='PEM') + + (cli, cli_args) = parser.parse_args(sys.argv[1:]) + + if len(cli_args) != 1: + parser.print_help() + raise SystemExit(1) + + return (cli, cli_args) + + def read_key(self, filename, keyform): + '''Reads a public or private key.''' + + print >>sys.stderr, 'Reading %s key from %s' % (self.keyname, filename) + with open(filename) as keyfile: + keydata = keyfile.read() + + return self.key_class.load_pkcs1(keydata, keyform) + + def read_infile(self, inname): + '''Read the input file''' + + if inname: + print >>sys.stderr, 'Reading input from %s' % inname + with open(inname, 'rb') as infile: + return infile.read() + + print >>sys.stderr, 'Reading input from stdin' + return sys.stdin.read() + + def write_outfile(self, outdata, outname): + '''Write the output file''' + + if outname: + print >>sys.stderr, 'Writing output to %s' % outname + with open(outname, 'wb') as outfile: + outfile.write(outdata) + else: + print >>sys.stderr, 'Writing output to stdout' + sys.stdout.write(outdata) + +class EncryptOperation(CryptoOperation): + '''Encrypts a file.''' + + keyname = 'public' + description = ('Encrypts a file. The file must be shorter than the key ' + 'length in order to be encrypted. For larger files, use the ' + 'pyrsa-encrypt-bigfile command.') + operation = 'encrypt' + operation_past = 'encrypted' + operation_progressive = 'encrypting' + + + def perform_operation(self, indata, pub_key): + '''Encrypts files.''' + + return rsa.encrypt(indata, pub_key) + +class DecryptOperation(CryptoOperation): + '''Decrypts a file.''' + + keyname = 'private' + description = ('Decrypts a file. The original file must be shorter than ' + 'the key length in order to have been encrypted. For larger ' + 'files, use the pyrsa-decrypt-bigfile command.') + operation = 'decrypt' + operation_past = 'decrypted' + operation_progressive = 'decrypting' + key_class = rsa.PrivateKey + + def perform_operation(self, indata, priv_key): + '''Decrypts files.''' + + return rsa.decrypt(indata, priv_key) + +encrypt = EncryptOperation() +decrypt = DecryptOperation() + + |