Switch from pycrypto to cryptography

PyCrypto seems to no longer be maintained and has issues with
Python 3+. This patch switches refstack-client to use the cryptography
library instead. Cryptography is actively maintained and works with
later versions of Python.

Change-Id: Ie6d1405b1d48bcf12b6064f32a77810cbfc46a86
This commit is contained in:
Luz Cazares 2017-06-21 05:30:13 +00:00
parent 8c83694691
commit ef1cc141a3
2 changed files with 45 additions and 29 deletions

View File

@ -35,9 +35,12 @@ import os
import subprocess import subprocess
import time import time
from Crypto.Hash import SHA256 from cryptography.exceptions import UnsupportedAlgorithm
from Crypto.PublicKey import RSA from cryptography.hazmat import backends
from Crypto.Signature import PKCS1_v1_5 from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
import requests import requests
import requests.exceptions import requests.exceptions
import six.moves import six.moves
@ -361,26 +364,32 @@ class RefstackClient:
return results return results
def post_results(self, url, content, sign_with=None): def post_results(self, url, content, sign_with=None):
'''Post the combined results back to the server.''' '''Post the combined results back to the refstack server.'''
endpoint = '%s/v1/results/' % url endpoint = '%s/v1/results/' % url
headers = {'Content-type': 'application/json'} headers = {'Content-type': 'application/json'}
data = json.dumps(content) data = json.dumps(content)
self.logger.debug('API request content: %s ' % content) self.logger.debug('API request content: %s ' % content)
if sign_with: if sign_with:
data_hash = SHA256.new() with open(sign_with) as private_key_file:
data_hash.update(data.encode('utf-8'))
with open(sign_with) as key_pair_file:
try: try:
key = RSA.importKey(key_pair_file.read()) private_key = serialization.load_pem_private_key(
except (IOError, ValueError) as e: private_key_file.read().encode('utf-8'),
self.logger.info('Error during upload key pair %s' password=None,
'' % key_pair_file) backend=backends.default_backend())
except (IOError, UnsupportedAlgorithm, ValueError) as e:
self.logger.info('Error during upload key pair %s' %
private_key_file)
self.logger.exception(e) self.logger.exception(e)
return return
signer = PKCS1_v1_5.new(key) signer = private_key.signer(padding.PKCS1v15(), hashes.SHA256())
sign = signer.sign(data_hash) signer.update(data.encode('utf-8'))
headers['X-Signature'] = binascii.b2a_hex(sign) signature = binascii.b2a_hex(signer.finalize())
headers['X-Public-Key'] = key.publickey().exportKey('OpenSSH') pubkey = private_key.public_key().public_bytes(
serialization.Encoding.OpenSSH,
serialization.PublicFormat.OpenSSH)
headers['X-Signature'] = signature
headers['X-Public-Key'] = pubkey
try: try:
response = requests.post(endpoint, response = requests.post(endpoint,
data=data, data=data,
@ -563,27 +572,34 @@ class RefstackClient:
def _sign_pubkey(self): def _sign_pubkey(self):
"""Generate self signature for public key""" """Generate self signature for public key"""
private_key_file = self.args.priv_key_to_sign
try: try:
with open(self.args.priv_key_to_sign) as priv_key_file: with open(private_key_file) as pkf:
private_key = RSA.importKey(priv_key_file.read()) private_key = serialization.load_pem_private_key(
except (IOError, ValueError) as e: pkf.read().encode('utf-8'),
password=None,
backend=backends.default_backend())
except (IOError, UnsupportedAlgorithm, ValueError) as e:
self.logger.error('Error reading private key %s' self.logger.error('Error reading private key %s'
'' % self.args.priv_key_to_sign) '' % private_key_file)
self.logger.exception(e) self.logger.exception(e)
return return
pubkey_filename = '.'.join((self.args.priv_key_to_sign, 'pub'))
public_key_file = '.'.join((private_key_file, 'pub'))
try: try:
with open(pubkey_filename) as pub_key_file: with open(public_key_file) as pkf:
pub_key = pub_key_file.read() pub_key = pkf.read()
except IOError: except IOError:
self.logger.error('Public key file %s not found. ' self.logger.error('Public key file %s not found. '
'Public key is generated from private one.' 'Public key is generated from private one.'
'' % pubkey_filename) '' % public_key_file)
pub_key = private_key.publickey().exportKey('OpenSSH') pub_key = private_key.public_key().public_bytes(
data_hash = SHA256.new() serialization.Encoding.OpenSSH,
data_hash.update('signature'.encode('utf-8')) serialization.PublicFormat.OpenSSH)
signer = PKCS1_v1_5.new(private_key)
signature = binascii.b2a_hex(signer.sign(data_hash)) signer = private_key.signer(padding.PKCS1v15(), hashes.SHA256())
signer.update('signature'.encode('utf-8'))
signature = binascii.b2a_hex(signer.finalize())
return pub_key, signature return pub_key, signature
def self_sign(self): def self_sign(self):

View File

@ -1,6 +1,6 @@
gitpython>=0.3.2.RC1 gitpython>=0.3.2.RC1
python-subunit>=0.0.18 python-subunit>=0.0.18
pycrypto>=2.6.1 cryptography>=1.0,!=1.3.0 # BSD/Apache-2.0
requests>=2.5.2 requests>=2.5.2
PyYAML>=3.1.0 PyYAML>=3.1.0
six>=1.9.0 six>=1.9.0