More documentation
diff --git a/doc/compatibility.rst b/doc/compatibility.rst
index cbc0eb3..0cb2ba6 100644
--- a/doc/compatibility.rst
+++ b/doc/compatibility.rst
@@ -42,3 +42,4 @@
    --out=OUTFILENAME  Output filename. Writes to stdout of not specified
    --inform=INFORM    key format of input - default PEM
    --outform=OUTFORM  key format of output - default PEM
+
diff --git a/doc/conf.py b/doc/conf.py
index 3ee83f1..ad49886 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -26,7 +26,9 @@
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo',
-    'sphinx.ext.coverage', 'sphinx.ext.viewcode', 'sphinx.ext.pngmath']
+    'sphinx.ext.coverage', 'sphinx.ext.pngmath']
+
+# I would like to add 'sphinx.ext.viewcode', but it causes a UnicodeDecodeError
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
@@ -35,7 +37,7 @@
 source_suffix = '.rst'
 
 # The encoding of source files.
-#source_encoding = 'utf-8-sig'
+source_encoding = 'utf-8'
 
 # The master toctree document.
 master_doc = 'index'
diff --git a/doc/index.rst b/doc/index.rst
index addc869..df81a77 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -39,6 +39,7 @@
     licence
     usage
     compatibility
+    reference
 
 
 Indices and tables
diff --git a/doc/intro.rst b/doc/intro.rst
index e27a7a2..cc89a19 100644
--- a/doc/intro.rst
+++ b/doc/intro.rst
@@ -14,6 +14,6 @@
 was no functionality for working with byte sequences (such as files)
 yet.
 
-.. TODO:: write more history
+.. todo:: write more history
 
 
diff --git a/doc/reference.rst b/doc/reference.rst
new file mode 100644
index 0000000..69a89bc
--- /dev/null
+++ b/doc/reference.rst
@@ -0,0 +1,29 @@
+Reference
+==================================================
+
+Functions
+--------------------------------------------------
+
+.. autofunction:: rsa.encrypt
+
+.. autofunction:: rsa.decrypt
+
+.. autofunction:: rsa.sign
+
+.. autofunction:: rsa.verify
+
+.. autofunction:: rsa.newkeys(keysize)
+
+Classes
+--------------------------------------------------
+
+.. autoclass:: rsa.PublicKey
+    :members:
+    :inherited-members:
+
+.. autoclass:: rsa.PrivateKey
+    :members:
+    :inherited-members:
+
+
+
diff --git a/doc/usage.rst b/doc/usage.rst
index bd499a9..61121e0 100644
--- a/doc/usage.rst
+++ b/doc/usage.rst
@@ -3,10 +3,6 @@
 
 This section describes the usage of the Python-RSA module.
 
-
-Generating keys
---------------------------------------------------
-
 Before you can use RSA you need keys. You will receive a private key
 and a public key.
 
@@ -15,10 +11,86 @@
     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.
+Alternatively you can use :py:func:`rsa.PrivateKey.load_pkcs1` and
+:py:func:`rsa.PublicKey.load_pkcs1` to load keys from a file.
+
+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.
+
+These are some timings from my netbook (Linux 2.6, 1.6 GHz Intel Atom
+N270 CPU, 2 GB RAM):
+
++----------------+------------------+
+| Keysize (bits) | Time to generate |
++================+==================+
+| 32             | 0.01 sec.        |
++----------------+------------------+
+| 64             | 0.03 sec.        |
++----------------+------------------+
+| 96             | 0.04 sec.        |
++----------------+------------------+
+| 128            | 0.08 sec.        |
++----------------+------------------+
+| 256            | 0.27 sec.        |
++----------------+------------------+
+| 384            | 0.93 sec.        |
++----------------+------------------+
+| 512            | 1.21 sec.        |
++----------------+------------------+
+| 1024           | 7.93 sec.        |
++----------------+------------------+
+| 2048           | 132.97 sec.      |
++----------------+------------------+
+
 
 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).
+
+#. Alice writes a message
+
+#. Alice encrypts the message using Bob's public key, and sends the
+   encrypted message.
+
+#. Bob receives the message, and decrypts it with his private key.
+
+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.
+
+
+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
 --------------------------------------------------
