@bsv/sdk 1.6.8 → 1.6.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +9 -4
  2. package/dist/cjs/package.json +7 -5
  3. package/dist/cjs/src/wallet/substrates/HTTPWalletJSON.js +11 -3
  4. package/dist/cjs/src/wallet/substrates/HTTPWalletJSON.js.map +1 -1
  5. package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js +1 -1
  6. package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js.map +1 -1
  7. package/dist/cjs/src/wallet/substrates/utils/toOriginHeader.js +21 -0
  8. package/dist/cjs/src/wallet/substrates/utils/toOriginHeader.js.map +1 -0
  9. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  10. package/dist/esm/src/wallet/substrates/HTTPWalletJSON.js +9 -1
  11. package/dist/esm/src/wallet/substrates/HTTPWalletJSON.js.map +1 -1
  12. package/dist/esm/src/wallet/substrates/WalletWireProcessor.js +1 -1
  13. package/dist/esm/src/wallet/substrates/WalletWireProcessor.js.map +1 -1
  14. package/dist/esm/src/wallet/substrates/utils/toOriginHeader.js +17 -0
  15. package/dist/esm/src/wallet/substrates/utils/toOriginHeader.js.map +1 -0
  16. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  17. package/dist/types/src/wallet/substrates/HTTPWalletJSON.d.ts.map +1 -1
  18. package/dist/types/src/wallet/substrates/utils/toOriginHeader.d.ts +2 -0
  19. package/dist/types/src/wallet/substrates/utils/toOriginHeader.d.ts.map +1 -0
  20. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  21. package/dist/umd/bundle.js +1 -1
  22. package/docs/concepts/beef.md +84 -0
  23. package/docs/concepts/chain-tracking.md +122 -0
  24. package/docs/concepts/decentralized-identity.md +184 -0
  25. package/docs/concepts/fees.md +217 -0
  26. package/docs/concepts/identity-certificates.md +255 -0
  27. package/docs/concepts/index.md +62 -0
  28. package/docs/concepts/key-management.md +176 -0
  29. package/docs/concepts/script-templates.md +163 -0
  30. package/docs/concepts/sdk-philosophy.md +72 -0
  31. package/docs/concepts/signatures.md +179 -0
  32. package/docs/concepts/spv-verification.md +106 -0
  33. package/docs/concepts/transaction-encoding.md +148 -0
  34. package/docs/concepts/transaction-structure.md +63 -0
  35. package/docs/concepts/trust-model.md +123 -0
  36. package/docs/concepts/verification.md +219 -0
  37. package/docs/concepts/wallet-integration.md +95 -0
  38. package/docs/guides/direct-transaction-creation.md +137 -0
  39. package/docs/guides/http-client-configuration.md +414 -0
  40. package/docs/guides/index.md +30 -0
  41. package/docs/guides/transaction-signing-methods.md +268 -0
  42. package/docs/index.md +74 -0
  43. package/docs/reference/arc-config.md +698 -0
  44. package/docs/reference/brc-100.md +33 -0
  45. package/docs/reference/configuration.md +829 -0
  46. package/docs/reference/debugging.md +700 -0
  47. package/docs/reference/errors.md +547 -0
  48. package/docs/reference/index.md +98 -0
  49. package/docs/reference/network-config.md +914 -0
  50. package/docs/reference/op-codes.md +306 -0
  51. package/docs/reference/transaction-signatures.md +94 -0
  52. package/docs/{wallet.md → reference/wallet.md} +9 -0
  53. package/docs/requirements.txt +3 -0
  54. package/docs/tutorials/advanced-transaction.md +575 -0
  55. package/docs/tutorials/aes-encryption.md +947 -0
  56. package/docs/tutorials/authfetch-tutorial.md +957 -0
  57. package/docs/tutorials/ecdh-key-exchange.md +547 -0
  58. package/docs/tutorials/elliptic-curve-fundamentals.md +603 -0
  59. package/docs/tutorials/error-handling.md +1215 -0
  60. package/docs/tutorials/first-transaction-low-level.md +204 -0
  61. package/docs/tutorials/first-transaction.md +278 -0
  62. package/docs/tutorials/hashes-and-hmacs.md +814 -0
  63. package/docs/tutorials/identity-management.md +702 -0
  64. package/docs/tutorials/index.md +182 -0
  65. package/docs/tutorials/key-management.md +536 -0
  66. package/docs/tutorials/protowallet-development.md +716 -0
  67. package/docs/tutorials/script-construction.md +690 -0
  68. package/docs/tutorials/spv-merkle-proofs.md +682 -0
  69. package/docs/tutorials/testnet-transactions-low-level.md +352 -0
  70. package/docs/tutorials/transaction-broadcasting.md +535 -0
  71. package/docs/tutorials/transaction-types.md +419 -0
  72. package/docs/tutorials/type-42.md +582 -0
  73. package/docs/tutorials/uhrp-storage.md +579 -0
  74. package/package.json +7 -5
  75. package/src/transaction/__tests/Transaction.test.ts +1 -1
  76. package/src/wallet/substrates/HTTPWalletJSON.ts +11 -1
  77. package/src/wallet/substrates/WalletWireProcessor.ts +1 -1
  78. package/src/wallet/substrates/__tests/toOriginHeader.test.ts +34 -0
  79. package/src/wallet/substrates/utils/toOriginHeader.ts +15 -0
  80. package/docs/README.md +0 -21
  81. /package/docs/{auth.md → reference/auth.md} +0 -0
  82. /package/docs/{compat.md → reference/compat.md} +0 -0
  83. /package/docs/{identity.md → reference/identity.md} +0 -0
  84. /package/docs/{kvstore.md → reference/kvstore.md} +0 -0
  85. /package/docs/{messages.md → reference/messages.md} +0 -0
  86. /package/docs/{overlay-tools.md → reference/overlay-tools.md} +0 -0
  87. /package/docs/{primitives.md → reference/primitives.md} +0 -0
  88. /package/docs/{registry.md → reference/registry.md} +0 -0
  89. /package/docs/{script.md → reference/script.md} +0 -0
  90. /package/docs/{storage.md → reference/storage.md} +0 -0
  91. /package/docs/{totp.md → reference/totp.md} +0 -0
  92. /package/docs/{transaction.md → reference/transaction.md} +0 -0
