Skip to content

Conversation

@Gaubee
Copy link
Contributor

@Gaubee Gaubee commented Jan 19, 2026

Summary

This PR implements two major features:

1. Crypto Box - Secure Token-Based Authorization

A "crypto black box" system that allows miniapps to perform cryptographic operations without exposing private keys.

Security features:

  • sessionSecret = SHA256(walletId + patternKey + miniappId + tokenId)
  • patternKey encrypted in Token payload (not stored in memory)
  • Ed25519 → X25519 key conversion for BFMetaSignUtil compatibility
  • Token validation from encrypted payload

New APIs:

  • bio_requestCryptoToken: Request crypto authorization with gesture password
  • bio_cryptoExecute: Execute asymmetricEncrypt/sign operations

New packages:

  • @biochain/dweb-compat: RWA Hub compatibility adapter

2. Code Improvements

  • Refactored ChainIcon to use chainConfigService directly (removed Context)
  • Fixed and updated tests for token-store and chain-icon
  • Added whitebook documentation for CryptoBox

3. TODO: Remote Miniapp Integration

Will add vite-plugin-remote-miniapps to support downloading and serving remote miniapps (like RWA Hub) with ETag-based caching.

Test Results

  • token-store.test.ts: 24/24 passed
  • chain-icon.test.tsx: 12/12 passed
  • wallet-handlers.test.ts: 11/11 passed
  • Typecheck: 14/14 passed

Gaubee added 16 commits January 19, 2026 19:32
…ystem

- Add Crypto Box service for miniapp crypto operations without exposing private keys
- Implement sessionSecret-based payload encryption (SHA256 derived key)
- Add dweb-compat package for RWA Hub integration
- Refactor ChainIcon to use chainConfigService directly (remove Context)
- Add CryptoAuthorizeJob sheet for gesture password authorization
- Update whitebook with CryptoBox security documentation
- Fix and update tests for token-store and chain-icon

Security features:
- patternKey encrypted in Token payload, not stored in memory
- sessionSecret = SHA256(walletId + patternKey + miniappId + tokenId)
- Ed25519 to X25519 key conversion for BFMetaSignUtil compatibility
- Token validation from encrypted payload (distrust plaintext copies)
Update mock to use correct import path @/services/chain-adapter/providers
instead of @/services/chain-adapter. All 11 tests now pass.
- Add fetchWithEtag utility for cached downloads to /tmp/fetch/{hash}.bin
- Add vite-plugin-remote-miniapps for downloading and serving remote miniapps
- Integrate remote miniapps into ecosystem.json generation
- Install jszip and sirv dependencies for zip extraction and static serving
- Change config from manifestUrl+zipUrl to single metadataUrl
- Parse relative URLs from metadata.json for manifest and zip
- Skip remote miniapps in miniappsPlugin (no vite.config.ts)
- Add RWA Hub remote miniapp config
- Add miniapps/rwa-hub/ to .gitignore
- Store _zipEtag in local manifest.json
- Compare remote zip ETag with local to detect content changes
- Auto-update when same version but different content
Security fixes:
- Fix cross-wallet token usage: Token now strictly uses walletId for keypair lookup
- Add ADDRESS_MISMATCH validation: bio_cryptoExecute validates address matches token
- Add error code 4105 for ADDRESS_MISMATCH

UI improvements:
- Add walletInfo prop to MiniappSheetHeader for left-right layout
- Update all miniapp authorization dialogs to show wallet name in header:
  - SigningConfirmJob
  - MiniappTransferConfirmJob
  - MiniappSignTransactionJob
  - MiniappDestroyConfirmJob
  - CryptoAuthorizeJob
- Add duration selector to CryptoAuthorizeJob (5min/30min/2hour/1day)

Test updates:
- Update token duration options from 15min/1hour to 30min/2hour
- Add ADDRESS_MISMATCH error code test
- Add CryptoExecuteParams address field test
- token-store.ts: prefix unused oldVersion param with underscore
- provider.ts: remove duplicate import of setCryptoAuthorizeDialog (already re-exported)
- WalletPickerJob.tsx: use chainConfigService.getName() instead of removed CHAIN_DISPLAY_NAMES
Security fix: Token response now includes the bound address so miniapp can:
1. Cache the address alongside tokenId/sessionSecret
2. Compare with current user-selected address
3. Request new Token when address changes

This prevents cross-address Token reuse vulnerability.
Security enhancement for cross-address Token reuse vulnerability:

1. New API: bio_getCryptoTokenInfo
   - Allows miniapp to query Token info (address, expiresAt, actions, valid)
   - Miniapp can check if cached Token matches current address before use

2. Enhanced responses:
   - RequestCryptoTokenResponse: returns bound address
   - CryptoExecuteResponse: returns bound address

3. New files/methods:
   - types.ts: GetCryptoTokenInfoParams, GetCryptoTokenInfoResponse
   - token-store.ts: getTokenInfo() method
   - handlers/crypto.ts: handleGetCryptoTokenInfo handler
   - provider.ts: register bio_getCryptoTokenInfo
   - ecosystem/types.ts: KNOWN_PERMISSIONS for crypto APIs

Usage for miniapp:
```javascript
// Check if cached Token is valid and matches current address
const info = await keyapp.getCryptoTokenInfo({ tokenId, sessionSecret })
if (!info.valid || info.address !== currentAddress) {
  // Request new Token
}
```
1. Add getCryptoTokenInfo function for Token validation
2. Update response types to include address field:
   - RequestCryptoTokenResponse.address
   - CryptoExecuteResponse.address
3. Fix rwaLogin to use address from asymmetricEncrypt response
   instead of account.address (ensures address matches Token)

This enables miniapps to:
- Query Token info before use
- Verify Token is bound to expected address
- Invalidate cache when address changes
TypeScript 5.9.3 has an internal error when processing complex type
inference in the i18n folder. Temporarily excluding it until fixed.

TODO: Generate i18n types to avoid this issue
- Sync TokenDuration with KeyApp: '5min' | '30min' | '2hour' | '1day'
- Change rwaLogin default duration from 5min to 1day
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants