def decrypt_master_key(self, master_password, data): ''' dkLen=32 corresponds to AES256 key (32 bytes). Return (kdf_salt, hmac_salt, encrypted data, hmac(kdf_salt, hmac_salt, encrypted data)). hashlib.sha3_256 produces 32 bytes hash. :Arguments: master_password: string or byte string data: bytes :Returns: bytes [ PBKDF2 :Arguments: password: string or byte string salt: string or byte string dkLen: integer count: integer prf: callable hmac_hash_module: module PBKDF2 :Returns: A byte string of length ``dkLen`` that can be used as key material. ] ''' kdf_salt = data[:self.SALT_SIZE] hmac_salt = data[self.SALT_SIZE:self.SALT_SIZE * 2] encryption_key = KDF.PBKDF2( master_password, kdf_salt, dkLen=self.DK_LEN, count=self.KDF_COUNT, hmac_hash_module=self.PBKDF_HMAC_HASH_MODULE) hmac_key = KDF.PBKDF2(master_password, hmac_salt, dkLen=self.DK_LEN, count=self.KDF_COUNT, hmac_hash_module=self.PBKDF_HMAC_HASH_MODULE) hmac_ = hmac.new(hmac_key, data[:-self.HMAC_HASH_SIZE], digestmod=self.HMAC_DIGESTMOD).digest() if hmac_ != data[-self.HMAC_HASH_SIZE:]: raise Exception('Bad hmac!') master_key = self.decrypt( encryption_key, data[self.SALT_SIZE * 2:-self.HMAC_HASH_SIZE]) return master_key
def encrypt_master_key(self, master_password, master_key): ''' dkLen=32 corresponds to AES256 key (32 bytes). Return (kdf_salt, hmac_salt, encrypted data, hmac(kdf_salt, hmac_salt, encrypted data)). hashlib.sha3_256 produces 32 bytes hash. :Arguments: master_password: string or byte string master_key: bytes :Returns: bytes (total 112 bytes in lenght) [ PBKDF2 :Arguments: password: string or byte string salt: string or byte string dkLen: integer count: integer prf: callable hmac_hash_module: module PBKDF2 :Returns: A byte string of length ``dkLen`` that can be used as key material. ] ''' kdf_salt = self.get_salt() hmac_salt = self.get_salt() iv = self.get_iv() encryption_key = KDF.PBKDF2( master_password, kdf_salt, dkLen=self.DK_LEN, count=self.KDF_COUNT, hmac_hash_module=self.PBKDF_HMAC_HASH_MODULE) hmac_key = KDF.PBKDF2(master_password, hmac_salt, dkLen=self.DK_LEN, count=self.KDF_COUNT, hmac_hash_module=self.PBKDF_HMAC_HASH_MODULE) encrypted_master_key = self.encrypt(encryption_key, iv, master_key) data = kdf_salt + hmac_salt + encrypted_master_key data += hmac.new(hmac_key, data, digestmod=self.HMAC_DIGESTMOD).digest() return data
def decrypt(ciphertext, key, keylen=KEYLEN): """Decrypt bytes using AES-CBC with keys of length `keylen` (defaults to KEYLEN: 256 bits). @param ciphertext: Data to be decrypted. @type ciphertext: bytes @param key: Encryption passphrase. @type key: str, bytes @param keylen: Length of the key to use in bytes. Can be either 16, 24 or 32. @type keylen: str, bytes @return: The decrypted ciphertext. @rtype : bytes @raise ValueError: Incorrect padding. Happens if passphrase is incorrect. """ ciphertext = base64.b64decode(ciphertext) salt = ciphertext[:AES.block_size] iv = ciphertext[AES.block_size:2 * AES.block_size] key = KDF.PBKDF2(key, salt, dkLen=keylen) cipher = AES.new(key, AES.MODE_CBC, iv=iv) return Padding.unpad(cipher.decrypt(ciphertext[2 * AES.block_size:]), AES.block_size)
def encrypt(plaintext, key, keylen=KEYLEN): """Encrypt bytes using AES-CBC with keys of length `keylen` (defaults to KEYLEN: 256 bits). Key is passed in KDF `PBKDF2` in order to protect weak keys against brute force attacks. @param plaintext: Data to be encrypted. @type plaintext: bytes @param key: Encryption passphrase. @type key: str, bytes @param keylen: Length of the key to use in bytes. Can be either 16, 24 or 32. @type keylen: str, bytes @return: The produced ciphertext. @rtype : bytes @raise ValueError: Incorrect padding. Happens if passphrase is incorrect. """ salt = Random.new().read(AES.block_size) iv = Random.new().read(AES.block_size) key = KDF.PBKDF2(key, salt, dkLen=keylen) plaintext = Padding.pad(plaintext, AES.block_size) cipher = AES.new(key, AES.MODE_CBC, iv=iv) return base64.b64encode(salt + iv + cipher.encrypt(plaintext))
def derive_key(passphrase, keysize): """ derive key of desired bytesize from passphrase """ key = KDF.PBKDF2(passphrase, SALT, keysize) if len(key) != keysize: msg = "Attention! Something has gone wrong when deriving key from passphrase!" raise RuntimeError(msg) ks2cipher = {16: 'aes128', 24: 'aes192', 32: 'aes256'} cipher_name = ks2cipher[keysize] return cipher_name, key
def _apply_pbkdf(passphrase, salt): return KDF.PBKDF2(passphrase, salt, 32, 10000, lambda p, s: hmac.new(p, s, hashlib.sha256).digest())
def kdf(password, salt): return KDF.PBKDF2(password, salt, dkLen=32, count=2000)
def __init__(self, key, salt): self.__key = KDF.PBKDF2(password=key, salt=salt.encode(), dkLen=32, count=10000, prf=_prf)