@@ -0,0 +1,547 @@
1
+ # ECDH Key Exchange
2
+
3
+ **Duration**: 75 minutes
4
+ **Prerequisites**: Basic TypeScript knowledge, [Elliptic Curve Fundamentals](./elliptic-curve-fundamentals.md) tutorial completed
5
+
6
+ ## Learning Goals
7
+ - Understand Elliptic Curve Diffie-Hellman (ECDH) key exchange principles
8
+ - Implement secure key exchange using the BSV TypeScript SDK
9
+ - Create shared secrets for encrypted communication
10
+ - Apply ECDH in practical Bitcoin applications
11
+ - Understand security considerations and best practices
12
+
13
+ ## Introduction to ECDH
14
+
15
+ Elliptic Curve Diffie-Hellman (ECDH) is a key agreement protocol that allows two parties to establish a shared secret over an unsecured communication channel. Unlike traditional encryption where you need to share a secret key beforehand, ECDH allows two parties who have never met to create a shared secret that only they know.
16
+
17
+ The mathematical foundation of ECDH relies on the commutative property of elliptic curve point multiplication:
18
+ - Alice computes: `(Alice's private key) × (Bob's public key)`
19
+ - Bob computes: `(Bob's private key) × (Alice's public key)`
20
+ - Both arrive at the same shared secret point
21
+
22
+ ## Setting Up Your Environment
23
+
24
+ ```typescript
25
+ import { PrivateKey, PublicKey, Point, BigNumber } from '@bsv/sdk'
26
+ ```
27
+
28
+ ## Basic ECDH Key Exchange
29
+
30
+ ### Step 1: Key Generation
31
+
32
+ Let's start by generating key pairs for Alice and Bob:
33
+
34
+ ```typescript
35
+ function generateKeyPairs() {
36
+ console.log('=== Generating Key Pairs ===')
37
+
38
+ // Generate Alice's key pair
39
+ const alicePrivKey = PrivateKey.fromRandom()
40
+ const alicePubKey = alicePrivKey.toPublicKey()
41
+
42
+ // Generate Bob's key pair
43
+ const bobPrivKey = PrivateKey.fromRandom()
44
+ const bobPubKey = bobPrivKey.toPublicKey()
45
+
46
+ console.log('Alice private key:', alicePrivKey.toWif())
47
+ console.log('Alice public key:', alicePubKey.toString())
48
+ console.log('Bob private key:', bobPrivKey.toWif())
49
+ console.log('Bob public key:', bobPubKey.toString())
50
+
51
+ return { alicePrivKey, alicePubKey, bobPrivKey, bobPubKey }
52
+ }
53
+ ```
54
+
55
+ ### Step 2: Deriving Shared Secrets
56
+
57
+ Now both parties can derive the same shared secret:
58
+
59
+ ```typescript
60
+ function performECDH(alicePrivKey: PrivateKey, alicePubKey: PublicKey,
61
+ bobPrivKey: PrivateKey, bobPubKey: PublicKey) {
62
+ console.log('\n=== ECDH Key Exchange ===')
63
+
64
+ // Alice creates a shared secret using Bob's public key and her private key
65
+ const aliceSharedSecret = alicePrivKey.deriveSharedSecret(bobPubKey)
66
+
67
+ // Bob creates the same shared secret using Alice's public key and his private key
68
+ const bobSharedSecret = bobPrivKey.deriveSharedSecret(alicePubKey)
69
+
70
+ // Verify they're identical
71
+ const aliceSecretHex = aliceSharedSecret.getX().toHex()
72
+ const bobSecretHex = bobSharedSecret.getX().toHex()
73
+
74
+ console.log('Alice\'s shared secret (x-coordinate):', aliceSecretHex)
75
+ console.log('Bob\'s shared secret (x-coordinate):', bobSecretHex)
76
+ console.log('Secrets match:', aliceSecretHex === bobSecretHex)
77
+
78
+ return aliceSharedSecret
79
+ }
80
+ ```
81
+
82
+ ### Step 3: Complete Example
83
+
84
+ ```typescript
85
+ function basicECDHExample() {
86
+ try {
87
+ // Generate key pairs
88
+ const { alicePrivKey, alicePubKey, bobPrivKey, bobPubKey } = generateKeyPairs()
89
+
90
+ // Perform ECDH
91
+ const sharedSecret = performECDH(alicePrivKey, alicePubKey, bobPrivKey, bobPubKey)
92
+
93
+ // The shared secret is a point on the curve
94
+ console.log('\nShared secret point:')
95
+ console.log('X:', sharedSecret.getX().toHex())
96
+ console.log('Y:', sharedSecret.getY().toHex())
97
+
98
+ } catch (error) {
99
+ console.error('ECDH Error:', error.message)
100
+ }
101
+ }
102
+
103
+ // Run the example
104
+ basicECDHExample()
105
+ ```
106
+
107
+ ## Security Validation
108
+
109
+ The SDK includes built-in security checks to prevent twist attacks:
110
+
111
+ ```typescript
112
+ function demonstrateSecurityValidation() {
113
+ console.log('\n=== Security Validation ===')
114
+
115
+ const validPrivKey = PrivateKey.fromRandom()
116
+
117
+ // This will work - valid public key
118
+ const validPubKey = PrivateKey.fromRandom().toPublicKey()
119
+ const validSecret = validPrivKey.deriveSharedSecret(validPubKey)
120
+ console.log('Valid ECDH succeeded')
121
+
122
+ // This will fail - invalid point (not on curve)
123
+ try {
124
+ const invalidPubKey = new PublicKey(new BigNumber(14), new BigNumber(16))
125
+ validPrivKey.deriveSharedSecret(invalidPubKey)
126
+ } catch (error) {
127
+ console.log('Security check prevented invalid key usage:', error.message)
128
+ }
129
+ }
130
+
131
+ demonstrateSecurityValidation()
132
+ ```
133
+
134
+ ## Practical Applications
135
+
136
+ ### Secure Message Exchange
137
+
138
+ Here's how to use ECDH for encrypting messages:
139
+
140
+ ```typescript
141
+ import { createHash, createCipheriv, createDecipheriv, randomBytes } from 'crypto'
142
+
143
+ function deriveEncryptionKey(sharedSecret: Point): Buffer {
144
+ // Use the x-coordinate of the shared secret as key material
145
+ const keyMaterial = sharedSecret.getX().toArray('be', 32)
146
+
147
+ // Hash to create a proper encryption key
148
+ return createHash('sha256').update(Buffer.from(keyMaterial)).digest()
149
+ }
150
+
151
+ function encryptMessage(message: string, sharedSecret: Point): {
152
+ encrypted: string,
153
+ iv: string
154
+ } {
155
+ const key = deriveEncryptionKey(sharedSecret)
156
+ const iv = randomBytes(16)
157
+ const cipher = createCipheriv('aes-256-cbc', key, iv)
158
+
159
+ let encrypted = cipher.update(message, 'utf8', 'hex')
160
+ encrypted += cipher.final('hex')
161
+
162
+ return {
163
+ encrypted,
164
+ iv: iv.toString('hex')
165
+ }
166
+ }
167
+
168
+ function decryptMessage(encryptedData: { encrypted: string, iv: string },
169
+ sharedSecret: Point): string {
170
+ const key = deriveEncryptionKey(sharedSecret)
171
+ const decipher = createDecipheriv('aes-256-cbc', key, Buffer.from(encryptedData.iv, 'hex'))
172
+
173
+ let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8')
174
+ decrypted += decipher.final('utf8')
175
+
176
+ return decrypted
177
+ }
178
+
179
+ function secureMessagingExample() {
180
+ console.log('\n=== Secure Messaging with ECDH ===')
181
+
182
+ // Setup key pairs
183
+ const alicePrivKey = PrivateKey.fromRandom()
184
+ const bobPrivKey = PrivateKey.fromRandom()
185
+ const alicePubKey = alicePrivKey.toPublicKey()
186
+ const bobPubKey = bobPrivKey.toPublicKey()
187
+
188
+ // Derive shared secret
189
+ const sharedSecret = alicePrivKey.deriveSharedSecret(bobPubKey)
190
+
191
+ // Alice encrypts a message
192
+ const message = "Hello Bob! This is a secret message."
193
+ const encryptedData = encryptMessage(message, sharedSecret)
194
+
195
+ console.log('Original message:', message)
196
+ console.log('Encrypted:', encryptedData.encrypted)
197
+
198
+ // Bob decrypts the message using the same shared secret
199
+ const bobSharedSecret = bobPrivKey.deriveSharedSecret(alicePubKey)
200
+ const decryptedMessage = decryptMessage(encryptedData, bobSharedSecret)
201
+
202
+ console.log('Decrypted message:', decryptedMessage)
203
+ console.log('Messages match:', message === decryptedMessage)
204
+ }
205
+
206
+ secureMessagingExample()
207
+ ```
208
+
209
+ ### Key Exchange with Authentication
210
+
211
+ Combine ECDH with digital signatures for authenticated key exchange:
212
+
213
+ ```typescript
214
+ function authenticatedKeyExchange() {
215
+ console.log('\n=== Authenticated Key Exchange ===')
216
+
217
+ // Generate long-term identity keys
218
+ const aliceIdentityPrivKey = PrivateKey.fromRandom()
219
+ const bobIdentityPrivKey = PrivateKey.fromRandom()
220
+ const aliceIdentityPubKey = aliceIdentityPrivKey.toPublicKey()
221
+ const bobIdentityPubKey = bobIdentityPrivKey.toPublicKey()
222
+
223
+ // Generate ephemeral keys for this session
224
+ const aliceEphemeralPrivKey = PrivateKey.fromRandom()
225
+ const bobEphemeralPrivKey = PrivateKey.fromRandom()
226
+ const aliceEphemeralPubKey = aliceEphemeralPrivKey.toPublicKey()
227
+ const bobEphemeralPubKey = bobEphemeralPrivKey.toPublicKey()
228
+
229
+ // Alice signs her ephemeral public key with her identity key
230
+ const aliceSignature = aliceIdentityPrivKey.sign(
231
+ Buffer.from(aliceEphemeralPubKey.toString(), 'utf8')
232
+ )
233
+
234
+ // Bob signs his ephemeral public key with his identity key
235
+ const bobSignature = bobIdentityPrivKey.sign(
236
+ Buffer.from(bobEphemeralPubKey.toString(), 'utf8')
237
+ )
238
+
239
+ // Verify signatures (in practice, you'd exchange these over the network)
240
+ const aliceSignatureValid = aliceIdentityPubKey.verify(
241
+ Buffer.from(aliceEphemeralPubKey.toString(), 'utf8'),
242
+ aliceSignature
243
+ )
244
+
245
+ const bobSignatureValid = bobIdentityPubKey.verify(
246
+ Buffer.from(bobEphemeralPubKey.toString(), 'utf8'),
247
+ bobSignature
248
+ )
249
+
250
+ console.log('Alice signature valid:', aliceSignatureValid)
251
+ console.log('Bob signature valid:', bobSignatureValid)
252
+
253
+ if (aliceSignatureValid && bobSignatureValid) {
254
+ // Perform ECDH with ephemeral keys
255
+ const sharedSecret = aliceEphemeralPrivKey.deriveSharedSecret(bobEphemeralPubKey)
256
+ console.log('Authenticated shared secret established')
257
+ console.log('Secret (x-coordinate):', sharedSecret.getX().toHex().substring(0, 16) + '...')
258
+ }
259
+ }
260
+
261
+ authenticatedKeyExchange()
262
+ ```
263
+
264
+ ## Advanced ECDH Patterns
265
+
266
+ ### Multi-Party Key Agreement
267
+
268
+ Extend ECDH to multiple parties:
269
+
270
+ ```typescript
271
+ function multiPartyKeyAgreement() {
272
+ console.log('\n=== Multi-Party Key Agreement ===')
273
+
274
+ // Generate keys for three parties
275
+ const parties = ['Alice', 'Bob', 'Charlie'].map(name => ({
276
+ name,
277
+ privKey: PrivateKey.fromRandom(),
278
+ pubKey: null as PublicKey | null
279
+ }))
280
+
281
+ // Generate public keys
282
+ parties.forEach(party => {
283
+ party.pubKey = party.privKey.toPublicKey()
284
+ })
285
+
286
+ // Each party computes pairwise shared secrets
287
+ const sharedSecrets = new Map<string, Point>()
288
+
289
+ for (let i = 0; i < parties.length; i++) {
290
+ for (let j = i + 1; j < parties.length; j++) {
291
+ const party1 = parties[i]
292
+ const party2 = parties[j]
293
+
294
+ const secret = party1.privKey.deriveSharedSecret(party2.pubKey!)
295
+ const pairKey = `${party1.name}-${party2.name}`
296
+ sharedSecrets.set(pairKey, secret)
297
+
298
+ console.log(`${pairKey} shared secret:`, secret.getX().toHex().substring(0, 16) + '...')
299
+ }
300
+ }
301
+
302
+ return sharedSecrets
303
+ }
304
+
305
+ multiPartyKeyAgreement()
306
+ ```
307
+
308
+ ### Key Derivation Functions
309
+
310
+ Use proper key derivation for different purposes:
311
+
312
+ ```typescript
313
+ function keyDerivationExample() {
314
+ console.log('\n=== Key Derivation Functions ===')
315
+
316
+ const alicePrivKey = PrivateKey.fromRandom()
317
+ const bobPrivKey = PrivateKey.fromRandom()
318
+ const sharedSecret = alicePrivKey.deriveSharedSecret(bobPrivKey.toPublicKey())
319
+
320
+ // Derive different keys for different purposes
321
+ function deriveKey(purpose: string, length: number = 32): Buffer {
322
+ const keyMaterial = sharedSecret.getX().toArray('be', 32)
323
+ const hash = createHash('sha256')
324
+ hash.update(Buffer.from(keyMaterial))
325
+ hash.update(Buffer.from(purpose, 'utf8'))
326
+ return hash.digest().slice(0, length)
327
+ }
328
+
329
+ const encryptionKey = deriveKey('encryption', 32)
330
+ const macKey = deriveKey('authentication', 32)
331
+ const ivKey = deriveKey('iv', 16)
332
+
333
+ console.log('Encryption key:', encryptionKey.toString('hex'))
334
+ console.log('MAC key:', macKey.toString('hex'))
335
+ console.log('IV key:', ivKey.toString('hex'))
336
+ }
337
+
338
+ keyDerivationExample()
339
+ ```
340
+
341
+ ## Security Considerations
342
+
343
+ ### Best Practices
344
+
345
+ 1. **Key Validation**: Always validate public keys before use
346
+ 2. **Ephemeral Keys**: Use ephemeral keys for forward secrecy
347
+ 3. **Authentication**: Combine with signatures to prevent man-in-the-middle attacks
348
+ 4. **Key Derivation**: Use proper KDFs to derive encryption keys from shared secrets
349
+
350
+ ### Common Pitfalls
351
+
352
+ ```typescript
353
+ function securityPitfalls() {
354
+ console.log('\n=== Security Pitfalls to Avoid ===')
355
+
356
+ // ❌ DON'T: Use shared secret directly as encryption key
357
+ console.log('❌ Never use the shared secret point directly for encryption')
358
+
359
+ // ✅ DO: Use proper key derivation
360
+ console.log('✅ Always use key derivation functions')
361
+
362
+ // ❌ DON'T: Reuse ephemeral keys
363
+ console.log('❌ Never reuse ephemeral keys across sessions')
364
+
365
+ // ✅ DO: Generate fresh ephemeral keys for each session
366
+ console.log('✅ Generate fresh keys for each exchange')
367
+
368
+ // ❌ DON'T: Skip public key validation
369
+ console.log('❌ Never skip public key validation')
370
+
371
+ // ✅ DO: Always validate received public keys
372
+ console.log('✅ SDK automatically validates keys in deriveSharedSecret()')
373
+ }
374
+
375
+ securityPitfalls()
376
+ ```
377
+
378
+ ## Performance Considerations
379
+
380
+ ### Optimizing ECDH Operations
381
+
382
+ ```typescript
383
+ function performanceExample() {
384
+ console.log('\n=== Performance Optimization ===')
385
+
386
+ const iterations = 1000
387
+
388
+ // Pre-generate keys
389
+ const privateKeys = Array.from({ length: iterations }, () => PrivateKey.fromRandom())
390
+ const publicKeys = privateKeys.map(pk => pk.toPublicKey())
391
+
392
+ // Measure ECDH performance
393
+ const startTime = Date.now()
394
+
395
+ for (let i = 0; i < iterations; i++) {
396
+ const sharedSecret = privateKeys[i].deriveSharedSecret(publicKeys[(i + 1) % iterations])
397
+ // In practice, you'd process the shared secret here
398
+ }
399
+
400
+ const endTime = Date.now()
401
+ const avgTime = (endTime - startTime) / iterations
402
+
403
+ console.log(`Performed ${iterations} ECDH operations`)
404
+ console.log(`Average time per operation: ${avgTime.toFixed(2)}ms`)
405
+ }
406
+
407
+ performanceExample()
408
+ ```
409
+
410
+ ## Error Handling
411
+
412
+ ### Robust ECDH Implementation
413
+
414
+ ```typescript
415
+ function robustECDH(privateKey: PrivateKey, publicKey: PublicKey): Point | null {
416
+ try {
417
+ // Validate inputs
418
+ if (!privateKey || !publicKey) {
419
+ throw new Error('Invalid key parameters')
420
+ }
421
+
422
+ // Perform ECDH with built-in validation
423
+ const sharedSecret = privateKey.deriveSharedSecret(publicKey)
424
+
425
+ // Additional validation if needed
426
+ if (sharedSecret.getX().isZero() || sharedSecret.getY().isZero()) {
427
+ throw new Error('Invalid shared secret generated')
428
+ }
429
+
430
+ return sharedSecret
431
+
432
+ } catch (error) {
433
+ console.error('ECDH operation failed:', error.message)
434
+ return null
435
+ }
436
+ }
437
+
438
+ function errorHandlingExample() {
439
+ console.log('\n=== Error Handling ===')
440
+
441
+ const validPrivKey = PrivateKey.fromRandom()
442
+ const validPubKey = PrivateKey.fromRandom().toPublicKey()
443
+
444
+ // Test with valid keys
445
+ const result1 = robustECDH(validPrivKey, validPubKey)
446
+ console.log('Valid ECDH result:', result1 ? 'Success' : 'Failed')
447
+
448
+ // Test with invalid key (will be caught by SDK validation)
449
+ try {
450
+ const invalidPubKey = new PublicKey(new BigNumber(1), new BigNumber(1))
451
+ const result2 = robustECDH(validPrivKey, invalidPubKey)
452
+ console.log('Invalid ECDH result:', result2 ? 'Success' : 'Failed')
453
+ } catch (error) {
454
+ console.log('Caught invalid key error:', error.message)
455
+ }
456
+ }
457
+
458
+ errorHandlingExample()
459
+ ```
460
+
461
+ ## Testing Your ECDH Implementation
462
+
463
+ ### Comprehensive Test Suite
464
+
465
+ ```typescript
466
+ function testECDHImplementation() {
467
+ console.log('\n=== ECDH Test Suite ===')
468
+
469
+ let passed = 0
470
+ let total = 0
471
+
472
+ function test(name: string, testFn: () => boolean) {
473
+ total++
474
+ try {
475
+ if (testFn()) {
476
+ console.log(`✅ ${name}`)
477
+ passed++
478
+ } else {
479
+ console.log(`❌ ${name}`)
480
+ }
481
+ } catch (error) {
482
+ console.log(`❌ ${name}: ${error.message}`)
483
+ }
484
+ }
485
+
486
+ // Test 1: Basic ECDH symmetry
487
+ test('Basic ECDH symmetry', () => {
488
+ const privA = PrivateKey.fromRandom()
489
+ const privB = PrivateKey.fromRandom()
490
+ const secretA = privA.deriveSharedSecret(privB.toPublicKey())
491
+ const secretB = privB.deriveSharedSecret(privA.toPublicKey())
492
+ return secretA.getX().toHex() === secretB.getX().toHex()
493
+ })
494
+
495
+ // Test 2: Different key formats
496
+ test('Different key formats', () => {
497
+ const privA = PrivateKey.fromRandom()
498
+ const privB = PrivateKey.fromRandom()
499
+ const pubB = PublicKey.fromString(privB.toPublicKey().toDER('hex') as string)
500
+ const secret1 = privA.deriveSharedSecret(privB.toPublicKey())
501
+ const secret2 = privA.deriveSharedSecret(pubB)
502
+ return secret1.getX().toHex() === secret2.getX().toHex()
503
+ })
504
+
505
+ // Test 3: Invalid key rejection
506
+ test('Invalid key rejection', () => {
507
+ const privKey = PrivateKey.fromRandom()
508
+ const invalidPubKey = new PublicKey(new BigNumber(14), new BigNumber(16))
509
+ try {
510
+ privKey.deriveSharedSecret(invalidPubKey)
511
+ return false // Should have thrown
512
+ } catch (error) {
513
+ return error.message.includes('not valid for ECDH')
514
+ }
515
+ })
516
+
517
+ console.log(`\nTest Results: ${passed}/${total} passed`)
518
+ return passed === total
519
+ }
520
+
521
+ testECDHImplementation()
522
+ ```
523
+
524
+ ## Conclusion
525
+
526
+ In this tutorial, you've learned how to implement ECDH key exchange using the BSV TypeScript SDK. You now understand:
527
+
528
+ - The mathematical principles behind ECDH
529
+ - How to generate key pairs and derive shared secrets
530
+ - Security considerations and validation
531
+ - Practical applications including secure messaging
532
+ - Advanced patterns like authenticated key exchange
533
+ - Performance optimization and error handling
534
+
535
+ The BSV TypeScript SDK provides robust ECDH implementation with built-in security validations, making it safe and easy to implement secure key exchange protocols.
536
+
537
+ ## Next Steps
538
+
539
+ - **[Script Construction](./script-construction.md)**: Learn to create custom Bitcoin scripts
540
+ - **[Advanced Transaction Construction](./advanced-transaction.md)**: Build complex transactions
541
+ - **[SPV and Merkle Proofs](./spv-merkle-proofs.md)**: Implement lightweight verification
542
+
543
+ ## Further Reading
544
+
545
+ - [RFC 3526 - Diffie-Hellman Key Agreement](https://tools.ietf.org/html/rfc3526)
546
+ - [SEC 1: Elliptic Curve Cryptography](https://www.secg.org/sec1-v2.pdf)
547
+ - [BSV TypeScript SDK Documentation](../reference/primitives.md)