aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/rsa/cli.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/rsa/cli.py')
-rw-r--r--.venv/lib/python3.12/site-packages/rsa/cli.py321
1 files changed, 321 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/rsa/cli.py b/.venv/lib/python3.12/site-packages/rsa/cli.py
new file mode 100644
index 00000000..5a6b6506
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/rsa/cli.py
@@ -0,0 +1,321 @@
+# 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
+#
+# https://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.
+"""
+
+import abc
+import sys
+import typing
+import optparse
+
+import rsa
+import rsa.key
+import rsa.pkcs1
+
+HASH_METHODS = sorted(rsa.pkcs1.HASH_METHODS.keys())
+Indexable = typing.Union[typing.Tuple, typing.List[str]]
+
+
+def keygen() -> None:
+ """Key generator."""
+
+ # Parse the CLI options
+ parser = optparse.OptionParser(
+ usage="usage: %prog [options] keysize",
+ description='Generates a new RSA key pair 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 as ex:
+ parser.print_help()
+ print("Not a valid number: %s" % cli_args[0], file=sys.stderr)
+ raise SystemExit(1) from ex
+
+ 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.buffer.write(data)
+
+
+class CryptoOperation(metaclass=abc.ABCMeta):
+ """CLI callable that operates with input, output, and a key."""
+
+ keyname = "public" # or 'private'
+ usage = "usage: %%prog [options] %(keyname)s_key"
+ description = ""
+ 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 # type: typing.Type[rsa.key.AbstractKey]
+
+ def __init__(self) -> None:
+ 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: bytes, key: rsa.key.AbstractKey, cli_args: Indexable
+ ) -> typing.Any:
+ """Performs the program's operation.
+
+ Implement in a subclass.
+
+ :returns: the data to write to the output.
+ """
+
+ def __call__(self) -> None:
+ """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) -> typing.Tuple[optparse.Values, typing.List[str]]:
+ """Parse the CLI options
+
+ :returns: (cli_opts, cli_args)
+ """
+
+ parser = optparse.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: str, keyform: str) -> rsa.key.AbstractKey:
+ """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: str) -> bytes:
+ """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.buffer.read()
+
+ def write_outfile(self, outdata: bytes, outname: str) -> None:
+ """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.buffer.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."
+ )
+ operation = "encrypt"
+ operation_past = "encrypted"
+ operation_progressive = "encrypting"
+
+ def perform_operation(
+ self, indata: bytes, pub_key: rsa.key.AbstractKey, cli_args: Indexable = ()
+ ) -> bytes:
+ """Encrypts files."""
+ assert isinstance(pub_key, rsa.key.PublicKey)
+ 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."
+ )
+ operation = "decrypt"
+ operation_past = "decrypted"
+ operation_progressive = "decrypting"
+ key_class = rsa.PrivateKey
+
+ def perform_operation(
+ self, indata: bytes, priv_key: rsa.key.AbstractKey, cli_args: Indexable = ()
+ ) -> bytes:
+ """Decrypts files."""
+ assert isinstance(priv_key, rsa.key.PrivateKey)
+ 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: bytes, priv_key: rsa.key.AbstractKey, cli_args: Indexable
+ ) -> bytes:
+ """Signs files."""
+ assert isinstance(priv_key, rsa.key.PrivateKey)
+
+ 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: bytes, pub_key: rsa.key.AbstractKey, cli_args: Indexable
+ ) -> None:
+ """Verifies files."""
+ assert isinstance(pub_key, rsa.key.PublicKey)
+
+ 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 as ex:
+ raise SystemExit("Verification failed.") from ex
+
+ print("Verification OK", file=sys.stderr)
+
+
+encrypt = EncryptOperation()
+decrypt = DecryptOperation()
+sign = SignOperation()
+verify = VerifyOperation()