| Index: third_party/gsutil/third_party/rsa/doc/usage.rst
|
| diff --git a/third_party/gsutil/third_party/rsa/doc/usage.rst b/third_party/gsutil/third_party/rsa/doc/usage.rst
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8a736fb476d50ce8d8e5acfdba40a86e4c4f1460
|
| --- /dev/null
|
| +++ b/third_party/gsutil/third_party/rsa/doc/usage.rst
|
| @@ -0,0 +1,328 @@
|
| +.. _usage:
|
| +
|
| +Usage
|
| +==================================================
|
| +
|
| +This section describes the usage of the Python-RSA module.
|
| +
|
| +Before you can use RSA you need keys. You will receive a private key
|
| +and a public key.
|
| +
|
| +.. important::
|
| +
|
| + The private key is called *private* for a reason. Never share this
|
| + key with anyone.
|
| +
|
| +The public key is used for encypting a message such that it can only
|
| +be read by the owner of the private key. As such it's also referred to
|
| +as the *encryption key*. Decrypting a message can only be done using
|
| +the private key, hence it's also called the *decryption key*.
|
| +
|
| +The private key is used for signing a message. With this signature and
|
| +the public key, the receiver can verifying that a message was signed
|
| +by the owner of the private key, and that the message was not modified
|
| +after signing.
|
| +
|
| +Generating keys
|
| +--------------------------------------------------
|
| +
|
| +You can use the :py:func:`rsa.newkeys` function to create a keypair:
|
| +
|
| + >>> (pubkey, privkey) = rsa.newkeys(512)
|
| +
|
| +Alternatively you can use :py:meth:`rsa.PrivateKey.load_pkcs1` and
|
| +:py:meth:`rsa.PublicKey.load_pkcs1` to load keys from a file:
|
| +
|
| + >>> with open('private.pem') as privatefile:
|
| + ... keydata = privatefile.read()
|
| + >>> pubkey = rsa.PrivateKey.load_pkcs1(keydata)
|
| +
|
| +
|
| +Time to generate a key
|
| +++++++++++++++++++++++++++++++++++++++++
|
| +
|
| +Generating a keypair may take a long time, depending on the number of
|
| +bits required. The number of bits determines the cryptographic
|
| +strength of the key, as well as the size of the message you can
|
| +encrypt. If you don't mind having a slightly smaller key than you
|
| +requested, you can pass ``accurate=False`` to speed up the key
|
| +generation process.
|
| +
|
| +Another way to speed up the key generation process is to use multiple
|
| +processes in parallel to speed up the key generation. Use no more than
|
| +the number of processes that your machine can run in parallel; a
|
| +dual-core machine should use ``poolsize=2``; a quad-core
|
| +hyperthreading machine can run two threads on each core, and thus can
|
| +use ``poolsize=8``.
|
| +
|
| + >>> (pubkey, privkey) = rsa.newkeys(512, poolsize=8)
|
| +
|
| +These are some average timings from my desktop machine (Linux 2.6,
|
| +2.93 GHz quad-core Intel Core i7, 16 GB RAM) using 64-bit CPython 2.7.
|
| +Since key generation is a random process, times may differ even on
|
| +similar hardware. On all tests, we used the default ``accurate=True``.
|
| +
|
| ++----------------+------------------+------------------+
|
| +| Keysize (bits) | single process | eight processes |
|
| ++================+==================+==================+
|
| +| 128 | 0.01 sec. | 0.01 sec. |
|
| ++----------------+------------------+------------------+
|
| +| 256 | 0.03 sec. | 0.02 sec. |
|
| ++----------------+------------------+------------------+
|
| +| 384 | 0.09 sec. | 0.04 sec. |
|
| ++----------------+------------------+------------------+
|
| +| 512 | 0.11 sec. | 0.07 sec. |
|
| ++----------------+------------------+------------------+
|
| +| 1024 | 0.79 sec. | 0.30 sec. |
|
| ++----------------+------------------+------------------+
|
| +| 2048 | 6.55 sec. | 1.60 sec. |
|
| ++----------------+------------------+------------------+
|
| +| 3072 | 23.4 sec. | 7.14 sec. |
|
| ++----------------+------------------+------------------+
|
| +| 4096 | 72.0 sec. | 24.4 sec. |
|
| ++----------------+------------------+------------------+
|
| +
|
| +If key generation is too slow for you, you could use OpenSSL to
|
| +generate them for you, then load them in your Python code. OpenSSL
|
| +generates a 4096-bit key in 3.5 seconds on the same machine as used
|
| +above. See :ref:`openssl` for more information.
|
| +
|
| +Key size requirements
|
| +--------------------------------------------------
|
| +
|
| +Python-RSA version 3.0 introduced PKCS#1-style random padding. This
|
| +means that 11 bytes (88 bits) of your key are no longer usable for
|
| +encryption, so keys smaller than this are unusable. The larger the
|
| +key, the higher the security.
|
| +
|
| +Creating signatures also requires a key of a certain size, depending
|
| +on the used hash method:
|
| +
|
| ++-------------+-----------------------------------+
|
| +| Hash method | Suggested minimum key size (bits) |
|
| ++=============+===================================+
|
| +| MD5 | 360 |
|
| ++-------------+-----------------------------------+
|
| +| SHA-1 | 368 |
|
| ++-------------+-----------------------------------+
|
| +| SHA-256 | 496 |
|
| ++-------------+-----------------------------------+
|
| +| SHA-384 | 624 |
|
| ++-------------+-----------------------------------+
|
| +| SHA-512 | 752 |
|
| ++-------------+-----------------------------------+
|
| +
|
| +
|
| +
|
| +Encryption and decryption
|
| +--------------------------------------------------
|
| +
|
| +To encrypt or decrypt a message, use :py:func:`rsa.encrypt` resp.
|
| +:py:func:`rsa.decrypt`. Let's say that Alice wants to send a message
|
| +that only Bob can read.
|
| +
|
| +#. Bob generates a keypair, and gives the public key to Alice. This is
|
| + done such that Alice knows for sure that the key is really Bob's
|
| + (for example by handing over a USB stick that contains the key).
|
| +
|
| + >>> (bob_pub, bob_priv) = rsa.newkeys(512)
|
| +
|
| +#. Alice writes a message
|
| +
|
| + >>> message = 'hello Bob!'
|
| +
|
| +#. Alice encrypts the message using Bob's public key, and sends the
|
| + encrypted message.
|
| +
|
| + >>> crypto = rsa.encrypt(message, bob_pub)
|
| +
|
| +#. Bob receives the message, and decrypts it with his private key.
|
| +
|
| + >>> message = rsa.decrypt(crypto, bob_priv)
|
| + >>> print message
|
| + hello Bob!
|
| +
|
| +Since Bob kept his private key *private*, Alice can be sure that he is
|
| +the only one who can read the message. Bob does *not* know for sure
|
| +that it was Alice that sent the message, since she didn't sign it.
|
| +
|
| +
|
| +RSA can only encrypt messages that are smaller than the key. A couple
|
| +of bytes are lost on random padding, and the rest is available for the
|
| +message itself. For example, a 512-bit key can encode a 53-byte
|
| +message (512 bit = 64 bytes, 11 bytes are used for random padding and
|
| +other stuff). See :ref:`bigfiles` for information on how to work with
|
| +larger files.
|
| +
|
| +Altering the encrypted information will *likely* cause a
|
| +:py:class:`rsa.pkcs1.DecryptionError`. If you want to be *sure*, use
|
| +:py:func:`rsa.sign`.
|
| +
|
| + >>> crypto = encrypt('hello', pub_key)
|
| + >>> crypto = 'X' + crypto[1:] # change the first byte
|
| + >>> decrypt(crypto, priv_key)
|
| + Traceback (most recent call last):
|
| + ...
|
| + rsa.pkcs1.DecryptionError: Decryption failed
|
| +
|
| +
|
| +.. warning::
|
| +
|
| + Never display the stack trace of a
|
| + :py:class:`rsa.pkcs1.DecryptionError` exception. It shows where
|
| + in the code the exception occurred, and thus leaks information
|
| + about the key. It’s only a tiny bit of information, but every bit
|
| + makes cracking the keys easier.
|
| +
|
| +Low-level operations
|
| +++++++++++++++++++++++++++++++
|
| +
|
| +The core RSA algorithm operates on large integers. These operations
|
| +are considered low-level and are supported by the
|
| +:py:func:`rsa.core.encrypt_int` and :py:func:`rsa.core.decrypt_int`
|
| +functions.
|
| +
|
| +Signing and verification
|
| +--------------------------------------------------
|
| +
|
| +You can create a detached signature for a message using the
|
| +:py:func:`rsa.sign` function:
|
| +
|
| + >>> (pubkey, privkey) = rsa.newkeys(512)
|
| + >>> message = 'Go left at the blue tree'
|
| + >>> signature = rsa.sign(message, privkey, 'SHA-1')
|
| +
|
| +This hashes the message using SHA-1. Other hash methods are also
|
| +possible, check the :py:func:`rsa.sign` function documentation for
|
| +details. The hash is then signed with the private key.
|
| +
|
| +In order to verify the signature, use the :py:func:`rsa.verify`
|
| +function. This function returns True if the verification is successful:
|
| +
|
| + >>> message = 'Go left at the blue tree'
|
| + >>> rsa.verify(message, signature, pubkey)
|
| + True
|
| +
|
| +Modify the message, and the signature is no longer valid and a
|
| +:py:class:`rsa.pkcs1.VerificationError` is thrown:
|
| +
|
| + >>> message = 'Go right at the blue tree'
|
| + >>> rsa.verify(message, signature, pubkey)
|
| + Traceback (most recent call last):
|
| + File "<stdin>", line 1, in <module>
|
| + File "/home/sybren/workspace/python-rsa/rsa/pkcs1.py", line 289, in verify
|
| + raise VerificationError('Verification failed')
|
| + rsa.pkcs1.VerificationError: Verification failed
|
| +
|
| +.. warning::
|
| +
|
| + Never display the stack trace of a
|
| + :py:class:`rsa.pkcs1.VerificationError` exception. It shows where
|
| + in the code the exception occurred, and thus leaks information
|
| + about the key. It's only a tiny bit of information, but every bit
|
| + makes cracking the keys easier.
|
| +
|
| +Instead of a message you can also call :py:func:`rsa.sign` and
|
| +:py:func:`rsa.verify` with a :py:class:`file`-like object. If the
|
| +message object has a ``read(int)`` method it is assumed to be a file.
|
| +In that case the file is hashed in 1024-byte blocks at the time.
|
| +
|
| + >>> with open('somefile', 'rb') as msgfile:
|
| + ... signature = rsa.sign(msgfile, privkey, 'SHA-1')
|
| +
|
| + >>> with open('somefile', 'rb') as msgfile:
|
| + ... rsa.verify(msgfile, signature, pubkey)
|
| +
|
| +
|
| +.. _bigfiles:
|
| +
|
| +Working with big files
|
| +--------------------------------------------------
|
| +
|
| +RSA can only encrypt messages that are smaller than the key. A couple
|
| +of bytes are lost on random padding, and the rest is available for the
|
| +message itself. For example, a 512-bit key can encode a 53-byte
|
| +message (512 bit = 64 bytes, 11 bytes are used for random padding and
|
| +other stuff).
|
| +
|
| +How it usually works
|
| +++++++++++++++++++++++++++++++++++++++++
|
| +
|
| +The most common way to use RSA with larger files uses a block cypher
|
| +like AES or DES3 to encrypt the file with a random key, then encrypt
|
| +the random key with RSA. You would send the encrypted file along with
|
| +the encrypted key to the recipient. The complete flow is:
|
| +
|
| +#. Generate a random key
|
| +
|
| + >>> import rsa.randnum
|
| + >>> aes_key = rsa.randnum.read_random_bits(128)
|
| +
|
| +#. Use that key to encrypt the file with AES.
|
| +#. :py:func:`Encrypt <rsa.encrypt>` the AES key with RSA
|
| +
|
| + >>> encrypted_aes_key = rsa.encrypt(aes_key, public_rsa_key)
|
| +
|
| +#. Send the encrypted file together with ``encrypted_aes_key``
|
| +#. The recipient now reverses this process to obtain the encrypted
|
| + file.
|
| +
|
| +.. note::
|
| +
|
| + The Python-RSA module does not contain functionality to do the AES
|
| + encryption for you.
|
| +
|
| +Only using Python-RSA: the VARBLOCK format
|
| ++++++++++++++++++++++++++++++++++++++++++++
|
| +
|
| +As far as we know, there is no pure-Python AES encryption. Previous
|
| +versions of Python-RSA included functionality to encrypt large files
|
| +with just RSA, and so does this version. The format has been improved,
|
| +though.
|
| +
|
| +Encrypting works as follows: the input file is split into blocks that
|
| +are just large enough to encrypt with your RSA key. Every block is
|
| +then encrypted using RSA, and the encrypted blocks are assembled into
|
| +the output file. This file format is called the :ref:`VARBLOCK
|
| +<VARBLOCK>` format.
|
| +
|
| +Decrypting works in reverse. The encrypted file is separated into
|
| +encrypted blocks. Those are decrypted, and assembled into the original
|
| +file.
|
| +
|
| +.. note::
|
| +
|
| + The file will get larger after encryption, as each encrypted block
|
| + has 8 bytes of random padding and 3 more bytes of overhead.
|
| +
|
| +Since these encryption/decryption functions are potentially called on
|
| +very large files, they use another approach. Where the regular
|
| +functions store the message in memory in its entirety, these functions
|
| +work on one block at the time. As a result, you should call them with
|
| +:py:class:`file`-like objects as the parameters.
|
| +
|
| +Before using we of course need a keypair:
|
| +
|
| +>>> import rsa
|
| +>>> (pub_key, priv_key) = rsa.newkeys(512)
|
| +
|
| +Encryption works on file handles using the
|
| +:py:func:`rsa.bigfile.encrypt_bigfile` function:
|
| +
|
| +>>> from rsa.bigfile import *
|
| +>>> with open('inputfile', 'rb') as infile, open('outputfile', 'wb') as outfile:
|
| +... encrypt_bigfile(infile, outfile, pub_key)
|
| +
|
| +As does decryption using the :py:func:`rsa.bigfile.decrypt_bigfile`
|
| +function:
|
| +
|
| +>>> from rsa.bigfile import *
|
| +>>> with open('inputfile', 'rb') as infile, open('outputfile', 'wb') as outfile:
|
| +... decrypt_bigfile(infile, outfile, priv_key)
|
| +
|
| +.. note::
|
| +
|
| + :py:func:`rsa.sign` and :py:func:`rsa.verify` work on arbitrarily
|
| + long files, so they do not have a "bigfile" equivalent.
|
| +
|
| +
|
|
|