Skip to content

Commit

Permalink
Replaced M2Crypto with rsa and PyCrypto
Browse files Browse the repository at this point in the history
  • Loading branch information
dsuch committed Sep 16, 2013
1 parent 97b14d4 commit e3366d8
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 57 deletions.
2 changes: 0 additions & 2 deletions code/_install-darwin.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ pip install distribute==0.6.49
pip install virtualenv==1.9.1

pip install nose
pip install m2crypto
pip install zdaemon

brew tap samueljohn/python
Expand All @@ -44,7 +43,6 @@ brew install libpqxx
brew install samueljohn/python/numpy
brew install scipy

symlink_py 'M2Crypto'
symlink_py 'scipy'
symlink_py 'numpy'

Expand Down
3 changes: 1 addition & 2 deletions code/_install-deb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ sudo apt-get install git bzr gfortran haproxy \
libatlas-dev libatlas3gf-base libblas3gf \
libevent-dev libgfortran3 liblapack-dev liblapack3gf \
libpq-dev libyaml-dev libxml2-dev libxslt1-dev libumfpack5.4.0 \
openssl python2.7-dev python-m2crypto python-numpy python-pip \
openssl python2.7-dev python-numpy python-pip \
python-scipy python-zdaemon swig uuid-dev uuid-runtime

mkdir $CURDIR/zato_extra_paths

symlink_py 'M2Crypto'
symlink_py 'numpy'
symlink_py 'scipy'

Expand Down
3 changes: 1 addition & 2 deletions code/_install-fedora.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ sudo yum install git bzr gcc-gfortran haproxy \
gcc-c++ atlas-devel atlas blas-devel \
libevent-devel libgfortran lapack-devel lapack \
libpqxx-devel libyaml-devel libxml2-devel libxslt-devel suitesparse \
openssl python-devel m2crypto numpy python-pip \
openssl python-devel numpy python-pip \
scipy python-zdaemon swig uuid-devel uuid

mkdir $CURDIR/zato_extra_paths

symlink_py 'M2Crypto'
symlink_py 'numpy'
symlink_py 'scipy'

Expand Down
4 changes: 4 additions & 0 deletions code/buildout-darwin.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,14 @@ eggs =
pip
psutil
psycopg2
pyasn1
pycrypto
pygments
PyMySQL
pyparsing
pyprof2calltree
python-dateutil
python-keyczar
pytz
PyYAML
pyzmq
Expand All @@ -103,6 +106,7 @@ eggs =
repoze.profile
requests
retools
rsa
sec-wall
setproctitle
setuptools
Expand Down
4 changes: 4 additions & 0 deletions code/buildout.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,12 @@ eggs =
pip
psutil
psycopg2
pyasn1
pycrypto
pygments
pyparsing
python-dateutil
python-keyczar
pytz
PyYAML
PyMySQL
Expand All @@ -107,6 +110,7 @@ eggs =
repoze.profile
requests
retools
rsa
sec-wall
setproctitle
setuptools
Expand Down
4 changes: 4 additions & 0 deletions code/versions.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,15 @@ pika = 0.9.12
pip = 1.1
psutil = 0.6.1
psycopg2 = 2.4.5
pyasn1 = 0.1.3
pycrypto = 2.6
PyMySQL = 0.5
PyYAML = 3.10
pygments = 1.5
pyparsing = 1.5.6
pyprof2calltree = 1.1.0
python-dateutil = 2.1
python-keyczar = 0.71c
pytz = 2012h
pyzmq = 2.2.0.1
pyzmq-static = 2.2
Expand All @@ -64,6 +67,7 @@ repoze.lru = 0.6
repoze.profile = 2.0
requests = 1.2.3
retools = 0.3
rsa = 3.1.2
sec-wall = 1.2
setproctitle = 1.1.6
setuptools = 0.6c12dev-r89000
Expand Down
10 changes: 5 additions & 5 deletions code/zato-cli/src/zato/cli/create_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
'config/repo/service-sources.txt':service_sources_contents}

priv_key_location = './config/repo/config-priv.pem'
pub_key_location = './config/repo/config-pub.pem'
priv_key_location = './config/repo/config-pub.pem'

