WAL-1868: Express endpoint to verify a TSS EdDSA key belongs to a wallet - #9873
yashaanand wants to merge 1 commit into
Conversation
|
|
|
@claude review this PR? are there any critical blockers? |
|
Claude finished @yashaanand's task —— View job PR Review AnalysisReviewing PR for critical blockers and security issues... Todo List:
✅ No Critical Blockers FoundThis PR implements a secure TSS EdDSA key verification feature with excellent security practices. Here's my analysis: 🔒 Security Review - EXCELLENTKey Material Protection:
Error Handling:
🏗️ Architecture Review - SOLIDClean Separation of Concerns:
Extensible Design:
🧪 Test Coverage - COMPREHENSIVESecurity-First Testing:
Edge Cases Covered:
🚀 Implementation Quality - HIGHDefensive Programming:
Performance:
📝 Documentation & Standards - GOOD
Minor Observations (Non-blocking):
🎯 Recommendation: APPROVEThis PR demonstrates exemplary security practices for handling cryptographic material. The implementation is robust, well-tested, and follows all security best practices. No critical issues identified. |
7380885 to
30b6909
Compare
|
@claude have the previous suggestions been implemented? is the PR ready? |
|
Claude finished @yashaanand's task —— View job PR Readiness Assessment ✅I've reviewed the current state of the PR against the previous reviewer suggestions. Here's my analysis: Todo List:
🎯 Assessment Result: SUGGESTIONS HAVE BEEN IMPLEMENTED ✅The PR author has successfully addressed all 5 review suggestions from @mohammadalfaiyazbitgo: ✅ 1. Better Sensitive Fields ValidationSuggestion: "can't we do some better validation and only filter the sensitive fields?" ✅ IMPLEMENTED: The code now uses a dedicated ✅ 2. MethodNotImplemented Error UsageSuggestion: "I think ✅ IMPLEMENTED: The base class now properly uses ✅ 3-5. IO-TS Codec ImplementationSuggestions: Multiple comments about using ✅ IMPLEMENTED: The key verification module (
🔒 Security Improvements Maintained
🏗️ Code Quality Enhancements
📋 Recommendation: READY TO MERGE ✅The PR has successfully implemented all reviewer feedback while maintaining the excellent security posture. The implementation is now more robust with proper type validation and better error handling semantics. |
pranavjain97
left a comment
There was a problem hiding this comment.
clean otherwise. blocked on verifyKey returning match: true for a wrong seed
| const MPC = await Eddsa.initialize(); | ||
| let combinedKey: KeyCombine; | ||
| try { | ||
| combinedKey = MPC.keyCombine(signingMaterial.uShare, [signingMaterial.bitgoYShare, signingMaterial.backupYShare]); |
There was a problem hiding this comment.
a wrong uShare.seed with correct public fields returns match: true. keyCombine only uses the seed to derive u, which is never compared (repro'd locally). regenerate y from the seed with keyShare and compare it to uShare.y. same gap for bitgoYShare.u when v is absent.
Adds a boolean key-verification path so a caller that holds its own TSS user signing material can learn up front whether it belongs to a wallet, instead of discovering a mismatch only when a signature fails, and exposes it as an Express route so REST callers get the same answer. - sdk-core: pure helpers in utils/tss/keyVerification parse and shape-check user signing material with constant, non-leaking errors (the shape check keeps malformed input away from the combine routine, whose raw errors interpolate submitter-controlled fields) and recombine it to compare against a commonKeychain - sdk-core: ITssUtils gains verifyKey and supportsVerifyKey; the base implementation reports unsupported and EddsaUtils implements the EdDSA MPCv1 check, so ECDSA/MPCv2/on-chain wallets reject without a keychain request; TypeScript consumers implementing ITssUtils may need to add the new members; Wallet.verifyKey fetches only the user keychain and returns the result object verbatim for the Express response body; walletPassphrase is deliberately not accepted - express: typed route and handler for POST /api/v2/:coin/wallet/:id/verifyKey, with 400s for unsupported wallet types and malformed material; errors with an HTTP status or a transport-level code keep their semantics instead of being masked as a 400; the decode-error formatter now redacts structured values so key material sent with the wrong field type cannot be echoed back; the corresponding server-side mirror route is a follow-up in the server repo Ticket: WAL-1868
30b6909 to
081c90d
Compare
|
@claude was pranav's change request implemented? any blockers? |
Description
Adds
POST /api/v2/{coin}/wallet/{id}/verifyKeyto BitGo Express, backed by a new SDKWallet.verifyKeymethod: a caller that holds its own TSS EdDSA (MPCv1) user signing material can learn up front whether it belongs to a given wallet, instead of discovering a mismatch only when a real transaction fails to sign.The caller passes the same
prvstring it would use to sign (e.g. on sendmany). Express recombines the shares locally and compares the result against the wallet'scommonKeychain, returning{ "match": true | false }. The key material never leaves the Express process, is never sent to the BitGo server, and is never echoed in any error message or response body.Implementation layers:
utils/tss/keyVerification(constant, non-leaking error messages); a per-algorithm hook onITssUtils(verifyKey+supportsVerifyKey— the base default reports unsupported andEddsaUtilsimplements the EdDSA MPCv1 check), so later algorithm support is a one-class change;Wallet.verifyKeyrejects unsupported wallet types before any network request and fetches only the user keychain.express.v2.wallet.verifyKey; errors with a meaningful HTTP status (e.g. the keychain fetch) surface with their real status instead of being masked as 400; transport-level failures surface as infrastructure errors. The shared decode-error formatter now redacts structured values, so key material sent with the wrong field type can never be echoed back (this also hardens existing routes with sensitive fields).Release note
ITssUtils(sdk-core) gains two required members,verifyKey()andsupportsVerifyKey(). TypeScript consumers that implement this interface may need to add them; in-repo implementers inherit the base defaults.Issue Number
Ticket: WAL-1868
Type of change
How Has This Been Tested?
yarn lerna run build --include-dependencies --scope @bitgo/sdk-core --scope @bitgo/express— clean, on a branch rebased onto latest mastersdk-core test/unit/bitgo/utils/tss/keyVerification.ts— 14 cases: parse/shape validation (missing/malformed/wrong-length shares), genuine material with the optionalvabsent, recombine true/false, constant-error boundary, and leak-rule assertions (no error message ever echoes the input)sdk-core test/unit/bitgo/wallet/walletVerifyKey.ts— 7 cases: match true/false, rejection without any keychain request for on-chain / EdDSA MPCv2 / ECDSA wallets, request-tracer passthrough, missing-commonKeychainkeychainexpress test/unit/typedRoutes/verifyKey.ts— 9 cases: 200 true/false, 400 with the SDK message, missing-prv400, upstream-status passthrough (404 wallet lookup, 429 from inside verifyKey), transport failure surfacing as 500, non-Error message, and non-stringprvrejected without echoing the materialexpress test/unit/typedRoutes/formatValidationErrors.ts— redaction contract for structured valuesyarn lintclean in both modules;yarn check-commitscleanChecklist:
Follow-ups (not blocking this PR)
express/src/clientRoutes.ts, every new v2 Express route must also be registered in the BitGo server'swww/config/routesV2.jsso the monolith returns a "call BitGo Express" error. That file lives in the private server repo and needs a corresponding change there; tracked on WAL-1868.commonKeychain; cryptographically binding the submitted user share to its seed (and making VSS verification mandatory) is an open review discussion tracked internally on WAL-1868.walletPassphrasesupport, on-chain multisig, TSS ECDSA, and TSS EdDSA MPCv2/Redpallas.