Source code for concurrent.core.util.cryptohelper
# -*- coding: utf-8 -*-
"""
Cryptographic helper
"""
import Crypto.Random
from Crypto.Cipher import AES
import hashlib
import base64
[docs]class CryptoHelper(object):
"""
Crypto helper used in the framework
"""
def __init__(self, salt_size, num_iterations, aes_padding):
self.salt_size = salt_size
self.num_iterations = num_iterations
self.aes_padding = aes_padding
def _generate_key(self, password, salt, iterations):
assert iterations > 0
key = password + salt
for i in range(iterations):
key = hashlib.sha256(key).digest()
return key
def _pad_text(self, text, multiple):
extra_bytes = len(text) % multiple
padding_size = multiple - extra_bytes
padding = chr(padding_size) * padding_size
padded_text = text + padding
return padded_text
def _unpad_text(self, padded_text):
padding_size = ord(padded_text[-1])
text = padded_text[:-padding_size]
return text
[docs] def encrypt(self, plaintext, password):
plaintext = base64.b64encode(plaintext)
password = base64.b64encode(password)
salt = Crypto.Random.get_random_bytes(self.salt_size)
key = self._generate_key(password, salt, self.num_iterations)
cipher = AES.new(key, AES.MODE_ECB)
padded_plaintext = self._pad_text(plaintext, self.aes_padding)
ciphertext = cipher.encrypt(padded_plaintext)
return salt + ciphertext
[docs] def decrypt(self, ciphertext, password):
password = base64.b64encode(password)
salt = ciphertext[0:self.salt_size]
ciphertext_sans_salt = ciphertext[self.salt_size:]
key = self._generate_key(password, salt, self.num_iterations)
cipher = AES.new(key, AES.MODE_ECB)
padded_plaintext = cipher.decrypt(ciphertext_sans_salt)
return base64.b64decode(self._unpad_text(padded_plaintext))