class Create(ZatoCommand):
""" Creates a new Zato server
Expand All @@ -146,7 +146,7 @@ class Create(ZatoCommand):
opts = deepcopy(common_odb_opts)
opts.extend(kvdb_opts)

opts.append({'name':'pub_key_path', 'help':"Path to the server's public key in PEM"})
opts.append({'name':'priv_key_path', 'help':"Path to the server's public key in PEM"})
opts.append({'name':'priv_key_path', 'help':"Path to the server's private key in PEM"})
opts.append({'name':'cert_path', 'help':"Path to the server's certificate in PEM"})
opts.append({'name':'ca_certs_path', 'help':"Path to the a PEM list of certificates the server will trust"})
Expand Down Expand Up @@ -201,7 +201,7 @@ def execute(self, args, port=http_plain_server_port, show_output=True):

repo_dir = os.path.join(self.target_dir, 'config', 'repo')
self.copy_server_crypto(repo_dir, args)
pub_key = open(os.path.join(repo_dir, 'zato-server-pub-key.pem')).read()
priv_key = open(os.path.join(repo_dir, 'zato-server-priv-key.pem')).read()

if show_output:
self.logger.debug('Created a Bazaar repo in {}'.format(repo_dir))
Expand Down Expand Up @@ -233,13 +233,13 @@ def execute(self, args, port=http_plain_server_port, show_output=True):
odb_db_name=args.odb_db_name,
odb_engine=args.odb_type,
odb_host=args.odb_host,
odb_password=encrypt(args.odb_password, pub_key),
odb_password=encrypt(args.odb_password, priv_key),
odb_pool_size=default_odb_pool_size,
odb_user=args.odb_user,
token=self.token,
kvdb_host=args.kvdb_host,
kvdb_port=args.kvdb_port,
kvdb_password=encrypt(args.kvdb_password, pub_key) if args.kvdb_password else '',
kvdb_password=encrypt(args.kvdb_password, priv_key) if args.kvdb_password else '',
initial_cluster_name=args.cluster_name,
initial_server_name=args.server_name,
))
Expand Down
8 changes: 4 additions & 4 deletions code/zato-cli/src/zato/cli/create_web_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def execute(self, args, show_output=True, password=None):
password = password if password else generate_password()

self.copy_web_admin_crypto(repo_dir, args)
pub_key = open(os.path.join(repo_dir, 'web-admin-pub-key.pem')).read()
priv_key = open(os.path.join(repo_dir, 'web-admin-priv-key.pem')).read()

config = {
'host': web_admin_host,
Expand All @@ -112,13 +112,13 @@ def execute(self, args, show_output=True, password=None):
'log_config': 'logging.conf',
'DATABASE_NAME': args.odb_db_name,
'DATABASE_USER': args.odb_user,
'DATABASE_PASSWORD': encrypt(args.odb_password, pub_key),
'DATABASE_PASSWORD': encrypt(args.odb_password, priv_key),
'DATABASE_HOST': args.odb_host,
'DATABASE_PORT': args.odb_port,
'SITE_ID': getrandbits(20),
'SECRET_KEY': encrypt(uuid.uuid4().hex, pub_key),
'SECRET_KEY': encrypt(uuid.uuid4().hex, priv_key),
'ADMIN_INVOKE_NAME':'admin.invoke',
'ADMIN_INVOKE_PASSWORD':encrypt(getattr(args, 'admin_invoke_password', None) or getattr(args, 'tech_account_password'), pub_key),
'ADMIN_INVOKE_PASSWORD':encrypt(getattr(args, 'admin_invoke_password', None) or getattr(args, 'tech_account_password'), priv_key),
}

open(os.path.join(repo_dir, 'logging.conf'), 'w').write(common_logging_conf_contents.format(log_path='./logs/web-admin.log'))
Expand Down
55 changes: 30 additions & 25 deletions code/zato-common/src/zato/common/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,58 +13,63 @@
from base64 import b64decode, b64encode
from hashlib import sha256

# M2Crypto
from M2Crypto import BIO, RSA
# PyCrypto
from Crypto.PublicKey import RSA as pycrypto_rsa

# rsa
import rsa

logger = logging.getLogger(__name__)

class CryptoManager(object):
""" Responsible for management of the server's crypto material.
"""
def __init__(self, priv_key_location=None, pub_key_location=None,
priv_key=None, pub_key=None):
def __init__(self, priv_key_location=None, priv_key=None, pub_key_location=None, pub_key=None):

self.priv_key_location = priv_key_location
self.pub_key_location = pub_key_location

self.priv_key = priv_key
self.pub_key = pub_key

def _get_bio(self, key):
bio = BIO.MemoryBuffer(key)
bio.close()
self.pub_key_location = pub_key_location
self.pub_key = pub_key

return bio
def _pkcs1_from_pkcs8(self, pkcs8):
""" Private keys saved by CLI are in PKCS#8 but the rsa module needs PKCS#1.
Note that PKCS#8 deals with private keys only (https://tools.ietf.org/html/rfc5208).
"""
key = pycrypto_rsa.importKey(pkcs8)
return key.exportKey()

def load_keys(self):
if self.priv_key_location:
self.priv_key = RSA.load_key(self.priv_key_location)
elif self.priv_key:
bio = self._get_bio(self.priv_key)
self.priv_key = RSA.load_key_bio(bio)


if self.pub_key_location:
self.pub_key = RSA.load_pub_key(self.pub_key_location)
elif self.pub_key:
bio = self._get_bio(self.pub_key)
self.pub_key = RSA.load_pub_key_bio(bio)
pkcs1 = open(self.pub_key_location).read()
self.pub_key = rsa.key.PublicKey.load_pkcs1_openssl_pem(pkcs1)
else:
if self.priv_key_location:
pkcs8 = open(self.priv_key_location).read()
pkcs1 = self._pkcs1_from_pkcs8(pkcs8)
elif self.priv_key:
pkcs1 = self._pkcs1_from_pkcs8(self._pkcs1_from_pkcs8(self.priv_key))

self.priv_key = rsa.key.PrivateKey.load_pkcs1(pkcs1)
self.pub_key = rsa.key.PublicKey(self.priv_key.n, self.priv_key.e)

def decrypt(self, data, padding=RSA.pkcs1_padding, hexlified=True):
def decrypt(self, data, hexlified=True):
""" Decrypts data using the private config key. Padding used defaults
to PKCS#1. hexlified defaults to True and indicates whether the data
should be hex-decoded before being decrypted.
"""
if hexlified:
data = b64decode(data)

return self.priv_key.private_decrypt(data, padding).replace('\x00', '')
return rsa.decrypt(data, self.priv_key)

def encrypt(self, data, padding=RSA.pkcs1_padding, b64=True):
def encrypt(self, data, b64=True):
""" Encrypts data using the public config key. Padding used defaults
to PKCS#1. b64 defaults to True and indicates whether the data
should be BASE64-encoded after being encrypted.
"""
encrypted = self.pub_key.public_encrypt(data, padding)
encrypted = rsa.encrypt(data, self.pub_key)
if b64:
return b64encode(encrypted)

Expand Down
24 changes: 7 additions & 17 deletions code/zato-common/src/zato/common/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@
# lxml
from lxml import objectify

# M2Crypto
from M2Crypto import RSA

# pip
from pip.download import is_archive_file, unpack_file_url

Expand Down Expand Up @@ -124,33 +121,29 @@ def pprint(obj):

return value

def encrypt(data, pub_key, padding=RSA.pkcs1_padding, b64=True):
""" Encrypt data using the given public key.
def encrypt(data, priv_key, b64=True):
""" Encrypt data using a public key derived from the private key.
data - data to be encrypted
pub_key - public key to use (as a PEM string)
padding - padding to use, defaults to PKCS#1
priv_key - private key to use (as a PEM string)
b64 - should the encrypted data be BASE64-encoded before being returned, defaults to True
"""
logger.debug('Using pub_key:[{}]'.format(pub_key))

