|
1 | 1 | # NFC Chip Integration Guide |
2 | 2 |
|
3 | | -Complete guide for using Infineon SECORA Blockchain NFC chips with the Stellar dapp and the XRPL POC to mint/claim/transfer NFTs or sign XRPL testnet transactions from a physical chip. |
| 3 | +Complete guide for using Infineon SECORA Blockchain NFC chips with the Stellar dapp. Mint, claim, and transfer NFTs with hardware-secured signatures. |
4 | 4 |
|
5 | | -## Overview |
| 5 | +## Related repositories |
6 | 6 |
|
7 | | -This application integrates Infineon NFC chips for desktop crypto operations: |
| 7 | +| Repo | Radicle | Purpose | |
| 8 | +|------|---------|---------| |
| 9 | +| **chimpdao-nfc-bridge** | [z2CDTfv…](https://radicle.network/nodes/radicle.consulting-manao.com/rad%3Az2CDTfvUguLG3UboK46HyYxoxg1og) | Node.js PC/SC WebSocket bridge + `@chimpdao/nfc-client` | |
| 10 | +| **chimpdao-terminal** | [z4Y793T…](https://radicle.network/nodes/radicle.consulting-manao.com/rad%3Az4Y793TkQB4X4Uz4CRdEMUHxakZKt) | Merchant tap-to-pay (XRPL + Stellar UI) | |
| 11 | +| **chimpdao-contracts** | this repo | Soroban contracts + admin dapp | |
8 | 12 |
|
9 | | -- **Desktop**: USB NFC reader (uTrust 4701F) via a Node.js WebSocket server |
10 | | -- **Chains**: Stellar Soroban (SEP-53 contract auth) + XRPL testnet (single-sign chip demo) |
11 | | -- **Security**: Hardware-secured ECDSA signatures over secp256k1 |
| 13 | +```bash |
| 14 | +git clone https://radicle.consulting-manao.com/z2CDTfvUguLG3UboK46HyYxoxg1og.git chimpdao-nfc-bridge |
| 15 | +``` |
12 | 16 |
|
13 | 17 | ## Prerequisites |
14 | 18 |
|
15 | | -- **Hardware**: Infineon SECORA Blockchain NFC chip + uTrust 4701F reader (Desktop) |
16 | | -- **Software**: Node.js >= 22 for the NFC server; Bun for the dapp/XRPL script |
17 | | -- **Wallet**: Freighter or compatible Stellar wallet (Stellar only) |
| 19 | +- **Hardware**: Infineon SECORA chip + Identiv/uTrust USB reader |
| 20 | +- **Software**: Node.js ≥ 22 for the bridge; Bun for the dapp |
| 21 | +- **Wallet**: Freighter or compatible Stellar wallet |
18 | 22 |
|
19 | 23 | ## Running |
20 | 24 |
|
21 | 25 | ```bash |
22 | | -# Terminal 1: NFC Server (must run with Node, not Bun) |
23 | | -cd nfc-server |
24 | | -node index.js |
| 26 | +# Terminal 1: NFC bridge (Node only — not Bun) |
| 27 | +cd chimpdao-nfc-bridge |
| 28 | +npm install && npm start |
25 | 29 |
|
26 | | -# Terminal 2: Stellar dev server |
| 30 | +# Terminal 2: Stellar dapp |
27 | 31 | cd dapp |
28 | | -bun run dev |
| 32 | +bun install && bun run dev |
29 | 33 |
|
30 | | -# Or start everything together: |
| 34 | +# Or from dapp (bridge must be cloned as sibling): |
31 | 35 | bun run dev:with-nfc |
32 | 36 | ``` |
33 | 37 |
|
34 | | -### Chi//mp POS (XRPL tap-to-pay) |
35 | | - |
36 | | -Standalone POS UI at [`pos/`](pos/): amount → tap chip → chip-signed XRPL Payment. |
| 38 | +If the chip was already on the reader when the bridge started, **lift and retap**. |
37 | 39 |
|
38 | | -```bash |
39 | | -# Terminal 1: NFC server |
40 | | -cd nfc-server && node index.js |
| 40 | +## Architecture |
41 | 41 |
|
42 | | -# Terminal 2: POS |
43 | | -cd pos && bun install && bun run dev |
44 | | -# → http://localhost:5174 |
45 | 42 | ``` |
46 | | - |
47 | | -Wallet tab: create/fund merchant + fund chip (testnet faucet). Pay tab never auto-funds. |
48 | | - |
49 | | -### XRPL one-shot script |
50 | | - |
51 | | -```bash |
52 | | -cd dapp |
53 | | -bun run xrpl-nfc-sign |
| 43 | +Browser ← WebSocket → chimpdao-nfc-bridge ← nfc-pcsc → USB Reader ← NFC → Chip |
54 | 44 | ``` |
55 | 45 |
|
56 | | -(Script lives at `nfc-server/scripts/xrpl-nfc-sign.ts`.) |
57 | | - |
58 | | -## How It Works |
59 | | - |
60 | | -### Architecture |
| 46 | +Protocol: `status` | `read-pubkey` | `sign` | `read-ndef` | `write-ndef` | `generate-key` | `fetch-key` |
61 | 47 |
|
62 | | -``` |
63 | | -Browser ← WebSocket → NFC Server ← nfc-pcsc → USB Reader ← NFC → Chip |
64 | | - ↑ |
65 | | - └── XRPL script |
66 | | -``` |
67 | | - |
68 | | -The NFC server is a small `nfc-pcsc` bridge over WebSocket. It exposes APDU operations (`read-pubkey`, `sign`, `read-ndef`, `write-ndef`, `generate-key`, `fetch-key`) and is used by both the Stellar dapp and the XRPL POC. |
| 48 | +Full spec: [chimpdao-nfc-bridge/docs/PROTOCOL.md](https://radicle.consulting-manao.com/z2CDTfvUguLG3UboK46HyYxoxg1og.git) (clone the bridge repo). |
69 | 49 |
|
70 | 50 | ### Stellar flow |
71 | 51 |
|
72 | | -1. **Read chip**: get the 65-byte secp256k1 public key |
73 | | -2. **Fetch nonce**: current chip nonce for SEP-53 expiry |
74 | | -3. **Create message**: build SEP-53 auth message (`network_hash + contract_id + function_name + args + nonce`) |
75 | | -4. **Hash**: SHA-256 hash of the message |
76 | | -5. **Sign**: chip signs the 32-byte hash |
77 | | -6. **Detect recovery ID**: client-side (`@noble/secp256k1`) recovers the recovery ID from the signature |
78 | | -7. **Contract call**: send message + `r||s` signature + recovery ID to the Soroban contract |
79 | | -8. **Verify**: contract hashes the message and recovers the public key via `secp256k1_recover` |
80 | | - |
81 | | -### XRPL flow |
82 | | - |
83 | | -1. **Read chip**: get the 65-byte public key |
84 | | -2. **Compress**: 65-byte SEC1 → 33-byte compressed pubkey |
85 | | -3. **Derive address**: `encodeAccountID(RIPEMD160(SHA256(compressed)))` |
86 | | -4. **Fund chip**: faucet wallet sends testnet XRP to the chip address |
87 | | -5. **Build Payment**: chip address as sender, `SigningPubKey` set |
88 | | -6. **Hash**: `encodeForSigning` + SHA-512Half (first 32 bytes of SHA-512) |
89 | | -7. **Sign**: chip signs the 32-byte hash |
90 | | -8. **Re-DER**: raw 64-byte `r||s` → DER → `TxnSignature` |
91 | | -9. **Submit**: `encode(...)` + `submitAndWait` |
92 | | - |
93 | | -## Technical Details |
| 52 | +1. Read chip public key (65-byte SEC1) |
| 53 | +2. Fetch nonce for SEP-53 |
| 54 | +3. Build SEP-53 auth message |
| 55 | +4. Hash with SHA-256 |
| 56 | +5. Chip signs the 32-byte digest |
| 57 | +6. Client recovers recovery ID (`@noble/secp256k1`) |
| 58 | +7. Submit to Soroban contract with `r||s` + recovery ID |
94 | 59 |
|
95 | | -### Signature format |
96 | | - |
97 | | -- **From chip**: DER-encoded ECDSA signature |
98 | | -- **From server**: `r` (32 bytes) + `s` (32 bytes) as hex strings, low-S normalized |
99 | | -- **Stellar consumer**: client recomputes recovery ID; signature is `r||s` + recovery ID |
100 | | -- **XRPL consumer**: `r||s` is re-encoded into DER for `TxnSignature` |
101 | | - |
102 | | -### blocksec2go diagnostic commands (optional) |
103 | | - |
104 | | -These are only used for regenerating contract test signatures, not the server runtime: |
| 60 | +### Merchant terminal (XRPL) |
105 | 61 |
|
106 | 62 | ```bash |
107 | | -# Get card info |
108 | | -blocksec2go get_card_info |
| 63 | +git clone https://radicle.consulting-manao.com/z4Y793TkQB4X4Uz4CRdEMUHxakZKt.git chimpdao-terminal |
| 64 | +``` |
109 | 65 |
|
110 | | -# Get public key (key index 1) |
111 | | -blocksec2go get_key_info 1 |
| 66 | +## Signature format |
112 | 67 |
|
113 | | -# Sign 32-byte hash (key index 1) |
114 | | -blocksec2go generate_signature 1 <32-byte-hex> |
115 | | -``` |
| 68 | +- **From chip**: DER-encoded ECDSA |
| 69 | +- **From bridge**: `r` + `s` as 32-byte hex (low-S) |
| 70 | +- **Stellar dapp**: `formatSignatureForSoroban()` in `dapp/src/util/crypto.ts` |
116 | 71 |
|
117 | | -### Regenerating NFC test signatures |
| 72 | +## Regenerating NFC test signatures |
118 | 73 |
|
119 | | -To update the 5 test signatures and chip public keys in `contracts/nfc-nft` (e.g. after changing the message hash or rotating chips), follow the one-shot instructions in **[dapp/scripts/REGENERATE_NFC_TEST_SIGS.md](dapp/scripts/REGENERATE_NFC_TEST_SIGS.md)**. |
| 74 | +See [dapp/scripts/REGENERATE_NFC_TEST_SIGS.md](dapp/scripts/REGENERATE_NFC_TEST_SIGS.md). |
0 commit comments