[Python] Crypto wallet mac verification

Discussão em 'Python' iniciado por Stack, Agosto 14, 2025.

  1. Stack

    Stack Membro Participativo

    I am attempting to understand how a Chrome extension–based cryptocurrency wallet stores and verifies the seed phrase locally. From an exported keystore (real data from a dummy wallet of course)

    {
    "cipher": "aes-128-ctr",
    "cipherparams": { "iv": "eeebb71712efaa9f6d428a5be3a70c2b" },
    "ciphertext": "a220e41509363eb2a69a69de4cae34c87ee57c56bfa7117ac1f4e3b2665ccd313baef8934b46f331bab3e91b18cff57269ebfe2036a9fbf5b62459328f9a3dea8c81eed096bdb80a806110",
    "kdf": "scrypt",
    "kdfparams": {
    "dklen": 32, "n": 16384, "p": 4, "r": 8,
    "salt": "7e0b6b8681461b10995c8f347010d3ed0fc7c5b4ae4c07682792053c5d538b26"
    },
    "mac": "e84f8c77a491d30769dff6597d1853279355c57494865033105c6dd6cb975d70"
    }


    According to the wallet’s source code, Keccak‑256 is used to generate the MAC. I attempted to replicate this using PyCryptodome in Python with the following code, but the computed MAC does not match the stored value:

    from Crypto.Protocol.KDF import scrypt
    from Crypto.Hash import keccak

    data = {
    ...
    }

    ciphertext = bytes.fromhex(data["ciphertext"])
    salt = bytes.fromhex(data["kdfparams"]["salt"])
    password = "123456789t"

    derived_key = scrypt(password.encode(),
    salt=salt,
    key_len=data["kdfparams"]["dklen"],
    N=data["kdfparams"]["n"],
    r=data["kdfparams"]["r"],
    p=data["kdfparams"]["p"]
    )

    computed_mac = keccak.new(digest_bits=256).update(derived_key[-16:] + ciphertext).hexdigest()
    print(computed_mac)
    print(data["mac"])


    Computed mac 1cf3468633eaa69c9b66316c5dfae7d43f8d42df204f79406778aafe75fd16e0

    Expected mac e84f8c77a491d30769dff6597d1853279355c57494865033105c6dd6cb975d70

    Wallet source: https://github.com/trustwallet/wallet-core/blob/master/src/Keystore/EncryptionParameters.cpp#L24

    Continue reading...

Compartilhe esta Página