[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [bridgedb/develop] Add crypto.getRSAKey() function.
commit 67e14a5d367f8c82c806f7c64f9e1c28293f7c5a
Author: Isis Lovecruft <isis@xxxxxxxxxxxxxx>
Date: Tue Mar 11 20:25:20 2014 +0000
Add crypto.getRSAKey() function.
* ADD a function for getting/creating RSA keypairs.
* ADDS a dependency on pyCrypto.
---
lib/bridgedb/crypto.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
requirements.txt | 1 +
2 files changed, 73 insertions(+)
diff --git a/lib/bridgedb/crypto.py b/lib/bridgedb/crypto.py
index f5a95ec..dc2523b 100644
--- a/lib/bridgedb/crypto.py
+++ b/lib/bridgedb/crypto.py
@@ -36,11 +36,18 @@ import os
import OpenSSL.rand
+from Crypto.Cipher import PKCS1_OAEP
+from Crypto.PublicKey import RSA
+
#: The hash digest to use for HMACs.
DIGESTMOD = hashlib.sha1
+class RSAKeyGenerationError(Exception):
+ """Raised when there was an error creating an RSA keypair."""
+
+
def writeKeyToFile(key, filename):
"""Write **key** to **filename**, with ``0400`` permissions.
@@ -60,6 +67,71 @@ def writeKeyToFile(key, filename):
os.fsync(fd)
os.close(fd)
+def getRSAKey(filename, bits=2048):
+ """Load the RSA key stored in **filename**, or create and save a new key.
+
+ >>> from bridgedb import crypto
+ >>> keyfile = 'doctest_getRSAKey'
+ >>> message = "The secret words are Squeamish Ossifrage."
+ >>> keypair = crypto.getRSAKey(keyfile, bits=2048)
+ >>> (secretkey, publickey) = keypair
+ >>> encrypted = publickey.encrypt(message)
+ >>> assert encrypted != message
+ >>> decrypted = secretkey.decrypt(encrypted)
+ >>> assert message == decrypted
+
+
+ If **filename** already exists, it is assumed to contain a PEM-encoded RSA
+ private key, which will be read from the file. (The parameters of a
+ private RSA key contain the public exponent and public modulus, which
+ together comprise the public key â?? ergo having two separate keyfiles is
+ assumed unnecessary.)
+
+ If **filename** doesn't exist, a new RSA keypair will be created, and the
+ private key will be stored in **filename**, using :func:`writeKeyToFile`.
+
+ Once the private key is either loaded or created, the public key is
+ extracted from it. Both keys are then input into PKCS#1 RSAES-OAEP cipher
+ schemes (see `RFC 3447 §7.1`__) in order to introduce padding, and then
+ returned.
+
+ .. __: https://tools.ietf.org/html/rfc3447#section-7.1
+
+ :param str filename: The filename to which the secret parameters of the
+ RSA key are stored in.
+ :param int bits: If no key is found within the file, create a new key with
+ this bitlength and store it in **filename**.
+ :rtype: tuple of ``Crypto.Cipher.PKCS1_OAEP.PKCS1OAEP_Cipher``
+ :returns: A 2-tuple of ``(privatekey, publickey)``, which are PKCS#1
+ RSAES-OAEP padded and encoded private and public keys, forming an RSA
+ keypair.
+ """
+ filename = os.path.extsep.join([filename, 'sec'])
+ keyfile = os.path.join(os.getcwd(), filename)
+
+ try:
+ fh = open(keyfile, 'rb')
+ except IOError:
+ logging.info("Generating %d-bit RSA keypair..." % bits)
+ secretKey = RSA.generate(bits, e=65537)
+
+ # Store a PEM copy of the secret key (which contains the parameters
+ # necessary to create the corresponding public key):
+ secretKeyPEM = secretKey.exportKey("PEM")
+ writeKeyToFile(secretKeyPEM, keyfile)
+ else:
+ logging.info("Secret RSA keyfile %r found. Loading..." % filename)
+ secretKey = RSA.importKey(fh.read())
+ fh.close()
+
+ publicKey = secretKey.publickey()
+
+ # Add PKCS#1 OAEP padding to the secret and public keys:
+ sk = PKCS1_OAEP.new(secretKey)
+ pk = PKCS1_OAEP.new(publicKey)
+
+ return (sk, pk)
+
def getKey(filename):
"""Load the key stored in ``filename``, or create a new key.
diff --git a/requirements.txt b/requirements.txt
index 72a322c..2d1be77 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,6 +4,7 @@ Mako==0.8.1
MarkupSafe==0.18
Twisted==13.1.0
https://ipaddr-py.googlecode.com/files/ipaddr-2.1.10.tar.gz#sha1=c608450b077b19773d4f1b5f1ef88b26f6650ce0#egg=ipaddr-2.1.10-py2.7
+pycrypto==2.6.1
pyOpenSSL==0.13.1
pygeoip==0.2.7
pygpgme==0.3
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits