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. |
+ |
+ |