diff --git a/rsa/key.py b/rsa/key.py
index e8fb63f..2d2ca4d 100644
--- a/rsa/key.py
+++ b/rsa/key.py
@@ -41,15 +41,17 @@
     def load_pkcs1(cls, keyfile, format='PEM'):
         r'''Loads a key in PKCS#1 DER or PEM format.
 
-        @param keyfile: contents of a DER- or PEM-encoded file that contains
+        :param keyfile: contents of a DER- or PEM-encoded file that contains
             the public key.
-        @param format: the format of the file to load; 'PEM' or 'DER'
-        @return: a PublicKey object
+        :param format: the format of the file to load; 'PEM' or 'DER'
+
+        :return: a PublicKey object
+
         '''
 
         methods = {
-            'PEM': cls.load_pkcs1_pem,
-            'DER': cls.load_pkcs1_der,
+            'PEM': cls._load_pkcs1_pem,
+            'DER': cls._load_pkcs1_der,
         }
 
         if format not in methods:
@@ -63,13 +65,14 @@
     def save_pkcs1(self, format='PEM'):
         '''Saves the public key in PKCS#1 DER or PEM format.
 
-        @param format: the format to save; 'PEM' or 'DER'
-        @returns: the DER- or PEM-encoded public key.
+        :param format: the format to save; 'PEM' or 'DER'
+        :returns: the DER- or PEM-encoded public key.
+
         '''
 
         methods = {
-            'PEM': self.save_pkcs1_pem,
-            'DER': self.save_pkcs1_der,
+            'PEM': self._save_pkcs1_pem,
+            'DER': self._save_pkcs1_der,
         }
 
         if format not in methods:
@@ -86,7 +89,8 @@
     This key is also known as the 'encryption key'. It contains the 'n' and 'e'
     values.
 
-    Supports attributes as well as dictionary-like access.
+    Supports attributes as well as dictionary-like access. Attribute accesss is
+    faster, though.
 
     >>> PublicKey(5, 3)
     PublicKey(5, 3)
@@ -128,7 +132,7 @@
         return not (self == other)
 
     @classmethod
-    def load_pkcs1_der(cls, keyfile):
+    def _load_pkcs1_der(cls, keyfile):
         r'''Loads a key in PKCS#1 DER format.
 
         @param keyfile: contents of a DER-encoded file that contains the public
@@ -160,7 +164,7 @@
         as_ints = tuple(int(x) for x in priv)
         return cls(*as_ints)
 
-    def save_pkcs1_der(self):
+    def _save_pkcs1_der(self):
         '''Saves the public key in PKCS#1 DER format.
 
         @returns: the DER-encoded public key.
@@ -183,7 +187,7 @@
         return encoder.encode(asn_key)
 
     @classmethod
-    def load_pkcs1_pem(cls, keyfile):
+    def _load_pkcs1_pem(cls, keyfile):
         '''Loads a PKCS#1 PEM-encoded public key file.
 
         The contents of the file before the "-----BEGIN RSA PUBLIC KEY-----" and
@@ -197,7 +201,7 @@
         der = rsa.pem.load_pem(keyfile, 'RSA PUBLIC KEY')
         return cls.load_pkcs1_der(der)
 
-    def save_pkcs1_pem(self):
+    def _save_pkcs1_pem(self):
         '''Saves a PKCS#1 PEM-encoded public key file.
 
         @return: contents of a PEM-encoded file that contains the public key.
@@ -212,7 +216,8 @@
     This key is also known as the 'decryption key'. It contains the 'n', 'e',
     'd', 'p', 'q' and other values.
 
-    Supports attributes as well as dictionary-like access.
+    Supports attributes as well as dictionary-like access. Attribute accesss is
+    faster, though.
 
     >>> PrivateKey(3247, 65537, 833, 191, 17)
     PrivateKey(3247, 65537, 833, 191, 17)
@@ -290,7 +295,7 @@
         return not (self == other)
 
     @classmethod
