Trust Wallet Vault Decryption
-
Hi everyone,
Has anyone here ever built a Trust Wallet vault decryptor or at least checked how they encrypt it?
I've been digging into it over the past few days but haven't been able to get a working script together yet. From what I can tell, Trust Wallet seems to store two different types of "vaults" in the ldb. One for the mnemonic, and another for something else.
Here's how the entries look like:
"trust:vault": "{\"data\":\"REDACTED\",\"iv\":\"REDACTED\",\"salt\":\"REDACTED\"}"
and
"crypto": { "cipher": "aes-128-ctr", "cipherparams": { "iv": "REDACTED" }, "ciphertext": "REDACTED", "kdf": "scrypt", "kdfparams": { "dklen": 32, "n": 16384, "p": 4, "r": 8, "salt": "REDACTED" }, "mac": "REDACTED" }
Additionally there was this in the ldb:
"trust:pbkdf2": "\"{\\\"salt\\\":\\\"0xREDACTED\\\"}\"",
I'd really appreciate any help
-
Share with us?
-
Okay, i will answer by myself
here is gpt-translated code from c to python:
import json import base64 from Crypto.Cipher import AES from Crypto.Util.Padding import unpad from Crypto.Protocol.KDF import scrypt, PBKDF2 from Crypto.Hash import SHA256, SHA512, SHA3_256, HMAC, keccak def hexify(data): return data.hex() def keccak256(data): h = keccak.new(digest_bits=256) h.update(data) return h.digest() def decode_utf8(data): try: return data.decode('utf-8') except UnicodeDecodeError: return None def decrypt_data(json_data, password): if "trust:pbkdf2" in json_data: pbkdf2_salt = bytes.fromhex(json_data["trust:pbkdf2"]["salt"][2:]) pre_derived_password = PBKDF2( password=password.encode(), salt=pbkdf2_salt, dkLen=512, count=20000, prf=lambda p, s: HMAC.new(p, s, SHA512).digest() ) password_hex = "0x" + hexify(pre_derived_password) password = password_hex crypto = json_data["crypto"] kdf = crypto["kdf"] kdfparams = crypto["kdfparams"] salt = bytes.fromhex(kdfparams["salt"]) if kdf == "scrypt": derived_key = scrypt( password.encode(), salt, key_len=kdfparams["dklen"], N=kdfparams["n"], r=kdfparams["r"], p=kdfparams["p"] ) elif kdf == "pbkdf2": derived_key = PBKDF2( password=password.encode(), salt=salt, dkLen=kdfparams["dklen"], count=kdfparams.get("c", 100000), prf=lambda p, s: HMAC.new(p, s, SHA256).digest() ) else: raise ValueError(f"Unsupported KDF: {kdf}") ciphertext = bytes.fromhex(crypto["ciphertext"]) mac_data = derived_key[16:] + ciphertext computed_mac = keccak256(mac_data).hex() if computed_mac != crypto["mac"]: raise ValueError("MAC mismatch - wrong password or corrupted data") cipher = crypto["cipher"] iv = bytes.fromhex(crypto["cipherparams"]["iv"]) key_length = 16 if cipher.startswith("aes-128-") else 32 key = derived_key[:key_length] if cipher.endswith("-ctr"): cipher_impl = AES.new(key, AES.MODE_CTR, nonce=b'', initial_value=iv) elif cipher.endswith("-cbc"): cipher_impl = AES.new(key, AES.MODE_CBC, iv) decrypted_data = unpad(cipher_impl.decrypt(ciphertext), AES.block_size) else: raise ValueError(f"Unsupported cipher mode: {cipher}") decrypted_data = cipher_impl.decrypt(ciphertext) result = decode_utf8(decrypted_data) if result: return result if "trust:vault" in json_data: try: vault_data = base64.b64decode(json_data["trust:vault"]["data"]) return vault_data.decode('utf-8', errors='replace') except: return decrypted_data return decrypted_data if __name__ == "__main__": json_example = """{ "crypto" : { "cipher": "aes-128-ctr", "cipherparams": { "iv": "ec81fd1d75250f04b6d5d6b3ba84eb79" }, "ciphertext": "96e0bb368e96d1ffc0c4be3aa14092f5a0366eea054e5fa6cef5a10bf7396e2cada1557a42595205898caa96e4db58f7e1a8203c2a92ad0c8513beeb9ee2bd1e7fa5d706d0320a93d28d", "kdf": "scrypt", "kdfparams": { "dklen": 32, "n": 16384, "p": 4, "r": 8, "salt": "cd48e825f9e70fc3543cb50c6a68ec01395d9bc5e684de95dd3dfabb88392721" }, "mac": "77af8487b3ff04525d66d1e3a7c4ee3df5e5b8a0f2a5e613c9f46e4654855986" }, "trust:pbkdf2" : { "salt": "0xfe4da3b335af5d0affc25784c9764477c0215ac9a48b0167faa9186bdbe8a0ba" } } """ data = json.loads(json_example) password = "Hashpwn.net1" try: decrypted = decrypt_data(data, password) print("\nSuccessfully decrypted:") print(decrypted) except Exception as e: print(f"\nDecryption failed: {str(e)}")
-
@potato100500 How did you extract vault data, which file you used? I checked one of trustwallet .ldb and found other vault format. It differ from one you posted in your script.