Enhance encryption handling with error reporting and validation#4787
Enhance encryption handling with error reporting and validation#4787sergei-boiko-trustwallet wants to merge 10 commits into
Conversation
Summary by OctaneNew Contracts
Updated Contracts
🔗 Commit Hash: ad8c14a |
|
This PR touches persistence-sensitive files: Post a comment with one of:
Each token must be accompanied by >=60 chars of reasoning. The reasoning must be fresh — posted or edited at or after the HEAD commit. Why audit evidence is required for Pass / Mitigated: humans don't reliably ask the right BC question on every PR. AI being in the loop is the whole point of this gate. The bot does not judge whether your reasoning is correct — reviewers do, like any other code review. Things worth thinking about: could a previous version have written data this PR's new check would now reject? Was there a partial migration ("regenerate on next user action") that may not have completed for all users? Does this format live in iCloud / Google Drive backup, exported files, or sync payloads? See Changed files (8)
Copy this audit prompt into Claude Code on this branch (or run the
|
There was a problem hiding this comment.
Pull request overview
This PR modernizes encryption-related error handling in Wallet Core by introducing a standardized FFI “void result” type (TWResultVoid) and refactoring fixEncryption (and related keystore code) to return structured success/error outcomes with descriptive messages across language bindings.
Changes:
- Introduces
TWResultVoidin the Rust FFI layer (plus interface tests) and integrates it into the public C API surface. - Refactors
TWStoredKeyFixEncryptionto returnTWResultVoid*and propagates exception-based error messages instead of boolean/enums. - Updates multi-platform tests (C++/Rust/Swift/Android/Wasm) to validate success/error states and error strings.
Reviewed changes
Copilot reviewed 20 out of 22 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| wasm/tests/KeyStore+fs.test.ts | Updates Wasm keystore test to use TWResultVoid-style result object and delete it. |
| wasm/tests/KeyStore+extension.test.ts | Same as above for extension storage variant. |
| wasm/tests/KeyStore.test.ts | Uses result object from fixEncryption() and releases it; keeps behavior assertions. |
| tests/interface/TWStoredKeyTests.cpp | Updates TWStoredKeyFixEncryption tests to assert success/error and verify error message. |
| tests/interface/TWResultVoidTests.cpp | Adds C++ interface tests validating TWResultVoid behavior. |
| tests/common/Keystore/StoredKeyTests.cpp | Updates exception expectations after removal of custom decryption enums. |
| swift/Tests/Keystore/KeyStoreTests.swift | Updates Swift tests to assert fixEncryption error message on wrong password. |
| src/Keystore/StoredKey.h | Updates API docs to reflect exception types thrown. |
| src/Keystore/StoredKey.cpp | Replaces custom decryption error with std::invalid_argument and message for invalid JSON format. |
| src/Keystore/EncryptionParameters.h | Removes DecryptionError enum from keystore parameters. |
| src/Keystore/EncryptionParameters.cpp | Switches validation to TW::Result<void> and refactors decrypt errors to standard exceptions/messages. |
| src/Keystore/AESParameters.h | Changes AES parameter validation to return TW::Result<void> with message. |
| src/Keystore/AESParameters.cpp | Implements new validation result with detailed IV-size error. |
| src/interface/TWStoredKey.cpp | Changes TWStoredKeyFixEncryption to return TWResultVoid* and map exceptions to error messages. |
| rust/tw_memory/tests/tw_result_ffi_tests.rs | Adds Rust-side FFI tests covering success/error/null-pointer behavior and deletion. |
| rust/tw_memory/src/ffi/tw_result.rs | Adds Rust FFI implementation of TWResultVoid and its exported functions. |
| rust/tw_memory/src/ffi/mod.rs | Exposes the new tw_result module. |
| rust/tw_memory/Cargo.toml | Adds tw_macros dependency for FFI metadata generation. |
| rust/Cargo.lock | Locks in the new tw_macros dependency for tw_memory. |
| include/TrustWalletCore/TWStoredKey.h | Updates public header: TWStoredKeyFixEncryption now returns TWResultVoid* with updated docs. |
| android/app/src/androidTest/java/com/trustwallet/core/app/utils/TestKeyStore.kt | Updates Android instrumentation test to assert fixEncryption error message on wrong password. |
| .gitignore | Ignores generated include/TrustWalletCore/TWResultVoid.h. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Binary size comparison➡️ aarch64-apple-ios: 14.31 MB ➡️ aarch64-apple-ios-sim: 14.32 MB ➡️ aarch64-linux-android: - 18.73 MB
+ 18.73 MB +3 KB➡️ armv7-linux-androideabi: - 16.17 MB
+ 16.17 MB +3 KB➡️ wasm32-unknown-emscripten: - 13.66 MB
+ 13.66 MB -1 KB |
Overview
Detailed findings
|
…nd Encryption parameters * Add `deep-review` skill
…ges in validation
|
[bc-check: Risk-Accepted] BC-risk audit — fix/ripple-x-address-tag → master @ 175af63 — 2026-06-03Verdict: RISK (investigated; blast radius is effectively zero for user keystore data) Finding: All keystore JSON fields are unchanged:
Recommended action: Bump version minor to signal ABI change; note in release notes that |
|
[bc-check: Risk-Accepted] BC-risk audit — fix/ripple-x-address-tag → master @ 175af63 — 2026-06-03Verdict: RISK (investigated; blast radius is effectively zero for user keystore data) Finding: All keystore JSON fields are unchanged:
Recommended action: Bump version minor to signal ABI change; note in release notes that |
Summary
TWResultVoid— new structured error type. A lightweight Rust-backed result type(
TWResultVoidCreateOk/TWResultVoidCreateError) is exposed through the C ABI andregenerated into all binding layers (Swift, Kotlin/KMP, JNI C, WASM). It carries an
optional error string so callers can distinguish failure reasons without parsing exception
messages.
TWStoredKeyFixEncryptionreturn type:bool→TWResultVoid*. Callers can now getthe actual error message (e.g.
"Invalid password: MAC verification failed") instead of aboolean false. Breaking C ABI change — existing compiled binaries that read the return
as
boolwill always seetrue(non-null pointer), which is a silent no-op on failure.Documented in
docs/bc-footguns.md.New API:
TWStoredKeyValidateJsonandTWStoredKeyValidateFile. Structural validationof a keystore JSON blob or file path without decrypting. Confirms the crypto parameters
(KDF, cipher, IV) are well-formed without requiring the password.
KeyStore.invalidKeys(Swift).KeyStorenow surfaces files that failed to load as[InvalidKey]instead of silently discarding them. Each entry carries the file URL, ahuman-readable error, whether it looks like a third-party keystore (top-level
addressfield), and the first account address if present in the JSON.
DecryptionErrorandAESValidationErrorenums removed. All error paths now throwstd::invalid_argumentorstd::runtime_errorwith descriptive messages, making errortext visible at the C ABI boundary.
Bug fix:
@Testannotation was missing ontestFixScryptWithEmptySaltin the Androidinstrumented tests — that test was silently never running.
Test plan
./build/tests/tests --gtest_filter="*StoredKey*"and--gtest_filter="*TWResultVoid*"tools/ios-test):testValidateFile,testValidateJson,testLoadAllInvalidKeys,testLoadOneInvalidKeyAlongsideValidWallet,testLoadInvalidKeysEmptyWhenAllWalletsAreValid,testFixScryptWithEmptySalt./gradlew connectedAndroidTest):testValidateFile,testValidateJson,testFixScryptWithEmptySaltcd wasm && npm run build-and-test):test validateJson,test fix scrypt with empty salt