-    def load_pkcs1_der(cls, keyfile):
+    def _load_pkcs1_der(cls, keyfile):
         r'''Loads a key in PKCS#1 DER format.
 
         @param keyfile: contents of a DER-encoded file that contains the private
@@ -334,7 +339,7 @@
         as_ints = tuple(int(x) for x in priv[1:9])
         return cls(*as_ints)
 
-    def save_pkcs1_der(self):
+    def _save_pkcs1_der(self):
         '''Saves the private key in PKCS#1 DER format.
 
         @returns: the DER-encoded private key.
@@ -371,7 +376,7 @@
         return encoder.encode(asn_key)
 
     @classmethod
-    def load_pkcs1_pem(cls, keyfile):
+    def _load_pkcs1_pem(cls, keyfile):
         '''Loads a PKCS#1 PEM-encoded private key file.
 
         The contents of the file before the "-----BEGIN RSA PRIVATE KEY-----" and
@@ -385,7 +390,7 @@
         der = rsa.pem.load_pem(keyfile, 'RSA PRIVATE KEY')
         return cls.load_pkcs1_der(der)
 
-    def save_pkcs1_pem(self):
+    def _save_pkcs1_pem(self):
         '''Saves a PKCS#1 PEM-encoded private key file.
 
         @return: contents of a PEM-encoded file that contains the private key.
@@ -535,15 +540,16 @@
 def newkeys(nbits, accurate=True):
     """Generates public and private keys, and returns them as (pub, priv).
 
-    The public key is also known as the 'encryption key', and is a PublicKey
-    object. The private key is also known as the 'decryption key' and is a
-    PrivateKey object.
-    
-    @param nbits: the number of bits required to store ``n = p*q``.
-    @param accurate: when True, ``n`` will have exactly the number of bits you
-        asked for. However, this makes key generation much slower.
+    The public key is also known as the 'encryption key', and is a
+    :py:class:`PublicKey` object. The private key is also known as the
+    'decryption key' and is a :py:class:`PrivateKey` object.
 
-    @return: a tuple (PublicKey, PrivateKey)
+    :param nbits: the number of bits required to store ``n = p*q``.
+    :param accurate: when True, ``n`` will have exactly the number of bits you
+        asked for. However, this makes key generation much slower. When False,
+        `n`` may have slightly less bits.
+
+    :returns: a tuple (:py:class:`rsa.PublicKey`, :py:class:`rsa.PrivateKey`)
     
     """
 
diff --git a/rsa/pkcs1.py b/rsa/pkcs1.py
index 3955c30..7612b27 100644
--- a/rsa/pkcs1.py
+++ b/rsa/pkcs1.py
@@ -14,9 +14,9 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 
-'''Functions for PKCS1 version 1.5 encryption and signing
+'''Functions for PKCS#1 version 1.5 encryption and signing
 
-This module implements certain functionality from PKCS1 version 1.5. For a
+This module implements certain functionality from PKCS#1 version 1.5. For a
 very clear example, read http://www.di-mgt.com.au/rsa_alg.html#pkcs1schemes
 
 At least 8 bytes of random padding is used when encrypting a message. This makes
