Index: third_party/gsutil/third_party/rsa/rsa/cli.py |
diff --git a/third_party/gsutil/third_party/rsa/rsa/cli.py b/third_party/gsutil/third_party/rsa/rsa/cli.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..527cc4979a8287a13e9a6562f05c625def99d2fc |
--- /dev/null |
+++ b/third_party/gsutil/third_party/rsa/rsa/cli.py |
@@ -0,0 +1,379 @@ |
+# -*- coding: utf-8 -*- |
+# |
+# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> |
+# |
+# Licensed under the Apache License, Version 2.0 (the "License"); |
+# you may not use this file except in compliance with the License. |
+# You may obtain a copy of the License at |
+# |
+# http://www.apache.org/licenses/LICENSE-2.0 |
+# |
+# Unless required by applicable law or agreed to in writing, software |
+# distributed under the License is distributed on an "AS IS" BASIS, |
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+# See the License for the specific language governing permissions and |
+# limitations under the License. |
+ |
+'''Commandline scripts. |
+ |
+These scripts are called by the executables defined in setup.py. |
+''' |
+ |
+from __future__ import with_statement, print_function |
+ |
+import abc |
+import sys |
+from optparse import OptionParser |
+ |
+import rsa |
+import rsa.bigfile |
+import rsa.pkcs1 |
+ |
+HASH_METHODS = sorted(rsa.pkcs1.HASH_METHODS.keys()) |
+ |
+def keygen(): |
+ '''Key generator.''' |
+ |
+ # Parse the CLI options |
+ parser = OptionParser(usage='usage: %prog [options] keysize', |
+ description='Generates a new RSA keypair of "keysize" bits.') |
+ |
+ parser.add_option('--pubout', type='string', |
+ help='Output filename for the public key. The public key is ' |
+ 'not saved if this option is not present. You can use ' |
+ 'pyrsa-priv2pub to create the public key file later.') |
+ |
+ parser.add_option('-o', '--out', type='string', |
+ help='Output filename for the private key. The key is ' |
+ 'written to stdout if this option is not present.') |
+ |
+ parser.add_option('--form', |
+ help='key format of the private and public keys - 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) |
+ |
+ try: |
+ keysize = int(cli_args[0]) |
+ except ValueError: |
+ parser.print_help() |
+ print('Not a valid number: %s' % cli_args[0], file=sys.stderr) |
+ raise SystemExit(1) |
+ |
+ print('Generating %i-bit key' % keysize, file=sys.stderr) |
+ (pub_key, priv_key) = rsa.newkeys(keysize) |
+ |
+ |
+ # Save public key |
+ if cli.pubout: |
+ print('Writing public key to %s' % cli.pubout, file=sys.stderr) |
+ data = pub_key.save_pkcs1(format=cli.form) |
+ with open(cli.pubout, 'wb') as outfile: |
+ outfile.write(data) |
+ |
+ # Save private key |
+ data = priv_key.save_pkcs1(format=cli.form) |
+ |
+ if cli.out: |
+ print('Writing private key to %s' % cli.out, file=sys.stderr) |
+ with open(cli.out, 'wb') as outfile: |
+ outfile.write(data) |
+ else: |
+ print('Writing private key to stdout', file=sys.stderr) |
+ sys.stdout.write(data) |
+ |
+ |
+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.' |
+ expected_cli_args = 1 |
+ has_output = True |
+ |
+ 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, cli_args=None): |
+ '''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(self.operation_progressive.title(), file=sys.stderr) |
+ outdata = self.perform_operation(indata, key, cli_args) |
+ |
+ if self.has_output: |
+ self.write_outfile(outdata, cli.output) |
+ |
+ def parse_cli(self): |
+ '''Parse the CLI options |
+ |
+ :returns: (cli_opts, cli_args) |
+ ''' |
+ |
+ parser = OptionParser(usage=self.usage, description=self.description) |
+ |
+ parser.add_option('-i', '--input', type='string', help=self.input_help) |
+ |
+ if self.has_output: |
+ parser.add_option('-o', '--output', type='string', help=self.output_help) |
+ |
+ parser.add_option('--keyform', |
+ help='Key format of the %s key - default PEM' % self.keyname, |
+ choices=('PEM', 'DER'), default='PEM') |
+ |
+ (cli, cli_args) = parser.parse_args(sys.argv[1:]) |
+ |
+ if len(cli_args) != self.expected_cli_args: |
+ parser.print_help() |
+ raise SystemExit(1) |
+ |
+ return (cli, cli_args) |
+ |
+ def read_key(self, filename, keyform): |
+ '''Reads a public or private key.''' |
+ |
+ print('Reading %s key from %s' % (self.keyname, filename), file=sys.stderr) |
+ with open(filename, 'rb') 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('Reading input from %s' % inname, file=sys.stderr) |
+ with open(inname, 'rb') as infile: |
+ return infile.read() |
+ |
+ print('Reading input from stdin', file=sys.stderr) |
+ return sys.stdin.read() |
+ |
+ def write_outfile(self, outdata, outname): |
+ '''Write the output file''' |
+ |
+ if outname: |
+ print('Writing output to %s' % outname, file=sys.stderr) |
+ with open(outname, 'wb') as outfile: |
+ outfile.write(outdata) |
+ else: |
+ print('Writing output to stdout', file=sys.stderr) |
+ 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, cli_args=None): |
+ '''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, cli_args=None): |
+ '''Decrypts files.''' |
+ |
+ return rsa.decrypt(indata, priv_key) |
+ |
+class SignOperation(CryptoOperation): |
+ '''Signs a file.''' |
+ |
+ keyname = 'private' |
+ usage = 'usage: %%prog [options] private_key hash_method' |
+ description = ('Signs a file, outputs the signature. Choose the hash ' |
+ 'method from %s' % ', '.join(HASH_METHODS)) |
+ operation = 'sign' |
+ operation_past = 'signature' |
+ operation_progressive = 'Signing' |
+ key_class = rsa.PrivateKey |
+ expected_cli_args = 2 |
+ |
+ output_help = ('Name of the file to write the signature to. Written ' |
+ 'to stdout if this option is not present.') |
+ |
+ def perform_operation(self, indata, priv_key, cli_args): |
+ '''Decrypts files.''' |
+ |
+ hash_method = cli_args[1] |
+ if hash_method not in HASH_METHODS: |
+ raise SystemExit('Invalid hash method, choose one of %s' % |
+ ', '.join(HASH_METHODS)) |
+ |
+ return rsa.sign(indata, priv_key, hash_method) |
+ |
+class VerifyOperation(CryptoOperation): |
+ '''Verify a signature.''' |
+ |
+ keyname = 'public' |
+ usage = 'usage: %%prog [options] public_key signature_file' |
+ description = ('Verifies a signature, exits with status 0 upon success, ' |
+ 'prints an error message and exits with status 1 upon error.') |
+ operation = 'verify' |
+ operation_past = 'verified' |
+ operation_progressive = 'Verifying' |
+ key_class = rsa.PublicKey |
+ expected_cli_args = 2 |
+ has_output = False |
+ |
+ def perform_operation(self, indata, pub_key, cli_args): |
+ '''Decrypts files.''' |
+ |
+ signature_file = cli_args[1] |
+ |
+ with open(signature_file, 'rb') as sigfile: |
+ signature = sigfile.read() |
+ |
+ try: |
+ rsa.verify(indata, signature, pub_key) |
+ except rsa.VerificationError: |
+ raise SystemExit('Verification failed.') |
+ |
+ print('Verification OK', file=sys.stderr) |
+ |
+ |
+class BigfileOperation(CryptoOperation): |
+ '''CryptoOperation that doesn't read the entire file into memory.''' |
+ |
+ def __init__(self): |
+ CryptoOperation.__init__(self) |
+ |
+ self.file_objects = [] |
+ |
+ def __del__(self): |
+ '''Closes any open file handles.''' |
+ |
+ for fobj in self.file_objects: |
+ fobj.close() |
+ |
+ def __call__(self): |
+ '''Runs the program.''' |
+ |
+ (cli, cli_args) = self.parse_cli() |
+ |
+ key = self.read_key(cli_args[0], cli.keyform) |
+ |
+ # Get the file handles |
+ infile = self.get_infile(cli.input) |
+ outfile = self.get_outfile(cli.output) |
+ |
+ # Call the operation |
+ print(self.operation_progressive.title(), file=sys.stderr) |
+ self.perform_operation(infile, outfile, key, cli_args) |
+ |
+ def get_infile(self, inname): |
+ '''Returns the input file object''' |
+ |
+ if inname: |
+ print('Reading input from %s' % inname, file=sys.stderr) |
+ fobj = open(inname, 'rb') |
+ self.file_objects.append(fobj) |
+ else: |
+ print('Reading input from stdin', file=sys.stderr) |
+ fobj = sys.stdin |
+ |
+ return fobj |
+ |
+ def get_outfile(self, outname): |
+ '''Returns the output file object''' |
+ |
+ if outname: |
+ print('Will write output to %s' % outname, file=sys.stderr) |
+ fobj = open(outname, 'wb') |
+ self.file_objects.append(fobj) |
+ else: |
+ print('Will write output to stdout', file=sys.stderr) |
+ fobj = sys.stdout |
+ |
+ return fobj |
+ |
+class EncryptBigfileOperation(BigfileOperation): |
+ '''Encrypts a file to VARBLOCK format.''' |
+ |
+ keyname = 'public' |
+ description = ('Encrypts a file to an encrypted VARBLOCK file. The file ' |
+ 'can be larger than the key length, but the output file is only ' |
+ 'compatible with Python-RSA.') |
+ operation = 'encrypt' |
+ operation_past = 'encrypted' |
+ operation_progressive = 'encrypting' |
+ |
+ def perform_operation(self, infile, outfile, pub_key, cli_args=None): |
+ '''Encrypts files to VARBLOCK.''' |
+ |
+ return rsa.bigfile.encrypt_bigfile(infile, outfile, pub_key) |
+ |
+class DecryptBigfileOperation(BigfileOperation): |
+ '''Decrypts a file in VARBLOCK format.''' |
+ |
+ keyname = 'private' |
+ description = ('Decrypts an encrypted VARBLOCK file that was encrypted ' |
+ 'with pyrsa-encrypt-bigfile') |
+ operation = 'decrypt' |
+ operation_past = 'decrypted' |
+ operation_progressive = 'decrypting' |
+ key_class = rsa.PrivateKey |
+ |
+ def perform_operation(self, infile, outfile, priv_key, cli_args=None): |
+ '''Decrypts a VARBLOCK file.''' |
+ |
+ return rsa.bigfile.decrypt_bigfile(infile, outfile, priv_key) |
+ |
+ |
+encrypt = EncryptOperation() |
+decrypt = DecryptOperation() |
+sign = SignOperation() |
+verify = VerifyOperation() |
+encrypt_bigfile = EncryptBigfileOperation() |
+decrypt_bigfile = DecryptBigfileOperation() |
+ |