@bsv/sdk 1.9.31 → 1.10.2
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.
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/auth/Peer.js +68 -48
- package/dist/cjs/src/auth/Peer.js.map +1 -1
- package/dist/cjs/src/identity/IdentityClient.js +124 -20
- package/dist/cjs/src/identity/IdentityClient.js.map +1 -1
- package/dist/cjs/src/primitives/BigNumber.js +28 -54
- package/dist/cjs/src/primitives/BigNumber.js.map +1 -1
- package/dist/cjs/src/primitives/ECDSA.js +36 -1
- package/dist/cjs/src/primitives/ECDSA.js.map +1 -1
- package/dist/cjs/src/primitives/ReductionContext.js +35 -46
- package/dist/cjs/src/primitives/ReductionContext.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/auth/Peer.js +68 -48
- package/dist/esm/src/auth/Peer.js.map +1 -1
- package/dist/esm/src/identity/IdentityClient.js +124 -20
- package/dist/esm/src/identity/IdentityClient.js.map +1 -1
- package/dist/esm/src/primitives/BigNumber.js +28 -54
- package/dist/esm/src/primitives/BigNumber.js.map +1 -1
- package/dist/esm/src/primitives/ECDSA.js +36 -1
- package/dist/esm/src/primitives/ECDSA.js.map +1 -1
- package/dist/esm/src/primitives/ReductionContext.js +35 -46
- package/dist/esm/src/primitives/ReductionContext.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/auth/Peer.d.ts.map +1 -1
- package/dist/types/src/auth/types.d.ts +2 -0
- package/dist/types/src/auth/types.d.ts.map +1 -1
- package/dist/types/src/identity/IdentityClient.d.ts +8 -0
- package/dist/types/src/identity/IdentityClient.d.ts.map +1 -1
- package/dist/types/src/primitives/BigNumber.d.ts +8 -0
- package/dist/types/src/primitives/BigNumber.d.ts.map +1 -1
- package/dist/types/src/primitives/ECDSA.d.ts +24 -0
- package/dist/types/src/primitives/ECDSA.d.ts.map +1 -1
- package/dist/types/src/primitives/ReductionContext.d.ts +9 -0
- package/dist/types/src/primitives/ReductionContext.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +3 -3
- package/dist/umd/bundle.js.map +1 -1
- package/docs/index.md +15 -1
- package/docs/reference/auth.md +2 -0
- package/docs/reference/messages.md +0 -24
- package/docs/reference/primitives.md +91 -31
- package/package.json +1 -1
- package/src/auth/Peer.ts +122 -57
- package/src/auth/__tests/Peer.test.ts +166 -257
- package/src/auth/types.ts +2 -0
- package/src/identity/IdentityClient.ts +153 -29
- package/src/identity/__tests/IdentityClient.test.ts +289 -1
- package/src/primitives/BigNumber.ts +27 -31
- package/src/primitives/ECDSA.ts +41 -2
- package/src/primitives/ReductionContext.ts +44 -48
- package/src/primitives/__tests/ECDSA.test.ts +16 -0
|
@@ -328,6 +328,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
328
328
|
)
|
|
329
329
|
|
|
330
330
|
const { bobReceivedCertificates } = setupPeers(false, true)
|
|
331
|
+
|
|
331
332
|
await mockGetVerifiableCertificates(
|
|
332
333
|
aliceVerifiableCertificate,
|
|
333
334
|
undefined,
|
|
@@ -335,32 +336,11 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
335
336
|
bobPubKey
|
|
336
337
|
)
|
|
337
338
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
// Wrap async logic in an IIFE so the callback remains synchronous.
|
|
341
|
-
(async () => {
|
|
342
|
-
await bobReceivedCertificates
|
|
343
|
-
|
|
344
|
-
if (certificatesReceivedByBob !== undefined && certificatesReceivedByBob.length > 0) {
|
|
345
|
-
// Use a for...of loop instead of forEach with an async callback.
|
|
346
|
-
for (const cert of certificatesReceivedByBob) {
|
|
347
|
-
// Decrypt to ensure it has the correct fields.
|
|
348
|
-
// const decryptedFields = await cert.decryptFields(walletB)
|
|
349
|
-
if (cert.certifier !== 'bob') {
|
|
350
|
-
// console.log('Bob accepted the message:', Utils.toUTF8(payload))
|
|
351
|
-
// console.log('Decrypted fields:', decryptedFields)
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
resolve()
|
|
356
|
-
})().catch((e) => {
|
|
357
|
-
// console.error(e)
|
|
358
|
-
})
|
|
359
|
-
})
|
|
360
|
-
})
|
|
339
|
+
// Initiate handshake ONLY
|
|
340
|
+
await alice.getAuthenticatedSession(bobPubKey)
|
|
361
341
|
|
|
362
|
-
|
|
363
|
-
await
|
|
342
|
+
// Wait for Bob to receive Alice's certificates
|
|
343
|
+
await bobReceivedCertificates
|
|
364
344
|
|
|
365
345
|
expect(certificatesReceivedByAlice).toEqual([])
|
|
366
346
|
expect(certificatesReceivedByBob).toEqual([aliceVerifiableCertificate])
|
|
@@ -418,16 +398,10 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
418
398
|
})
|
|
419
399
|
|
|
420
400
|
it('Alice requests Bob to present his library card before lending him a book', async () => {
|
|
421
|
-
const alicePubKey = (await walletA.getPublicKey({ identityKey: true }))
|
|
422
|
-
|
|
423
|
-
const bobPubKey = (await walletB.getPublicKey({ identityKey: true }))
|
|
424
|
-
.publicKey
|
|
401
|
+
const alicePubKey = (await walletA.getPublicKey({ identityKey: true })).publicKey
|
|
402
|
+
const bobPubKey = (await walletB.getPublicKey({ identityKey: true })).publicKey
|
|
425
403
|
|
|
426
|
-
|
|
427
|
-
const bobMasterCertificate = await createMasterCertificate(
|
|
428
|
-
walletB,
|
|
429
|
-
bobFields
|
|
430
|
-
)
|
|
404
|
+
const bobMasterCertificate = await createMasterCertificate(walletB, bobFields)
|
|
431
405
|
const bobVerifiableCertificate = await createVerifiableCertificate(
|
|
432
406
|
bobMasterCertificate,
|
|
433
407
|
walletB,
|
|
@@ -435,7 +409,6 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
435
409
|
['libraryCardNumber']
|
|
436
410
|
)
|
|
437
411
|
|
|
438
|
-
// Alice requires Bob to present his library card number
|
|
439
412
|
const aliceCertificatesToRequest = {
|
|
440
413
|
certifiers: [certifierPublicKey],
|
|
441
414
|
types: { [certificateType]: ['libraryCardNumber'] }
|
|
@@ -444,6 +417,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
444
417
|
const { aliceReceivedCertificates } = setupPeers(true, false, {
|
|
445
418
|
aliceCertsToRequest: aliceCertificatesToRequest
|
|
446
419
|
})
|
|
420
|
+
|
|
447
421
|
await mockGetVerifiableCertificates(
|
|
448
422
|
undefined,
|
|
449
423
|
bobVerifiableCertificate,
|
|
@@ -453,39 +427,19 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
453
427
|
|
|
454
428
|
const aliceAcceptedLibraryCard = jest.fn()
|
|
455
429
|
|
|
456
|
-
alice.listenForCertificatesReceived((
|
|
457
|
-
(
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
// Check and use the decrypted fields
|
|
463
|
-
if (
|
|
464
|
-
Object.keys(decryptedFields).length !== 0 &&
|
|
465
|
-
typeof decryptedFields.libraryCardNumber !== 'undefined'
|
|
466
|
-
) {
|
|
467
|
-
// console.log(
|
|
468
|
-
// `Alice received Bob's library card number: ${decryptedFields.libraryCardNumber}`
|
|
469
|
-
// )
|
|
470
|
-
aliceAcceptedLibraryCard()
|
|
471
|
-
}
|
|
430
|
+
alice.listenForCertificatesReceived(async (_sender, certificates) => {
|
|
431
|
+
for (const cert of certificates) {
|
|
432
|
+
const decrypted = await cert.decryptFields(walletA)
|
|
433
|
+
if (decrypted.libraryCardNumber !== undefined) {
|
|
434
|
+
aliceAcceptedLibraryCard()
|
|
472
435
|
}
|
|
473
|
-
}
|
|
436
|
+
}
|
|
474
437
|
})
|
|
475
438
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
// console.log('Bob received message from Alice:', Utils.toUTF8(payload))
|
|
479
|
-
resolve()
|
|
480
|
-
})
|
|
481
|
-
})
|
|
439
|
+
// 🔑 Correct trigger: certificate request, NOT general message
|
|
440
|
+
await alice.requestCertificates(aliceCertificatesToRequest, bobPubKey)
|
|
482
441
|
|
|
483
|
-
// Alice sends a message to Bob requesting his library card before lending him a book
|
|
484
|
-
await alice.toPeer(
|
|
485
|
-
Utils.toArray('Please present your library card to borrow a book.')
|
|
486
|
-
)
|
|
487
442
|
await aliceReceivedCertificates
|
|
488
|
-
await bobReceivedGeneralMessage
|
|
489
443
|
|
|
490
444
|
expect(aliceAcceptedLibraryCard).toHaveBeenCalled()
|
|
491
445
|
expect(certificatesReceivedByAlice).toEqual([bobVerifiableCertificate])
|
|
@@ -501,6 +455,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
501
455
|
const aliceMasterCertificate = await createMasterCertificate(walletA, {
|
|
502
456
|
name: 'Alice'
|
|
503
457
|
})
|
|
458
|
+
|
|
504
459
|
const aliceVerifiableCertificate = await createVerifiableCertificate(
|
|
505
460
|
aliceMasterCertificate,
|
|
506
461
|
walletA,
|
|
@@ -509,6 +464,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
509
464
|
)
|
|
510
465
|
|
|
511
466
|
const { bobReceivedCertificates } = setupPeers(false, true)
|
|
467
|
+
|
|
512
468
|
await mockGetVerifiableCertificates(
|
|
513
469
|
aliceVerifiableCertificate,
|
|
514
470
|
undefined,
|
|
@@ -516,45 +472,23 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
516
472
|
bobPubKey
|
|
517
473
|
)
|
|
518
474
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
await bobReceivedCertificates
|
|
523
|
-
// console.log('Bob received message:', Utils.toUTF8(payload))
|
|
524
|
-
|
|
525
|
-
// Bob requests additional certificates after initial communication
|
|
526
|
-
await bob.requestCertificates(certificatesToRequest, senderPublicKey)
|
|
527
|
-
resolve()
|
|
528
|
-
})().catch(e => { console.error(e) })
|
|
529
|
-
})
|
|
530
|
-
})
|
|
531
|
-
|
|
532
|
-
// Initial communication from Alice
|
|
533
|
-
await alice.toPeer(Utils.toArray('Hello Bob!'))
|
|
534
|
-
await bobReceivedGeneralMessage
|
|
475
|
+
// ---- Initial communication = handshake + initial cert exchange
|
|
476
|
+
await alice.getAuthenticatedSession(bobPubKey)
|
|
477
|
+
await bobReceivedCertificates
|
|
535
478
|
|
|
536
|
-
//
|
|
479
|
+
// ---- Bob requests additional certificates AFTER validation
|
|
537
480
|
const bobReceivedAdditionalCertificates = new Promise<void>((resolve) => {
|
|
538
|
-
bob.listenForCertificatesReceived((senderPublicKey, certificates) => {
|
|
539
|
-
(
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
for (const cert of certificates) {
|
|
543
|
-
const decrypted = await cert.decryptFields(walletB)
|
|
544
|
-
// console.log(
|
|
545
|
-
// 'Bob received additional certificates from Alice:',
|
|
546
|
-
// cert
|
|
547
|
-
// )
|
|
548
|
-
// console.log('Decrypted fields:', decrypted)
|
|
549
|
-
}
|
|
550
|
-
resolve()
|
|
481
|
+
bob.listenForCertificatesReceived(async (senderPublicKey, certificates) => {
|
|
482
|
+
if (certificates.length > 0) {
|
|
483
|
+
for (const cert of certificates) {
|
|
484
|
+
await cert.decryptFields(walletB)
|
|
551
485
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
})
|
|
486
|
+
resolve()
|
|
487
|
+
}
|
|
555
488
|
})
|
|
556
489
|
})
|
|
557
490
|
|
|
491
|
+
await bob.requestCertificates(certificatesToRequest, alicePubKey)
|
|
558
492
|
await bobReceivedAdditionalCertificates
|
|
559
493
|
|
|
560
494
|
expect(certificatesReceivedByBob).toEqual([aliceVerifiableCertificate])
|
|
@@ -566,11 +500,11 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
566
500
|
const bobPubKey = (await walletB.getPublicKey({ identityKey: true }))
|
|
567
501
|
.publicKey
|
|
568
502
|
|
|
569
|
-
// Alice's certificate includes her membership status
|
|
570
503
|
const aliceMasterCertificate = await createMasterCertificate(walletA, {
|
|
571
504
|
...aliceFields,
|
|
572
505
|
membershipStatus: 'Gold'
|
|
573
506
|
})
|
|
507
|
+
|
|
574
508
|
const aliceVerifiableCertificate = await createVerifiableCertificate(
|
|
575
509
|
aliceMasterCertificate,
|
|
576
510
|
walletA,
|
|
@@ -578,7 +512,6 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
578
512
|
['membershipStatus']
|
|
579
513
|
)
|
|
580
514
|
|
|
581
|
-
// Bob requires Alice to present her membership status
|
|
582
515
|
const bobCertificatesToRequest = {
|
|
583
516
|
certifiers: [certifierPublicKey],
|
|
584
517
|
types: { [certificateType]: ['membershipStatus'] }
|
|
@@ -587,6 +520,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
587
520
|
const { bobReceivedCertificates } = setupPeers(false, true, {
|
|
588
521
|
bobCertsToRequest: bobCertificatesToRequest
|
|
589
522
|
})
|
|
523
|
+
|
|
590
524
|
await mockGetVerifiableCertificates(
|
|
591
525
|
aliceVerifiableCertificate,
|
|
592
526
|
undefined,
|
|
@@ -597,40 +531,26 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
597
531
|
const bobAcceptedMembershipStatus = jest.fn()
|
|
598
532
|
|
|
599
533
|
const waitForCerts = new Promise<void>((resolve) => {
|
|
600
|
-
bob.listenForCertificatesReceived((
|
|
601
|
-
(
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
// console.log(
|
|
607
|
-
// `Bob received Alice's membership status: ${decryptedFields.membershipStatus}`
|
|
608
|
-
// )
|
|
609
|
-
bobAcceptedMembershipStatus()
|
|
610
|
-
resolve()
|
|
611
|
-
}
|
|
534
|
+
bob.listenForCertificatesReceived(async (_, certificates) => {
|
|
535
|
+
for (const cert of certificates) {
|
|
536
|
+
const decryptedFields = await cert.decryptFields(walletB)
|
|
537
|
+
if (decryptedFields.membershipStatus === 'Gold') {
|
|
538
|
+
bobAcceptedMembershipStatus()
|
|
539
|
+
resolve()
|
|
612
540
|
}
|
|
613
|
-
}
|
|
614
|
-
console.error('Error processing certificates:', error)
|
|
615
|
-
})
|
|
616
|
-
}
|
|
617
|
-
)
|
|
618
|
-
})
|
|
619
|
-
|
|
620
|
-
const bobReceivedGeneralMessage = new Promise<void>((resolve) => {
|
|
621
|
-
bob.listenForGeneralMessages((senderPublicKey, payload) => {
|
|
622
|
-
// console.log('Bob received message from Alice:', Utils.toUTF8(payload))
|
|
623
|
-
resolve()
|
|
541
|
+
}
|
|
624
542
|
})
|
|
625
543
|
})
|
|
626
544
|
|
|
627
|
-
//
|
|
545
|
+
// ---- INITIAL COMMUNICATION = handshake + certificate exchange
|
|
546
|
+
await alice.getAuthenticatedSession(bobPubKey)
|
|
547
|
+
await bobReceivedCertificates
|
|
548
|
+
await waitForCerts
|
|
549
|
+
|
|
550
|
+
// ---- OPTIONAL: now Alice can request premium content
|
|
628
551
|
await alice.toPeer(
|
|
629
552
|
Utils.toArray('I would like to access the premium content.')
|
|
630
553
|
)
|
|
631
|
-
await bobReceivedCertificates
|
|
632
|
-
await bobReceivedGeneralMessage
|
|
633
|
-
await waitForCerts
|
|
634
554
|
|
|
635
555
|
expect(bobAcceptedMembershipStatus).toHaveBeenCalled()
|
|
636
556
|
expect(certificatesReceivedByBob).toEqual([aliceVerifiableCertificate])
|
|
@@ -638,12 +558,9 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
638
558
|
}, 15000)
|
|
639
559
|
|
|
640
560
|
it("Both peers require each other's driver's license before carpooling", async () => {
|
|
641
|
-
const alicePubKey = (await walletA.getPublicKey({ identityKey: true }))
|
|
642
|
-
|
|
643
|
-
const bobPubKey = (await walletB.getPublicKey({ identityKey: true }))
|
|
644
|
-
.publicKey
|
|
561
|
+
const alicePubKey = (await walletA.getPublicKey({ identityKey: true })).publicKey
|
|
562
|
+
const bobPubKey = (await walletB.getPublicKey({ identityKey: true })).publicKey
|
|
645
563
|
|
|
646
|
-
// Both Alice and Bob have driver's license certificates
|
|
647
564
|
const aliceMasterCertificate = await createMasterCertificate(walletA, {
|
|
648
565
|
...aliceFields,
|
|
649
566
|
driversLicenseNumber: 'DLA123456'
|
|
@@ -666,7 +583,6 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
666
583
|
['driversLicenseNumber']
|
|
667
584
|
)
|
|
668
585
|
|
|
669
|
-
// Both peers require the driver's license number
|
|
670
586
|
const certificatesToRequestDriversLicense = {
|
|
671
587
|
certifiers: [certifierPublicKey],
|
|
672
588
|
types: { [certificateType]: ['driversLicenseNumber'] }
|
|
@@ -680,6 +596,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
680
596
|
bobCertsToRequest: certificatesToRequestDriversLicense
|
|
681
597
|
}
|
|
682
598
|
)
|
|
599
|
+
|
|
683
600
|
await mockGetVerifiableCertificates(
|
|
684
601
|
aliceVerifiableCertificate,
|
|
685
602
|
bobVerifiableCertificate,
|
|
@@ -687,91 +604,31 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
687
604
|
bobPubKey
|
|
688
605
|
)
|
|
689
606
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
const waitForAliceToAcceptBobDL = new Promise<void>((resolve) => {
|
|
694
|
-
alice.listenForCertificatesReceived((senderPublicKey, certificates) => {
|
|
695
|
-
(async () => {
|
|
696
|
-
for (const cert of certificates) {
|
|
697
|
-
const decryptedFields = await cert.decryptFields(walletA)
|
|
698
|
-
if (decryptedFields.driversLicenseNumber !== undefined) {
|
|
699
|
-
// console.log(
|
|
700
|
-
// `Alice received Bob's driver's license number: ${decryptedFields.driversLicenseNumber}`
|
|
701
|
-
// )
|
|
702
|
-
aliceAcceptedBobDL()
|
|
703
|
-
resolve()
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
})().catch(e => { })
|
|
707
|
-
}
|
|
708
|
-
)
|
|
709
|
-
})
|
|
710
|
-
|
|
711
|
-
const waitForBobToAcceptAliceDL = new Promise<void>((resolve) => {
|
|
712
|
-
bob.listenForCertificatesReceived((senderPublicKey, certificates) => {
|
|
713
|
-
(async () => {
|
|
714
|
-
for (const cert of certificates) {
|
|
715
|
-
const decryptedFields = await cert.decryptFields(walletB)
|
|
716
|
-
if (decryptedFields.driversLicenseNumber !== undefined) {
|
|
717
|
-
// console.log(
|
|
718
|
-
// `Bob received Alice's driver's license number: ${decryptedFields.driversLicenseNumber}`
|
|
719
|
-
// )
|
|
720
|
-
bobAcceptedAliceDL()
|
|
721
|
-
resolve()
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
})().catch(e => { })
|
|
725
|
-
}
|
|
726
|
-
)
|
|
727
|
-
})
|
|
728
|
-
|
|
729
|
-
const bobReceivedGeneralMessage = new Promise<void>((resolve) => {
|
|
730
|
-
bob.listenForGeneralMessages((senderPublicKey, payload) => {
|
|
731
|
-
(async () => {
|
|
732
|
-
// console.log('Bob received message from Alice:', Utils.toUTF8(payload))
|
|
733
|
-
await bob.toPeer(
|
|
734
|
-
Utils.toArray('Looking forward to carpooling!'),
|
|
735
|
-
senderPublicKey
|
|
736
|
-
)
|
|
737
|
-
resolve()
|
|
738
|
-
})().catch(e => { })
|
|
739
|
-
})
|
|
740
|
-
})
|
|
741
|
-
|
|
742
|
-
const aliceReceivedGeneralMessage = new Promise<void>((resolve) => {
|
|
743
|
-
alice.listenForGeneralMessages((senderPublicKey, payload) => {
|
|
744
|
-
// console.log('Alice received message from Bob:', Utils.toUTF8(payload))
|
|
745
|
-
resolve()
|
|
746
|
-
})
|
|
747
|
-
})
|
|
748
|
-
|
|
749
|
-
// Alice initiates the conversation
|
|
750
|
-
await alice.toPeer(
|
|
751
|
-
Utils.toArray("Please share your driver's license number for carpooling.")
|
|
752
|
-
)
|
|
607
|
+
// 🔑 Step 1: Alice requests Bob's cert
|
|
608
|
+
await alice.requestCertificates(certificatesToRequestDriversLicense, bobPubKey)
|
|
753
609
|
await aliceReceivedCertificates
|
|
754
|
-
await bobReceivedCertificates
|
|
755
|
-
await bobReceivedGeneralMessage
|
|
756
|
-
await aliceReceivedGeneralMessage
|
|
757
610
|
|
|
758
|
-
//
|
|
759
|
-
await
|
|
760
|
-
await
|
|
611
|
+
// 🔑 Step 2: Bob requests Alice's cert
|
|
612
|
+
await bob.requestCertificates(certificatesToRequestDriversLicense, alicePubKey)
|
|
613
|
+
await bobReceivedCertificates
|
|
761
614
|
|
|
762
|
-
expect(aliceAcceptedBobDL).toHaveBeenCalled()
|
|
763
|
-
expect(bobAcceptedAliceDL).toHaveBeenCalled()
|
|
764
615
|
expect(certificatesReceivedByAlice).toEqual([bobVerifiableCertificate])
|
|
765
616
|
expect(certificatesReceivedByBob).toEqual([aliceVerifiableCertificate])
|
|
617
|
+
|
|
618
|
+
// 🔓 Step 3: NOW general messages are allowed
|
|
619
|
+
const bobReceivedMessage = new Promise<void>((resolve) => {
|
|
620
|
+
bob.listenForGeneralMessages(() => resolve())
|
|
621
|
+
})
|
|
622
|
+
|
|
623
|
+
await alice.toPeer(Utils.toArray('Ready to carpool!'), bobPubKey)
|
|
624
|
+
await bobReceivedMessage
|
|
766
625
|
}, 20000)
|
|
767
626
|
|
|
768
627
|
it('Peers accept partial certificates if at least one required field is present', async () => {
|
|
769
|
-
const alicePubKey = (await walletA.getPublicKey({ identityKey: true }))
|
|
770
|
-
|
|
771
|
-
const bobPubKey = (await walletB.getPublicKey({ identityKey: true }))
|
|
772
|
-
.publicKey
|
|
628
|
+
const alicePubKey = (await walletA.getPublicKey({ identityKey: true })).publicKey
|
|
629
|
+
const bobPubKey = (await walletB.getPublicKey({ identityKey: true })).publicKey
|
|
773
630
|
|
|
774
|
-
// Alice
|
|
631
|
+
// Alice has name+email, Bob has only email
|
|
775
632
|
const aliceMasterCertificate = await createMasterCertificate(walletA, {
|
|
776
633
|
name: 'Alice',
|
|
777
634
|
email: 'alice@example.com'
|
|
@@ -806,6 +663,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
806
663
|
bobCertsToRequest: partialCertificatesToRequest
|
|
807
664
|
}
|
|
808
665
|
)
|
|
666
|
+
|
|
809
667
|
await mockGetVerifiableCertificates(
|
|
810
668
|
aliceVerifiableCertificate,
|
|
811
669
|
bobVerifiableCertificate,
|
|
@@ -813,63 +671,36 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
813
671
|
bobPubKey
|
|
814
672
|
)
|
|
815
673
|
|
|
816
|
-
|
|
817
|
-
|
|
674
|
+
// --- Exchange certs explicitly (no general messages yet) ---
|
|
675
|
+
await alice.requestCertificates(partialCertificatesToRequest, bobPubKey)
|
|
676
|
+
await bob.requestCertificates(partialCertificatesToRequest, alicePubKey)
|
|
818
677
|
|
|
819
|
-
const waitForAlicePartialCert = new Promise<void>((resolve) => {
|
|
820
|
-
alice.listenForCertificatesReceived((senderPublicKey, certificates) => {
|
|
821
|
-
(async () => {
|
|
822
|
-
for (const cert of certificates) {
|
|
823
|
-
const decryptedFields = await cert.decryptFields(walletA)
|
|
824
|
-
if (decryptedFields.email !== undefined || decryptedFields.name !== undefined) {
|
|
825
|
-
// console.log(
|
|
826
|
-
// `Alice received Bob's certificate with fields: ${Object.keys(decryptedFields).join(', ')}`
|
|
827
|
-
// )
|
|
828
|
-
aliceAcceptedPartialCert()
|
|
829
|
-
resolve()
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
})().catch(e => { })
|
|
833
|
-
})
|
|
834
|
-
})
|
|
835
|
-
|
|
836
|
-
const waitForBobPartialCert = new Promise<void>((resolve) => {
|
|
837
|
-
bob.listenForCertificatesReceived((senderPublicKey, certificates) => {
|
|
838
|
-
(async () => {
|
|
839
|
-
for (const cert of certificates) {
|
|
840
|
-
const decryptedFields = await cert.decryptFields(walletB)
|
|
841
|
-
if (decryptedFields.email !== undefined || decryptedFields.name !== undefined) {
|
|
842
|
-
// console.log(
|
|
843
|
-
// `Bob received Alice's certificate with fields: ${Object.keys(decryptedFields).join(', ')}`
|
|
844
|
-
// )
|
|
845
|
-
bobAcceptedPartialCert()
|
|
846
|
-
resolve()
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
})().catch(e => { })
|
|
850
|
-
})
|
|
851
|
-
})
|
|
852
|
-
|
|
853
|
-
const bobReceivedGeneralMessage = new Promise<void>((resolve) => {
|
|
854
|
-
bob.listenForGeneralMessages((senderPublicKey, payload) => {
|
|
855
|
-
// console.log('Bob received message:', Utils.toUTF8(payload))
|
|
856
|
-
resolve()
|
|
857
|
-
})
|
|
858
|
-
})
|
|
859
|
-
|
|
860
|
-
await alice.toPeer(Utils.toArray('Hello Bob!'))
|
|
861
678
|
await aliceReceivedCertificates
|
|
862
679
|
await bobReceivedCertificates
|
|
863
|
-
await bobReceivedGeneralMessage
|
|
864
680
|
|
|
865
|
-
//
|
|
866
|
-
await
|
|
867
|
-
await
|
|
681
|
+
// --- Validate "partial" acceptance by decrypting on each side ---
|
|
682
|
+
const aliceDecrypted = await certificatesReceivedByAlice![0].decryptFields(walletA)
|
|
683
|
+
const bobDecrypted = await certificatesReceivedByBob![0].decryptFields(walletB)
|
|
684
|
+
|
|
685
|
+
// Alice received Bob's cert which only has email, but request was name+email
|
|
686
|
+
expect(aliceDecrypted.email).toBeDefined()
|
|
687
|
+
// (Bob did not reveal name, so it may be undefined)
|
|
688
|
+
expect(aliceDecrypted.name).toBeUndefined()
|
|
689
|
+
|
|
690
|
+
// Bob received Alice's cert which has both name+email
|
|
691
|
+
expect(bobDecrypted.email).toBeDefined()
|
|
692
|
+
expect(bobDecrypted.name).toBeDefined()
|
|
868
693
|
|
|
869
|
-
expect(aliceAcceptedPartialCert).toHaveBeenCalled()
|
|
870
|
-
expect(bobAcceptedPartialCert).toHaveBeenCalled()
|
|
871
694
|
expect(certificatesReceivedByAlice).toEqual([bobVerifiableCertificate])
|
|
872
695
|
expect(certificatesReceivedByBob).toEqual([aliceVerifiableCertificate])
|
|
696
|
+
|
|
697
|
+
// --- Optional: now general messages should work (since validation happened) ---
|
|
698
|
+
const bobReceivedGeneralMessage = new Promise<void>((resolve) => {
|
|
699
|
+
bob.listenForGeneralMessages(() => resolve())
|
|
700
|
+
})
|
|
701
|
+
|
|
702
|
+
await alice.toPeer(Utils.toArray('Hello Bob!'), bobPubKey)
|
|
703
|
+
await bobReceivedGeneralMessage
|
|
873
704
|
}, 20000)
|
|
874
705
|
|
|
875
706
|
describe('Transport Error Handling', () => {
|
|
@@ -1056,4 +887,82 @@ describe('Peer class mutual authentication and certificate exchange', () => {
|
|
|
1056
887
|
}
|
|
1057
888
|
}, 15000)
|
|
1058
889
|
})
|
|
890
|
+
|
|
891
|
+
describe('Certificate gating for general messages', () => {
|
|
892
|
+
it('rejects incoming general messages before certificate validation', async () => {
|
|
893
|
+
const bobPubKey = (await walletB.getPublicKey({ identityKey: true })).publicKey
|
|
894
|
+
|
|
895
|
+
setupPeers(false, true) // Bob requires certs
|
|
896
|
+
|
|
897
|
+
let received = false
|
|
898
|
+
bob.listenForGeneralMessages(() => {
|
|
899
|
+
received = true
|
|
900
|
+
})
|
|
901
|
+
|
|
902
|
+
// Send message — error is thrown internally
|
|
903
|
+
try {
|
|
904
|
+
await alice.toPeer(Utils.toArray('Hello Bob!'), bobPubKey)
|
|
905
|
+
} catch {
|
|
906
|
+
// swallow — error is expected but not part of assertion
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// Allow transport handlers to run
|
|
910
|
+
await new Promise(r => setTimeout(r, 50))
|
|
911
|
+
|
|
912
|
+
// Message must NOT be delivered
|
|
913
|
+
expect(received).toBe(false)
|
|
914
|
+
})
|
|
915
|
+
|
|
916
|
+
it('blocks outgoing messages until certificates are validated', async () => {
|
|
917
|
+
setupPeers(true, false) // Alice requires certs from Bob
|
|
918
|
+
|
|
919
|
+
// Prevent Bob from auto-supplying certificates during the handshake.
|
|
920
|
+
// This keeps Alice in "certs required but not validated" state.
|
|
921
|
+
bob.listenForCertificatesRequested(() => {
|
|
922
|
+
// Intentionally do nothing (no auto-response)
|
|
923
|
+
})
|
|
924
|
+
|
|
925
|
+
await expect(
|
|
926
|
+
alice.toPeer(Utils.toArray('Hello Bob!'))
|
|
927
|
+
).rejects.toThrow('certificate validation')
|
|
928
|
+
})
|
|
929
|
+
|
|
930
|
+
it('allows general messages after certificate validation completes', async () => {
|
|
931
|
+
const alicePubKey = (await walletA.getPublicKey({ identityKey: true })).publicKey
|
|
932
|
+
const bobPubKey = (await walletB.getPublicKey({ identityKey: true })).publicKey
|
|
933
|
+
|
|
934
|
+
const bobMasterCert = await createMasterCertificate(walletB, { name: 'Bob' })
|
|
935
|
+
const bobCert = await createVerifiableCertificate(
|
|
936
|
+
bobMasterCert,
|
|
937
|
+
walletB,
|
|
938
|
+
alicePubKey,
|
|
939
|
+
['name']
|
|
940
|
+
)
|
|
941
|
+
|
|
942
|
+
// Alice requires certs from Bob
|
|
943
|
+
const { aliceReceivedCertificates } = setupPeers(true, false)
|
|
944
|
+
|
|
945
|
+
// Bob will provide his cert to Alice when asked
|
|
946
|
+
await mockGetVerifiableCertificates(
|
|
947
|
+
undefined,
|
|
948
|
+
bobCert,
|
|
949
|
+
alicePubKey,
|
|
950
|
+
bobPubKey
|
|
951
|
+
)
|
|
952
|
+
|
|
953
|
+
// Trigger handshake + cert exchange WITHOUT sending a general message
|
|
954
|
+
await alice.toPeer(Utils.toArray('handshake'), bobPubKey)
|
|
955
|
+
|
|
956
|
+
// Wait until Alice has validated Bob’s certificate
|
|
957
|
+
await aliceReceivedCertificates
|
|
958
|
+
|
|
959
|
+
// Now general messages must be allowed
|
|
960
|
+
const received = new Promise<void>((resolve) => {
|
|
961
|
+
bob.listenForGeneralMessages(() => resolve())
|
|
962
|
+
})
|
|
963
|
+
|
|
964
|
+
await alice.toPeer(Utils.toArray('Hello Bob!'), bobPubKey)
|
|
965
|
+
await received
|
|
966
|
+
})
|
|
967
|
+
})
|
|
1059
968
|
})
|