cm = CryptoManager(pub_key=pub_key)
cm = CryptoManager(priv_key=priv_key)
cm.load_keys()

return cm.encrypt(data, padding, b64)
return cm.encrypt(data, b64)

def decrypt(data, priv_key, padding=RSA.pkcs1_padding, b64=True):
def decrypt(data, priv_key, b64=True):
""" Decrypts data using the given private key.
data - data to be encrypted
priv_key - private key to use (as a PEM string)
padding - padding to use, defaults to PKCS#1
b64 - should the data be BASE64-decoded before being decrypted, defaults to True
"""
logger.debug('Using priv_key:[{}]'.format(priv_key))

cm = CryptoManager(priv_key=priv_key)
cm.load_keys()

return cm.decrypt(data, padding, b64)
return cm.decrypt(data, b64)

def get_executable():
""" Returns the wrapper buildout uses for executing Zato commands. This has
Expand Down Expand Up @@ -321,17 +314,14 @@ def get_crypto_manager(repo_location, app_context, config, load_keys=True):
crypto_manager = app_context.get_object('crypto_manager')

priv_key_location = config['crypto']['priv_key_location']
pub_key_location = config['crypto']['pub_key_location']
cert_location = config['crypto']['cert_location']
ca_certs_location = config['crypto']['ca_certs_location']

priv_key_location = absolutize_path(repo_location, priv_key_location)
pub_key_location = absolutize_path(repo_location, pub_key_location)
cert_location = absolutize_path(repo_location, cert_location)
ca_certs_location = absolutize_path(repo_location, ca_certs_location)

crypto_manager.priv_key_location = priv_key_location
crypto_manager.pub_key_location = pub_key_location
crypto_manager.cert_location = cert_location
crypto_manager.ca_certs_location = ca_certs_location

Expand Down
Loading

0 comments on commit e3366d8

Please sign in to comment.