Support signing a pre-calculated hash (#87)

* Split the hashing out of the sign method

This code change adds support to split the hashing of a message
and the actual signing of the message.

* Updating unit test and documentation

This commit updates the unit test and usage docs. In addition,
This change removes a redundant error check inside rsa.sign().

* Refactore unit tests and code comments

Removed the print statements from the unit test and refactored a
few code comments to improve readability.

* Rename hash function

The new hash function had the same name as a function in the
standard library. This commit changes the name to avoid conflicts.

* Rename hash function to compute_hash()

This commit renames the hash function to compute_hash().
diff --git a/doc/usage.rst b/doc/usage.rst
index b4f8426..6ac9e82 100644
--- a/doc/usage.rst
+++ b/doc/usage.rst
@@ -203,6 +203,15 @@
 possible, check the :py:func:`rsa.sign` function documentation for
 details. The hash is then signed with the private key.
 
+It is possible to calculate the hash and signature in separate operations
+(i.e for generating the hash on a client machine and then sign with a
+private key on remote server). To hash a message use the :py:func:`rsa.compute_hash`
+function and then use the :py:func:`rsa.sign_hash` function to sign the hash:
+
+    >>> message = 'Go left at the blue tree'
+    >>> hash = rsa.compute_hash(message, 'SHA-1')
+    >>> signature = rsa.sign_hash(hash, privkey, 'SHA-1')
+
 In order to verify the signature, use the :py:func:`rsa.verify`
 function. This function returns True if the verification is successful:
 
diff --git a/rsa/__init__.py b/rsa/__init__.py
index 95cd3fd..ce3a341 100644
--- a/rsa/__init__.py
+++ b/rsa/__init__.py
@@ -25,7 +25,7 @@
 
 from rsa.key import newkeys, PrivateKey, PublicKey
 from rsa.pkcs1 import encrypt, decrypt, sign, verify, DecryptionError, \
-    VerificationError, find_signature_hash
+    VerificationError, find_signature_hash,  sign_hash, compute_hash
 
 __author__ = "Sybren Stuvel, Barry Mead and Yesudeep Mangalapilly"
 __date__ = "2016-03-29"
@@ -38,4 +38,5 @@
     doctest.testmod()
 
 __all__ = ["newkeys", "encrypt", "decrypt", "sign", "verify", 'PublicKey',
-           'PrivateKey', 'DecryptionError', 'VerificationError']
+           'PrivateKey', 'DecryptionError', 'VerificationError',
+           'compute_hash', 'sign_hash']
diff --git a/rsa/pkcs1.py b/rsa/pkcs1.py
index 41f543c..323bf48 100644
--- a/rsa/pkcs1.py
+++ b/rsa/pkcs1.py
@@ -245,7 +245,41 @@
     return cleartext[sep_idx + 1:]
 
 
-def sign(message, priv_key, hash):
+def sign_hash(hash_value, priv_key, hash_method):
+    """Signs a precomputed hash 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 altered.
+    
+    :param hash_value: A precomputed hash to sign (ignores message). Should be set to
+        None if needing to hash and sign message.
+    :param priv_key: the :py:class:`rsa.PrivateKey` to sign with
+    :param hash_method: 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
+        requested hash.
+
+    """
+
+    # Get the ASN1 code for this hash method
+    if hash_method not in HASH_ASN1:
+        raise ValueError('Invalid hash method: %s' % hash_method)
+    asn1code = HASH_ASN1[hash_method]
+
+    # Encrypt the hash with the private key
+    cleartext = asn1code + hash_value
+    keylength = common.byte_size(priv_key.n)
+    padded = _pad_for_signing(cleartext, keylength)
+
+    payload = transform.bytes2int(padded)
+    encrypted = priv_key.blinded_encrypt(payload)
+    block = transform.int2bytes(encrypted, keylength)
+
+    return block
+
+
+def sign(message, priv_key, hash_method):
     """Signs the message with the private key.
 
     Hashes the message, then signs the hash with the given key. This is known
@@ -255,7 +289,7 @@
         object. If ``message`` has a ``read()`` method, it is assumed to be a
         file-like object.
     :param priv_key: the :py:class:`rsa.PrivateKey` to sign with
-    :param hash: the hash method used on the message. Use 'MD5', 'SHA-1',
+    :param hash_method: 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
@@ -263,24 +297,8 @@
 
     """
 
-    # Get the ASN1 code for this hash method
-    if hash not in HASH_ASN1:
-        raise ValueError('Invalid hash method: %s' % hash)
-    asn1code = HASH_ASN1[hash]
-
-    # Calculate the hash
-    hash = _hash(message, hash)
-
-    # Encrypt the hash with the private key
-    cleartext = asn1code + hash
-    keylength = common.byte_size(priv_key.n)
-    padded = _pad_for_signing(cleartext, keylength)
-
-    payload = transform.bytes2int(padded)
-    encrypted = priv_key.blinded_encrypt(payload)
-    block = transform.int2bytes(encrypted, keylength)
-
-    return block
+    msg_hash = compute_hash(message, hash_method)
+    return sign_hash(msg_hash, priv_key, hash_method)
 
 
 def verify(message, signature, pub_key):
@@ -305,7 +323,7 @@
 
     # Get the hash method
     method_name = _find_method_hash(clearsig)
-    message_hash = _hash(message, method_name)
+    message_hash = compute_hash(message, method_name)
 
     # Reconstruct the expected padded hash
     cleartext = HASH_ASN1[method_name] + message_hash
@@ -358,7 +376,7 @@
             break
 
 
-def _hash(message, method_name):
+def compute_hash(message, method_name):
     """Returns the message digest.
 
     :param message: the signed message. Can be an 8-bit string or a file-like
diff --git a/tests/test_pkcs1.py b/tests/test_pkcs1.py
index a8afea7..a96c8be 100644
--- a/tests/test_pkcs1.py
+++ b/tests/test_pkcs1.py
@@ -111,3 +111,24 @@
         signature2 = pkcs1.sign(message, self.priv, 'SHA-1')
 
         self.assertEqual(signature1, signature2)
+
+    def test_split_hash_sign(self):
+        """Hashing and then signing should match with directly signing the message. """
+
+        message = b'je moeder'
+        msg_hash = pkcs1.compute_hash(message, 'SHA-256')
+        signature1 = pkcs1.sign_hash(msg_hash, self.priv, 'SHA-256')
+
+        # Calculate the signature using the unified method
+        signature2 = pkcs1.sign(message, self.priv, 'SHA-256')
+
+        self.assertEqual(signature1, signature2)
+
+    def test_hash_sign_verify(self):
+        """Test happy flow of hash, sign, and verify"""
+
+        message = b'je moeder'
+        msg_hash = pkcs1.compute_hash(message, 'SHA-256')
+        signature = pkcs1.sign_hash(msg_hash, self.priv, 'SHA-256')
+
+        self.assertTrue(pkcs1.verify(message, signature, self.pub))