summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorSybren A. St?vel <sybren@stuvel.eu>2011-08-03 13:31:57 +0200
committerSybren A. St?vel <sybren@stuvel.eu>2011-08-03 13:31:57 +0200
commit3a76cb25f634ecf317e0be65e53703b05d704bee (patch)
tree01770c1edff43ec14835682c18866e10eae2e278 /doc
parent27673f005e64071b1464c89f4aaeb2b2db8848fe (diff)
downloadrsa-3a76cb25f634ecf317e0be65e53703b05d704bee.tar.gz
more documentation
Diffstat (limited to 'doc')
-rw-r--r--doc/Makefile2
-rw-r--r--doc/compatibility.rst10
-rw-r--r--doc/index.rst2
-rw-r--r--doc/reference.rst37
-rw-r--r--doc/upgrading.rst67
-rw-r--r--doc/usage.rst65
6 files changed, 153 insertions, 30 deletions
diff --git a/doc/Makefile b/doc/Makefile
index f19a957..397d629 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -14,6 +14,8 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+default: html
+
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
diff --git a/doc/compatibility.rst b/doc/compatibility.rst
index c9dac39..ab9e2e4 100644
--- a/doc/compatibility.rst
+++ b/doc/compatibility.rst
@@ -11,20 +11,20 @@ Keys are stored in PEM or DER format according to PKCS#1 v1.5. Private
keys are compatible with OpenSSL. However, OpenSSL uses X.509 for its
public keys, which are not supported.
-:Encryption:
+Encryption:
PKCS#1 v1.5 with at least 8 bytes of random padding
-:Signatures:
+Signatures:
PKCS#1 v1.5 using the following hash methods:
MD5, SHA-1, SHA-256, SHA-384, SHA-512
-:Private keys:
+Private keys:
PKCS#1 v1.5 in PEM and DER format, ASN.1 type RSAPrivateKey
-:Public keys:
+Public keys:
PKCS#1 v1.5 in PEM and DER format, ASN.1 type RSAPublicKey
-:VARBLOCK encryption:
+:ref:`VARBLOCK <bigfiles>` encryption:
Python-RSA only, not compatible with any other known application.
diff --git a/doc/index.rst b/doc/index.rst
index 9c84331..02577ab 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -36,9 +36,11 @@ Contents
.. toctree::
:maxdepth: 2
+ :numbered:
intro
installation
+ upgrading
licence
usage
cli
diff --git a/doc/reference.rst b/doc/reference.rst
index a1a7d35..53dee63 100644
--- a/doc/reference.rst
+++ b/doc/reference.rst
@@ -1,6 +1,9 @@
Reference
==================================================
+This is the class and function reference. For more usage information
+see the :ref:`usage` page.
+
Functions
--------------------------------------------------
@@ -14,10 +17,6 @@ Functions
.. autofunction:: rsa.newkeys(keysize)
-.. autofunction:: rsa.bigfile.encrypt_bigfile
-
-.. autofunction:: rsa.bigfile.decrypt_bigfile
-
Classes
--------------------------------------------------
@@ -42,9 +41,22 @@ Exceptions
.. index:: VARBLOCK (file format)
-The VARBLOCK file format
+Module: rsa.bigfile
--------------------------------------------------
+The :py:mod:`rsa.bigfile` module contains functions for encrypting and
+decrypting files that are larger than the RSA key. See
+:ref:`bigfiles` for more information.
+
+.. autofunction:: rsa.bigfile.encrypt_bigfile
+
+.. autofunction:: rsa.bigfile.decrypt_bigfile
+
+.. _VARBLOCK:
+
+The VARBLOCK file format
+++++++++++++++++++++++++++++++++++++++++++++++++++
+
The VARBLOCK file format allows us to encrypt files that are larger
than the RSA key. The format is as follows; || denotes byte string
concatenation::
@@ -55,7 +67,7 @@ concatenation::
BLOCK := LENGTH || DATA
- LENGTH := varint-encoded length of the followng data, in bytes
+ LENGTH := varint-encoded length of the following data, in bytes
DATA := the data to store in the block
@@ -65,3 +77,16 @@ efficiently encode an arbitrarily long integer.
.. _Protobuf:
http://code.google.com/apis/protocolbuffers/docs/encoding.html#varints
+
+Module: rsa.core
+--------------------------------------------------
+
+At the core of the RSA encryption method lie these functions. They
+both operate on (arbitrarily long) integers only. They probably aren't
+of much use to you, but I wanted to document them anyway as they are
+the core of the entire library.
+
+.. autofunction:: rsa.core.encrypt_int
+
+.. autofunction:: rsa.core.decrypt_int
+
diff --git a/doc/upgrading.rst b/doc/upgrading.rst
new file mode 100644
index 0000000..c8a2d82
--- /dev/null
+++ b/doc/upgrading.rst
@@ -0,0 +1,67 @@
+Upgrading from older versions
+==================================================
+
+Previous versions of Python-RSA were less secure than the current
+version. In order to be able to gradually upgrade your software, those
+old versions are still available.
+
+To use version 1.3.3, use this::
+
+ import rsa._version133 as rsa
+
+And to use version 2.0, use this::
+
+ import rsa._version200 as rsa
+
+You can import all three versions at the same time. This allows you to
+use an old version to decrypt your messages, and a new version to
+re-encrypt them::
+
+ import rsa._version200 as rsa200
+ import rsa # this imports version 3.0
+
+ decrypted = rsa200.decrypt(old_crypto, version_200_private_key)
+ new_crypto = rsa.encrypt(decrypted, version_3_public_key)
+
+Those import statements *will create warnings* as they import much
+less secure code into your project.
+
+The random padding introduced in version 3.0 made things much more
+secure, but also requires a larger key to encrypt the same message.
+You can either generate a new key with :py:func:`rsa.newkeys`, or use
+:py:func:`rsa.bigfile.encrypt_bigfile` to encrypt your files.
+
+Converting keys
+--------------------------------------------------
+
+Version 3.0 introduced industrial standard RSA keys according to
+PKCS#1. The old keys were just dictionaries. To convert a key from an
+older version of Python-RSA, use the following::
+
+ import rsa
+
+ # Load the old key somehow.
+ old_pub_key = {
+ 'e': 65537,
+ 'n': 31698122414741849421263704398157795847591L
+ }
+
+ old_priv_key = {
+ 'd': 7506520894712811128876594754922157377793L,
+ 'p': 4169414332984308880603L,
+ 'q': 7602535963858869797L
+ }
+
+ # Create new key objects like this:
+ pub_key = rsa.PublicKey(n=old_pub_key['n'], e=old_pub_key['e'])
+
+ priv_key = rsa.PrivateKey(n=old_pub_key['n'], e=old_pub_key['e'],
+ d=old_priv_key['d'], p=old_priv_key['p'], q=old_priv_key['q'])
+
+
+ # Or use this shorter notation:
+ pub_key = rsa.PublicKey(**old_pub_key)
+
+ old_priv_key.update(old_pub_key)
+ priv_key = rsa.PrivateKey(**old_priv_key)
+
diff --git a/doc/usage.rst b/doc/usage.rst
index 09954e2..9b5fc17 100644
--- a/doc/usage.rst
+++ b/doc/usage.rst
@@ -1,3 +1,5 @@
+.. _usage:
+
Usage
==================================================
@@ -6,7 +8,7 @@ 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.
-.. note::
+.. important::
The private key is called *private* for a reason. Never share this
key with anyone.
@@ -97,23 +99,37 @@ that only Bob can read.
hello Bob!
Since Bob kept his private key *private*, Alice can be sure that he is
-the only one who can read the message.
-
-.. note::
-
- Bob does *not* know for sure that it was Alice that sent the
- message, since she didn't sign it.
+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 `Working with big files`_ for information on how to work with
+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
++++++++++++++++++++++++++++++
@@ -153,7 +169,7 @@ Modify the message, and the signature is no longer valid and a
raise VerificationError('Verification failed')
rsa.pkcs1.VerificationError: Verification failed
-.. note::
+.. warning::
Never display the stack trace of a
:py:class:`rsa.pkcs1.VerificationError` exception. It shows where
@@ -173,6 +189,8 @@ In that case the file is hashed in 1024-byte blocks at the time.
... rsa.verify(msgfile, signature, pubkey)
+.. _bigfiles:
+
Working with big files
--------------------------------------------------
@@ -196,33 +214,39 @@ the encrypted key to the recipient. The complete flow is:
>>> aes_key = rsa.randnum.read_random_bits(128)
#. Use that key to encrypt the file with AES.
-#. Encrypt the AES key with RSA
+#. :py:func:`Encrypt <rsa.encrypt>` the AES key with RSA
- >>> encrypted_aes_key = rsa.encrypt(aes_key, public_key)
+ >>> 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::
-Only using Python-RSA
-++++++++++++++++++++++++++++++++++++++++
+ 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,
+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 VARBLOCK format.
+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.
@@ -237,19 +261,22 @@ Before using we of course need a keypair:
>>> import rsa
>>> (pub_key, priv_key) = rsa.newkeys(512)
-Encryption works on file handles:
+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:
+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.