@@ -62,7 +62,7 @@
 def _pad_for_encryption(message, target_length):
     r'''Pads the message for encryption, returning the padded message.
     
-    @return: 00 02 RANDOM_DATA 00 MESSAGE
+    :return: 00 02 RANDOM_DATA 00 MESSAGE
     
     >>> block = _pad_for_encryption('hello', 16)
     >>> len(block)
@@ -110,7 +110,7 @@
     
     The padding is always a repetition of FF bytes.
     
-    @return: 00 01 PADDING 00 MESSAGE
+    :return: 00 01 PADDING 00 MESSAGE
     
     >>> block = _pad_for_signing('hello', 16)
     >>> len(block)
@@ -140,14 +140,13 @@
     
     
 def encrypt(message, pub_key):
-    '''Encrypts the given message using PKCS1 v1.5
+    '''Encrypts the given message using PKCS#1 v1.5
     
-    @param message: the message to encrypt. Must be a byte string no longer than
+    :param message: the message to encrypt. Must be a byte string no longer than
         ``k-11`` bytes, where ``k`` is the number of bytes needed to encode
         the ``n`` component of the public key.
-    @param pub_key: the public key to encrypt with.
-    
-    @raise OverflowError: when the message is too large to fit in the padded
+    :param pub_key: the :py:class:`rsa.PublicKey` to encrypt with.
+    :raise OverflowError: when the message is too large to fit in the padded
         block.
         
     >>> from rsa import key, common
@@ -156,6 +155,7 @@
     >>> crypto = encrypt(message, pub_key)
     
     The crypto text should be just as long as the public key 'n' component:
+
     >>> len(crypto) == common.byte_size(pub_key.n)
     True
     
@@ -171,28 +171,32 @@
     return block
 
 def decrypt(crypto, priv_key):
-    r'''Decrypts the given message using PKCS1 v1.5
+    r'''Decrypts the given message using PKCS#1 v1.5
     
     The decryption is considered 'failed' when the resulting cleartext doesn't
     start with the bytes 00 02, or when the 00 byte between the padding and
     the message cannot be found.
     
-    @param crypto: the crypto text as returned by ``encrypt(message, pub_key)``
-    @param priv_key: the private key to decrypt with.
-    
-    @raise DecryptionError: when the decryption fails. No details are given as
+    :param crypto: the crypto text as returned by :py:func:`rsa.encrypt`
+    :param priv_key: the :py:class:`rsa.PrivateKey` to decrypt with.
+    :raise DecryptionError: when the decryption fails. No details are given as
         to why the code thinks the decryption fails, as this would leak
         information about the private key.
 
-    >>> from rsa import key, common
-    >>> (pub_key, priv_key) = key.newkeys(256)
+
+    >>> import rsa
+    >>> (pub_key, priv_key) = rsa.newkeys(256)
 
     It works with strings:
-    >>> decrypt(encrypt('hello', pub_key), priv_key)
+
+    >>> crypto = encrypt('hello', pub_key)
+    >>> decrypt(crypto, priv_key)
     'hello'
     
     And with binary data:
-    >>> decrypt(encrypt('\x00\x00\x00\x00\x01', pub_key), priv_key)
+
+    >>> crypto = encrypt('\x00\x00\x00\x00\x01', pub_key)
+    >>> decrypt(crypto, priv_key)
     '\x00\x00\x00\x00\x01'
     
     '''
@@ -218,16 +222,14 @@
     '''Signs the message with the private key.
 
     Hashes the message, then signs the hash with the given key. This is known
-    as a "detached signature", because the message itself isn't signed.
+    as a "detached signature", because the message itself isn't altered.
     
-    @param message: the message to sign
-    @param priv_key: the private key to sign with
-    @param hash: the hash method used on the message. Use 'MD5', 'SHA-1',
+    :param message: the message to sign
+    :param priv_key: the :py:class:`rsa.PrivateKey` to sign with
+    :param hash: the hash method used on the message. Use 'MD5', 'SHA-1',
         'SHA-256', 'SHA-384' or 'SHA-512'.
-    
-    @return: a message signature block.
-    
-    @raise OverflowError: if the private key is too small to contain the
+    :return: a message signature block.
+    :raise OverflowError: if the private key is too small to contain the
         requested hash.
 
     '''
@@ -256,11 +258,11 @@
     
     The hash method is detected automatically from the signature.
     
-    @param message: the signed message
-    @param signature: the signature block, as created with ``sign(...)``.
-    @param pub_key: the public key of the person signing the message.
-    
-    @raise VerificationError: when the signature doesn't match the message.
+    :param message: the signed message
+    :param signature: the signature block, as created with ``sign(...)``.
+    :param pub_key: the :py:class:`rsa.PublicKey` of the person signing the message.
+    :raise VerificationError: when the signature doesn't match the message.
+
     '''
     
     blocksize = common.byte_size(pub_key.n)
@@ -301,13 +303,14 @@
 def _find_method_hash(method_hash):
     '''Finds the hash method and the hash itself.
     
-    @param method_hash: ASN1 code for the hash method concatenated with the
+    :param method_hash: ASN1 code for the hash method concatenated with the
         hash itself.
     
-    @return: tuple (method, hash) where ``method`` is the used hash method, and
+    :return: tuple (method, hash) where ``method`` is the used hash method, and
         ``hash`` is the hash itself.
     
-    @raise VerificationFailed: when the hash method cannot be found
+    :raise VerificationFailed: when the hash method cannot be found
+
     '''
 
     for (hashname, asn1code) in HASH_ASN1.iteritems():