MCPcopy Create free account
hub / github.com/StackStorm/st2 / cryptography_symmetric_decrypt

Function cryptography_symmetric_decrypt

st2common/st2common/util/crypto.py:293–351  ·  view source on GitHub ↗

Decrypt the provided ciphertext which has been encrypted using symmetric_encrypt() method (it assumes input is in hex notation as returned by binascii.hexlify). NOTE 1: This function assumes ciphertext has been encrypted using symmetric AES crypto from keyczar library. Underneath i

(decrypt_key, ciphertext)

Source from the content-addressed store, hash-verified

291
292
293def cryptography_symmetric_decrypt(decrypt_key, ciphertext):
294 """
295 Decrypt the provided ciphertext which has been encrypted using symmetric_encrypt() method (it
296 assumes input is in hex notation as returned by binascii.hexlify).
297
298 NOTE 1: This function assumes ciphertext has been encrypted using symmetric AES crypto from
299 keyczar library. Underneath it uses crypto primitives from cryptography library which is Python
300 3 compatible.
301
302 NOTE 2: This function is loosely based on keyczar AESKey.Decrypt() (Apache 2.0 license).
303 """
304 if not isinstance(decrypt_key, AESKey):
305 raise TypeError(
306 "Decrypted key needs to be an AESKey class instance"
307 f" (was {type(decrypt_key)})."
308 )
309 if not isinstance(ciphertext, (six.text_type, six.string_types, six.binary_type)):
310 raise TypeError(
311 "Ciphertext needs to either be a string/unicode or bytes"
312 f" (was {type(ciphertext)})."
313 )
314 aes_key_bytes = decrypt_key.aes_key_bytes
315 hmac_key_bytes = decrypt_key.hmac_key_bytes
316
317 if not isinstance(aes_key_bytes, six.binary_type):
318 raise TypeError(f"AESKey is not bytes (it is {type(aes_key_bytes)}).")
319 if not isinstance(hmac_key_bytes, six.binary_type):
320 raise TypeError(f"HMACKey is not bytes (it is {type(hmac_key_bytes)}).")
321
322 # Convert from hex notation ASCII string to bytes
323 ciphertext = binascii.unhexlify(ciphertext)
324
325 data_bytes = ciphertext[KEYCZAR_HEADER_SIZE:] # remove header
326
327 # Verify ciphertext contains IV + HMAC signature
328 if len(data_bytes) < (KEYCZAR_AES_BLOCK_SIZE + KEYCZAR_HLEN):
329 raise ValueError("Invalid or malformed ciphertext (too short)")
330
331 iv_bytes = data_bytes[:KEYCZAR_AES_BLOCK_SIZE] # first block is IV
332 ciphertext_bytes = data_bytes[
333 KEYCZAR_AES_BLOCK_SIZE:-KEYCZAR_HLEN
334 ] # strip IV and signature
335 signature_bytes = data_bytes[-KEYCZAR_HLEN:] # last 20 bytes are signature
336
337 # Verify HMAC signature
338 backend = default_backend()
339 h = hmac.HMAC(hmac_key_bytes, hashes.SHA1(), backend=backend)
340 h.update(ciphertext[:-KEYCZAR_HLEN])
341 h.verify(signature_bytes)
342
343 # Decrypt ciphertext
344 cipher = Cipher(algorithms.AES(aes_key_bytes), modes.CBC(iv_bytes), backend=backend)
345
346 decryptor = cipher.decryptor()
347 decrypted = decryptor.update(ciphertext_bytes) + decryptor.finalize()
348
349 # Unpad
350 decrypted = pkcs5_unpad(decrypted)

Calls 2

pkcs5_unpadFunction · 0.85
updateMethod · 0.45