Refactor the util directory to use subpackages.

This commit is contained in:
Jake Moshenko 2015-08-03 15:49:10 -04:00
parent 974ccaa2e7
commit 18100be481
46 changed files with 36 additions and 39 deletions

View file

32
util/security/aes.py Normal file
View file

@ -0,0 +1,32 @@
import base64
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
class AESCipher(object):
""" Helper class for encrypting and decrypting data via AES.
Copied From: http://stackoverflow.com/a/21928790
"""
def __init__(self, key):
self.bs = 32
self.key = key
def encrypt(self, raw):
raw = self._pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(raw))
def decrypt(self, enc):
enc = base64.b64decode(enc)
iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]

69
util/security/signing.py Normal file
View file

@ -0,0 +1,69 @@
import gpgme
import os
from StringIO import StringIO
class GPG2Signer(object):
""" Helper class for signing data using GPG2. """
def __init__(self, app, key_directory):
if not app.config.get('GPG2_PRIVATE_KEY_NAME'):
raise Exception('Missing configuration key GPG2_PRIVATE_KEY_NAME')
if not app.config.get('GPG2_PRIVATE_KEY_FILENAME'):
raise Exception('Missing configuration key GPG2_PRIVATE_KEY_FILENAME')
if not app.config.get('GPG2_PUBLIC_KEY_FILENAME'):
raise Exception('Missing configuration key GPG2_PUBLIC_KEY_FILENAME')
self._ctx = gpgme.Context()
self._ctx.armor = True
self._private_key_name = app.config['GPG2_PRIVATE_KEY_NAME']
self._public_key_path = os.path.join(key_directory, app.config['GPG2_PUBLIC_KEY_FILENAME'])
key_file = os.path.join(key_directory, app.config['GPG2_PRIVATE_KEY_FILENAME'])
if not os.path.exists(key_file):
raise Exception('Missing key file %s' % key_file)
with open(key_file, 'rb') as fp:
self._ctx.import_(fp)
@property
def name(self):
return 'gpg2'
@property
def public_key_path(self):
return self._public_key_path
def detached_sign(self, stream):
""" Signs the given stream, returning the signature. """
ctx = self._ctx
ctx.signers = [ctx.get_key(self._private_key_name)]
signature = StringIO()
new_sigs = ctx.sign(stream, signature, gpgme.SIG_MODE_DETACH)
signature.seek(0)
return signature.getvalue()
class Signer(object):
def __init__(self, app=None, key_directory=None):
self.app = app
if app is not None:
self.state = self.init_app(app, key_directory)
else:
self.state = None
def init_app(self, app, key_directory):
preference = app.config.get('SIGNING_ENGINE', None)
if preference is None:
return None
return SIGNING_ENGINES[preference](app, key_directory)
def __getattr__(self, name):
return getattr(self.state, name, None)
SIGNING_ENGINES = {
'gpg2': GPG2Signer
}

10
util/security/ssh.py Normal file
View file

@ -0,0 +1,10 @@
from Crypto.PublicKey import RSA
def generate_ssh_keypair():
"""
Generates a new 2048 bit RSA public key in OpenSSH format and private key in PEM format.
"""
key = RSA.generate(2048)
public_key = key.publickey().exportKey('OpenSSH')
private_key = key.exportKey('PEM')
return (public_key, private_key)