Source code for multiversx_sdk.wallet.crypto.decryptor

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, hmac
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.kdf.scrypt import Scrypt

from multiversx_sdk.wallet.crypto.constants import (
    CIPHER_ALGORITHM_AES_128_CTR, KEY_DERIVATION_FUNCTION_SCRYPT)
from multiversx_sdk.wallet.crypto.encrypted_data import EncryptedData
from multiversx_sdk.wallet.errors import (InvalidKeystoreFilePasswordError,
                                          UnknownCipherError,
                                          UnknownDerivationFunctionError)


[docs] def decrypt(encrypted_data: EncryptedData, password: str) -> bytes: """ Also see: https://github.com/multiversx/mx-sdk-js-wallet/blob/main/src/crypto/decryptor.ts """ backend = default_backend() if encrypted_data.kdf != KEY_DERIVATION_FUNCTION_SCRYPT: raise UnknownDerivationFunctionError() if encrypted_data.cipher != CIPHER_ALGORITHM_AES_128_CTR: raise UnknownCipherError(name=encrypted_data.cipher) salt = bytes.fromhex(encrypted_data.salt) iv = bytes.fromhex(encrypted_data.iv) ciphertext = bytes.fromhex(encrypted_data.ciphertext) kdf = Scrypt( salt=salt, length=encrypted_data.kdfparams.dklen, n=encrypted_data.kdfparams.n, r=encrypted_data.kdfparams.r, p=encrypted_data.kdfparams.p, backend=backend ) derived_key = kdf.derive(bytes(password.encode())) derived_key_first_half = derived_key[0:16] derived_key_second_half = derived_key[16:32] h = hmac.HMAC(derived_key_second_half, hashes.SHA256(), backend=backend) h.update(ciphertext) computed_mac = h.finalize() actual_mac = bytes.fromhex(encrypted_data.mac) if computed_mac != actual_mac: raise InvalidKeystoreFilePasswordError() cipher = Cipher(algorithms.AES(derived_key_first_half), modes.CTR(iv), backend=backend) decryptor = cipher.decryptor() data = decryptor.update(ciphertext) + decryptor.finalize() return data