@bsv/sdk 1.3.9 → 1.3.11

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 (72) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/auth/Peer.js.map +1 -1
  3. package/dist/cjs/src/auth/certificates/Certificate.js +1 -1
  4. package/dist/cjs/src/auth/certificates/Certificate.js.map +1 -1
  5. package/dist/cjs/src/auth/certificates/MasterCertificate.js +93 -63
  6. package/dist/cjs/src/auth/certificates/MasterCertificate.js.map +1 -1
  7. package/dist/cjs/src/auth/certificates/VerifiableCertificate.js +2 -2
  8. package/dist/cjs/src/auth/certificates/VerifiableCertificate.js.map +1 -1
  9. package/dist/cjs/src/auth/utils/createNonce.js +9 -3
  10. package/dist/cjs/src/auth/utils/createNonce.js.map +1 -1
  11. package/dist/cjs/src/auth/utils/getVerifiableCertificates.js +1 -1
  12. package/dist/cjs/src/auth/utils/getVerifiableCertificates.js.map +1 -1
  13. package/dist/cjs/src/auth/utils/validateCertificates.js +1 -1
  14. package/dist/cjs/src/auth/utils/validateCertificates.js.map +1 -1
  15. package/dist/cjs/src/auth/utils/verifyNonce.js +3 -2
  16. package/dist/cjs/src/auth/utils/verifyNonce.js.map +1 -1
  17. package/dist/cjs/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -1
  18. package/dist/cjs/src/wallet/ProtoWallet.js.map +1 -1
  19. package/dist/cjs/src/wallet/WalletClient.js.map +1 -1
  20. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  21. package/dist/esm/src/auth/Peer.js.map +1 -1
  22. package/dist/esm/src/auth/certificates/Certificate.js +2 -2
  23. package/dist/esm/src/auth/certificates/Certificate.js.map +1 -1
  24. package/dist/esm/src/auth/certificates/MasterCertificate.js +93 -63
  25. package/dist/esm/src/auth/certificates/MasterCertificate.js.map +1 -1
  26. package/dist/esm/src/auth/certificates/VerifiableCertificate.js +2 -2
  27. package/dist/esm/src/auth/certificates/VerifiableCertificate.js.map +1 -1
  28. package/dist/esm/src/auth/utils/createNonce.js +9 -3
  29. package/dist/esm/src/auth/utils/createNonce.js.map +1 -1
  30. package/dist/esm/src/auth/utils/getVerifiableCertificates.js +1 -1
  31. package/dist/esm/src/auth/utils/getVerifiableCertificates.js.map +1 -1
  32. package/dist/esm/src/auth/utils/validateCertificates.js +1 -1
  33. package/dist/esm/src/auth/utils/validateCertificates.js.map +1 -1
  34. package/dist/esm/src/auth/utils/verifyNonce.js +3 -2
  35. package/dist/esm/src/auth/utils/verifyNonce.js.map +1 -1
  36. package/dist/esm/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -1
  37. package/dist/esm/src/wallet/ProtoWallet.js.map +1 -1
  38. package/dist/esm/src/wallet/WalletClient.js.map +1 -1
  39. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  40. package/dist/types/src/auth/Peer.d.ts.map +1 -1
  41. package/dist/types/src/auth/certificates/Certificate.d.ts +3 -3
  42. package/dist/types/src/auth/certificates/Certificate.d.ts.map +1 -1
  43. package/dist/types/src/auth/certificates/MasterCertificate.d.ts +41 -11
  44. package/dist/types/src/auth/certificates/MasterCertificate.d.ts.map +1 -1
  45. package/dist/types/src/auth/certificates/VerifiableCertificate.d.ts +1 -1
  46. package/dist/types/src/auth/certificates/VerifiableCertificate.d.ts.map +1 -1
  47. package/dist/types/src/auth/utils/createNonce.d.ts +4 -3
  48. package/dist/types/src/auth/utils/createNonce.d.ts.map +1 -1
  49. package/dist/types/src/auth/utils/verifyNonce.d.ts +3 -2
  50. package/dist/types/src/auth/utils/verifyNonce.d.ts.map +1 -1
  51. package/dist/types/src/overlay-tools/OverlayAdminTokenTemplate.d.ts.map +1 -1
  52. package/dist/types/src/wallet/ProtoWallet.d.ts.map +1 -1
  53. package/dist/types/src/wallet/WalletClient.d.ts.map +1 -1
  54. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  55. package/dist/umd/bundle.js +1 -1
  56. package/docs/auth.md +71 -26
  57. package/package.json +1 -1
  58. package/src/auth/Peer.ts +21 -21
  59. package/src/auth/__tests/Peer.test.ts +19 -47
  60. package/src/auth/certificates/Certificate.ts +3 -3
  61. package/src/auth/certificates/MasterCertificate.ts +131 -67
  62. package/src/auth/certificates/VerifiableCertificate.ts +3 -4
  63. package/src/auth/certificates/__tests/MasterCertificate.test.ts +142 -51
  64. package/src/auth/certificates/__tests/VerifiableCertificate.test.ts +25 -30
  65. package/src/auth/utils/__tests/cryptononce.test.ts +42 -7
  66. package/src/auth/utils/createNonce.ts +10 -4
  67. package/src/auth/utils/getVerifiableCertificates.ts +2 -2
  68. package/src/auth/utils/validateCertificates.ts +2 -2
  69. package/src/auth/utils/verifyNonce.ts +4 -3
  70. package/src/overlay-tools/OverlayAdminTokenTemplate.ts +4 -4
  71. package/src/wallet/ProtoWallet.ts +10 -10
  72. package/src/wallet/WalletClient.ts +30 -30
package/docs/auth.md CHANGED
@@ -212,7 +212,7 @@ export default class Certificate {
212
212
  subject: PubKeyHex;
213
213
  certifier: PubKeyHex;
214
214
  revocationOutpoint: OutpointString;
215
- fields: Record<CertificateFieldNameUnder50Bytes, string>;
215
+ fields: Record<CertificateFieldNameUnder50Bytes, Base64String>;
216
216
  signature?: HexString;
217
217
  constructor(type: Base64String, serialNumber: Base64String, subject: PubKeyHex, certifier: PubKeyHex, revocationOutpoint: OutpointString, fields: Record<CertificateFieldNameUnder50Bytes, string>, signature?: HexString)
218
218
  toBinary(includeSignature: boolean = true): number[]
@@ -269,12 +269,12 @@ See also: [PubKeyHex](#type-pubkeyhex)
269
269
 
270
270
  #### Property fields
271
271
 
272
- All the fields present in the certificate, with field names as keys and field values as strings.
272
+ All the fields present in the certificate, with field names as keys and encrypted field values as Base64 strings.
273
273
 
274
274
  ```ts
275
- fields: Record<CertificateFieldNameUnder50Bytes, string>
275
+ fields: Record<CertificateFieldNameUnder50Bytes, Base64String>
276
276
  ```
277
- See also: [CertificateFieldNameUnder50Bytes](#type-certificatefieldnameunder50bytes)
277
+ See also: [Base64String](#type-base64string), [CertificateFieldNameUnder50Bytes](#type-certificatefieldnameunder50bytes)
278
278
 
279
279
  #### Property revocationOutpoint
280
280
 
@@ -466,9 +466,10 @@ export class MasterCertificate extends Certificate {
466
466
  declare signature?: HexString;
467
467
  masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>;
468
468
  constructor(type: Base64String, serialNumber: Base64String, subject: PubKeyHex, certifier: PubKeyHex, revocationOutpoint: OutpointString, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, signature?: HexString)
469
- async decryptFields(subjectWallet: WalletInterface): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
470
- async createKeyringForVerifier(subjectWallet: WalletInterface, verifier: WalletCounterparty, fieldsToReveal: string[], originator?: string): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
471
- static async issueCertificateForSubject(certifierWallet: WalletInterface, subject: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, string>, certificateType: string, getRevocationOutpoint = async (serialNumber: string): Promise<string> => { return "Certificate revocation not tracked."; }): Promise<MasterCertificate>
469
+ static async createCertificateFields(creatorWallet: WalletInterface, certifierOrSubject: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, string>): Promise<CreateCertificateFieldsResult>
470
+ static async createKeyringForVerifier(subjectWallet: WalletInterface, certifier: WalletCounterparty, verifier: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, fieldsToReveal: string[], masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, serialNumber: Base64String, originator?: string): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
471
+ static async issueCertificateForSubject(certifierWallet: WalletInterface, subject: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, string>, certificateType: string, getRevocationOutpoint = async (serialNumber: string): Promise<string> => { return "Certificate revocation not tracked."; }, serialNumber?: string): Promise<MasterCertificate>
472
+ static async decryptFields(subjectOrCertifierWallet: WalletInterface, masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, counterparty: WalletCounterparty): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
472
473
  }
473
474
  ```
474
475
 
@@ -478,6 +479,34 @@ See also: [Base64String](#type-base64string), [Certificate](#class-certificate),
478
479
 
479
480
  <summary>Class MasterCertificate Details</summary>
480
481
 
482
+ #### Method createCertificateFields
483
+
484
+ Encrypts certificate fields for a subject and generates a master keyring.
485
+ This method returns a master keyring tied to a specific certifier or subject who will validate
486
+ and sign off on the fields, along with the encrypted certificate fields.
487
+
488
+ ```ts
489
+ static async createCertificateFields(creatorWallet: WalletInterface, certifierOrSubject: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, string>): Promise<CreateCertificateFieldsResult>
490
+ ```
491
+ See also: [CertificateFieldNameUnder50Bytes](#type-certificatefieldnameunder50bytes), [WalletCounterparty](#type-walletcounterparty), [WalletInterface](#interface-walletinterface)
492
+
493
+ Returns
494
+
495
+ A promise resolving to an object containing:
496
+ - `certificateFields` {Record<CertificateFieldNameUnder50Bytes, Base64String>}:
497
+ The encrypted certificate fields.
498
+ - `masterKeyring` {Record<CertificateFieldNameUnder50Bytes, Base64String>}:
499
+ The master keyring containing encrypted revelation keys for each field.
500
+
501
+ Argument Details
502
+
503
+ + **creatorWallet**
504
+ + The wallet of the creator responsible for encrypting the fields.
505
+ + **certifierOrSubject**
506
+ + The certifier or subject who will validate the certificate fields.
507
+ + **fields**
508
+ + A record of certificate field names (under 50 bytes) mapped to their values.
509
+
481
510
  #### Method createKeyringForVerifier
482
511
 
483
512
  Creates a keyring for a verifier, enabling them to decrypt specific certificate fields.
@@ -486,9 +515,9 @@ for the verifier's identity key. The result is a keyring containing the keys nec
486
515
  for the verifier to access the designated fields.
487
516
 
488
517
  ```ts
489
- async createKeyringForVerifier(subjectWallet: WalletInterface, verifier: WalletCounterparty, fieldsToReveal: string[], originator?: string): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
518
+ static async createKeyringForVerifier(subjectWallet: WalletInterface, certifier: WalletCounterparty, verifier: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, fieldsToReveal: string[], masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, serialNumber: Base64String, originator?: string): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
490
519
  ```
491
- See also: [CertificateFieldNameUnder50Bytes](#type-certificatefieldnameunder50bytes), [WalletCounterparty](#type-walletcounterparty), [WalletInterface](#interface-walletinterface)
520
+ See also: [Base64String](#type-base64string), [CertificateFieldNameUnder50Bytes](#type-certificatefieldnameunder50bytes), [WalletCounterparty](#type-walletcounterparty), [WalletInterface](#interface-walletinterface)
492
521
 
493
522
  Returns
494
523
 
@@ -514,24 +543,33 @@ Throws an error if:
514
543
 
515
544
  #### Method decryptFields
516
545
 
517
- Decrypts all fields in the MasterCertificate using the subject's wallet.
546
+ Decrypts all fields in the MasterCertificate using the subject's or certifier's wallet.
518
547
 
519
- This method uses the `masterKeyring` to decrypt each field's encryption key and then
520
- decrypts the field values. The result is a record of plaintext field names and values.
548
+ This method allows the subject or certifier to decrypt the `masterKeyring` and retrieve
549
+ the encryption keys for each field, which are then used to decrypt the corresponding field values.
550
+ The counterparty used for decryption depends on how the certificate fields were created:
551
+ - If the certificate is self-signed, the counterparty should be set to 'self'.
552
+ - Otherwise, the counterparty should always be the other party involved in the certificate issuance process (the subject or certifier).
521
553
 
522
554
  ```ts
523
- async decryptFields(subjectWallet: WalletInterface): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
555
+ static async decryptFields(subjectOrCertifierWallet: WalletInterface, masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, counterparty: WalletCounterparty): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
524
556
  ```
525
- See also: [CertificateFieldNameUnder50Bytes](#type-certificatefieldnameunder50bytes), [WalletInterface](#interface-walletinterface)
557
+ See also: [Base64String](#type-base64string), [CertificateFieldNameUnder50Bytes](#type-certificatefieldnameunder50bytes), [WalletCounterparty](#type-walletcounterparty), [WalletInterface](#interface-walletinterface)
526
558
 
527
559
  Returns
528
560
 
529
- - A record of field names and their decrypted values in plaintext.
561
+ A promise resolving to a record of field names and their decrypted values in plaintext.
530
562
 
531
563
  Argument Details
532
564
 
533
- + **subjectWallet**
534
- + The wallet of the subject, used to decrypt the master keyring and field values.
565
+ + **subjectOrCertifierWallet**
566
+ + The wallet of the subject or certifier, used to decrypt the master keyring and field values.
567
+ + **masterKeyring**
568
+ + A record containing encrypted keys for each field.
569
+ + **fields**
570
+ + A record of encrypted field names and their values.
571
+ + **counterparty**
572
+ + The counterparty responsible for creating or signing the certificate. For self-signed certificates, use 'self'.
535
573
 
536
574
  Throws
537
575
 
@@ -547,7 +585,7 @@ generated symmetric key, which is then encrypted for the subject. The certificat
547
585
  can also includes a revocation outpoint to manage potential revocation.
548
586
 
549
587
  ```ts
550
- static async issueCertificateForSubject(certifierWallet: WalletInterface, subject: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, string>, certificateType: string, getRevocationOutpoint = async (serialNumber: string): Promise<string> => { return "Certificate revocation not tracked."; }): Promise<MasterCertificate>
588
+ static async issueCertificateForSubject(certifierWallet: WalletInterface, subject: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, string>, certificateType: string, getRevocationOutpoint = async (serialNumber: string): Promise<string> => { return "Certificate revocation not tracked."; }, serialNumber?: string): Promise<MasterCertificate>
551
589
  ```
552
590
  See also: [CertificateFieldNameUnder50Bytes](#type-certificatefieldnameunder50bytes), [MasterCertificate](#class-mastercertificate), [WalletCounterparty](#type-walletcounterparty), [WalletInterface](#interface-walletinterface)
553
591
 
@@ -1078,7 +1116,7 @@ export class VerifiableCertificate extends Certificate {
1078
1116
  declare signature?: HexString;
1079
1117
  keyring: Record<CertificateFieldNameUnder50Bytes, string>;
1080
1118
  decryptedFields?: Record<CertificateFieldNameUnder50Bytes, Base64String>;
1081
- constructor(type: Base64String, serialNumber: Base64String, subject: PubKeyHex, certifier: PubKeyHex, revocationOutpoint: OutpointString, fields: Record<CertificateFieldNameUnder50Bytes, string>, signature?: HexString, keyring?: Record<CertificateFieldNameUnder50Bytes, string>, decryptedFields?: Record<CertificateFieldNameUnder50Bytes, Base64String>)
1119
+ constructor(type: Base64String, serialNumber: Base64String, subject: PubKeyHex, certifier: PubKeyHex, revocationOutpoint: OutpointString, fields: Record<CertificateFieldNameUnder50Bytes, string>, keyring: Record<CertificateFieldNameUnder50Bytes, string>, signature?: HexString, decryptedFields?: Record<CertificateFieldNameUnder50Bytes, Base64String>)
1082
1120
  async decryptFields(verifierWallet: WalletInterface): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
1083
1121
  }
1084
1122
  ```
@@ -1129,13 +1167,13 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
1129
1167
 
1130
1168
  ### Function: createNonce
1131
1169
 
1132
- Creates a nonce derived from a privateKey
1170
+ Creates a nonce derived from a wallet
1133
1171
 
1134
1172
  ```ts
1135
- export async function createNonce(wallet: WalletInterface): Promise<string>
1173
+ export async function createNonce(wallet: WalletInterface, counterparty: WalletCounterparty = "self"): Promise<string>
1136
1174
  ```
1137
1175
 
1138
- See also: [WalletInterface](#interface-walletinterface)
1176
+ See also: [WalletCounterparty](#type-walletcounterparty), [WalletInterface](#interface-walletinterface)
1139
1177
 
1140
1178
  <details>
1141
1179
 
@@ -1145,6 +1183,11 @@ Returns
1145
1183
 
1146
1184
  A random nonce derived with a wallet
1147
1185
 
1186
+ Argument Details
1187
+
1188
+ + **counterparty**
1189
+ + The counterparty to the nonce creation. Defaults to 'self'.
1190
+
1148
1191
  </details>
1149
1192
 
1150
1193
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
@@ -1155,10 +1198,10 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
1155
1198
  Verifies a nonce derived from a wallet
1156
1199
 
1157
1200
  ```ts
1158
- export async function verifyNonce(nonce: string, wallet: WalletInterface): Promise<boolean>
1201
+ export async function verifyNonce(nonce: string, wallet: WalletInterface, counterparty: WalletCounterparty = "self"): Promise<boolean>
1159
1202
  ```
1160
1203
 
1161
- See also: [WalletInterface](#interface-walletinterface)
1204
+ See also: [WalletCounterparty](#type-walletcounterparty), [WalletInterface](#interface-walletinterface)
1162
1205
 
1163
1206
  <details>
1164
1207
 
@@ -1172,6 +1215,8 @@ Argument Details
1172
1215
 
1173
1216
  + **nonce**
1174
1217
  + A nonce to verify as a base64 string.
1218
+ + **counterparty**
1219
+ + The counterparty to the nonce creation. Defaults to 'self'.
1175
1220
 
1176
1221
  </details>
1177
1222
 
@@ -1207,7 +1252,7 @@ getVerifiableCertificates = async (wallet: WalletInterface, requestedCertificate
1207
1252
  fieldsToReveal: requestedCertificates.types[certificate.type],
1208
1253
  verifier: verifierIdentityKey
1209
1254
  });
1210
- return new VerifiableCertificate(certificate.type, certificate.serialNumber, certificate.subject, certificate.certifier, certificate.revocationOutpoint, certificate.fields, certificate.signature, keyringForVerifier);
1255
+ return new VerifiableCertificate(certificate.type, certificate.serialNumber, certificate.subject, certificate.certifier, certificate.revocationOutpoint, certificate.fields, keyringForVerifier, certificate.signature);
1211
1256
  }));
1212
1257
  }
1213
1258
  ```
@@ -1225,7 +1270,7 @@ validateCertificates = async (verifierWallet: WalletInterface, message: AuthMess
1225
1270
  if (incomingCert.subject !== message.identityKey) {
1226
1271
  throw new Error(`The subject of one of your certificates ("${incomingCert.subject}") is not the same as the request sender ("${message.identityKey}").`);
1227
1272
  }
1228
- const certToVerify = new VerifiableCertificate(incomingCert.type, incomingCert.serialNumber, incomingCert.subject, incomingCert.certifier, incomingCert.revocationOutpoint, incomingCert.fields, incomingCert.signature, incomingCert.keyring);
1273
+ const certToVerify = new VerifiableCertificate(incomingCert.type, incomingCert.serialNumber, incomingCert.subject, incomingCert.certifier, incomingCert.revocationOutpoint, incomingCert.fields, incomingCert.keyring, incomingCert.signature);
1229
1274
  const isValidCert = await certToVerify.verify();
1230
1275
  if (!isValidCert) {
1231
1276
  throw new Error(`The signature for the certificate with serial number ${certToVerify.serialNumber} is invalid!`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/sdk",
3
- "version": "1.3.9",
3
+ "version": "1.3.11",
4
4
  "type": "module",
5
5
  "description": "BSV Blockchain Software Development Kit",
6
6
  "main": "dist/cjs/mod.js",
package/src/auth/Peer.ts CHANGED
@@ -39,7 +39,7 @@ export class Peer {
39
39
  * @param {SessionManager} [sessionManager] - Optional SessionManager to be used for managing peer sessions.
40
40
  * @param {boolean} [autoPersistLastSession] - Whether to auto-persist the session with the last-interacted-with peer. Defaults to true.
41
41
  */
42
- constructor(
42
+ constructor (
43
43
  wallet: WalletInterface,
44
44
  transport: Transport,
45
45
  certificatesToRequest?: RequestedCertificateSet,
@@ -66,7 +66,7 @@ export class Peer {
66
66
  * @returns {Promise<void>}
67
67
  * @throws Will throw an error if the message fails to send.
68
68
  */
69
- async toPeer(message: number[], identityKey?: string, maxWaitTime?: number): Promise<void> {
69
+ async toPeer (message: number[], identityKey?: string, maxWaitTime?: number): Promise<void> {
70
70
  if (this.autoPersistLastSession && this.lastInteractedWithPeer && typeof identityKey !== 'string') {
71
71
  identityKey = this.lastInteractedWithPeer
72
72
  }
@@ -111,7 +111,7 @@ export class Peer {
111
111
  * @returns {Promise<void>} Resolves if the certificate request message is successfully sent.
112
112
  * @throws Will throw an error if the peer session is not authenticated or if sending the request fails.
113
113
  */
114
- async requestCertificates(certificatesToRequest: RequestedCertificateSet, identityKey?: string, maxWaitTime = 10000): Promise<void> {
114
+ async requestCertificates (certificatesToRequest: RequestedCertificateSet, identityKey?: string, maxWaitTime = 10000): Promise<void> {
115
115
  const peerSession = await this.getAuthenticatedSession(identityKey, maxWaitTime)
116
116
 
117
117
  // Prepare the general message
@@ -152,7 +152,7 @@ export class Peer {
152
152
  * @returns {Promise<PeerSession>} - A promise that resolves with an authenticated `PeerSession`.
153
153
  * @throws {Error} - Throws an error if the transport is not connected or if the handshake fails.
154
154
  */
155
- async getAuthenticatedSession(identityKey?: string, maxWaitTime?: number): Promise<PeerSession> {
155
+ async getAuthenticatedSession (identityKey?: string, maxWaitTime?: number): Promise<PeerSession> {
156
156
  if (!this.transport) {
157
157
  throw new Error('Peer transport is not connected!')
158
158
  }
@@ -175,7 +175,7 @@ export class Peer {
175
175
  * @param {(senderPublicKey: string, payload: number[]) => void} callback - The function to call when a general message is received.
176
176
  * @returns {number} The ID of the callback listener.
177
177
  */
178
- listenForGeneralMessages(callback: (senderPublicKey: string, payload: number[]) => void): number {
178
+ listenForGeneralMessages (callback: (senderPublicKey: string, payload: number[]) => void): number {
179
179
  const callbackID = this.callbackIdCounter++
180
180
  this.onGeneralMessageReceivedCallbacks.set(callbackID, callback)
181
181
  return callbackID
@@ -186,7 +186,7 @@ export class Peer {
186
186
  *
187
187
  * @param {number} callbackID - The ID of the callback to remove.
188
188
  */
189
- stopListeningForGeneralMessages(callbackID: number): void {
189
+ stopListeningForGeneralMessages (callbackID: number): void {
190
190
  this.onGeneralMessageReceivedCallbacks.delete(callbackID)
191
191
  }
192
192
 
@@ -196,7 +196,7 @@ export class Peer {
196
196
  * @param {(certs: VerifiableCertificate[]) => void} callback - The function to call when certificates are received.
197
197
  * @returns {number} The ID of the callback listener.
198
198
  */
199
- listenForCertificatesReceived(callback: (senderPublicKey: string, certs: VerifiableCertificate[]) => void): number {
199
+ listenForCertificatesReceived (callback: (senderPublicKey: string, certs: VerifiableCertificate[]) => void): number {
200
200
  const callbackID = this.callbackIdCounter++
201
201
  this.onCertificatesReceivedCallbacks.set(callbackID, callback)
202
202
  return callbackID
@@ -207,7 +207,7 @@ export class Peer {
207
207
  *
208
208
  * @param {number} callbackID - The ID of the certificates received callback to cancel.
209
209
  */
210
- stopListeningForCertificatesReceived(callbackID: number): void {
210
+ stopListeningForCertificatesReceived (callbackID: number): void {
211
211
  this.onCertificatesReceivedCallbacks.delete(callbackID)
212
212
  }
213
213
 
@@ -217,7 +217,7 @@ export class Peer {
217
217
  * @param {(requestedCertificates: RequestedCertificateSet) => void} callback - The function to call when a certificate request is received
218
218
  * @returns {number} The ID of the callback listener.
219
219
  */
220
- listenForCertificatesRequested(callback: (senderPublicKey: string, requestedCertificates: RequestedCertificateSet) => void): number {
220
+ listenForCertificatesRequested (callback: (senderPublicKey: string, requestedCertificates: RequestedCertificateSet) => void): number {
221
221
  const callbackID = this.callbackIdCounter++
222
222
  this.onCertificateRequestReceivedCallbacks.set(callbackID, callback)
223
223
  return callbackID
@@ -228,7 +228,7 @@ export class Peer {
228
228
  *
229
229
  * @param {number} callbackID - The ID of the requested certificates callback to cancel.
230
230
  */
231
- stopListeningForCertificatesRequested(callbackID: number): void {
231
+ stopListeningForCertificatesRequested (callbackID: number): void {
232
232
  this.onCertificateRequestReceivedCallbacks.delete(callbackID)
233
233
  }
234
234
 
@@ -239,7 +239,7 @@ export class Peer {
239
239
  * @param {string} [identityKey] - The identity public key of the peer.
240
240
  * @returns {Promise<string>} A promise that resolves to the session nonce.
241
241
  */
242
- private async initiateHandshake(identityKey?: string, maxWaitTime = 10000): Promise<string> {
242
+ private async initiateHandshake (identityKey?: string, maxWaitTime = 10000): Promise<string> {
243
243
  const sessionNonce = await createNonce(this.wallet) // Initial request nonce
244
244
  this.sessionManager.addSession({
245
245
  isAuthenticated: false,
@@ -265,7 +265,7 @@ export class Peer {
265
265
  * @param {string} sessionNonce - The session nonce created in the initial request.
266
266
  * @returns {Promise<string>} A promise that resolves with the session nonce when the initial response is received.
267
267
  */
268
- private async waitForInitialResponse(sessionNonce: string, maxWaitTime = 10000): Promise<string> {
268
+ private async waitForInitialResponse (sessionNonce: string, maxWaitTime = 10000): Promise<string> {
269
269
  return await new Promise((resolve, reject) => {
270
270
  const callbackID = this.listenForInitialResponse(sessionNonce, (sessionNonce) => {
271
271
  clearTimeout(timeoutHandle)
@@ -288,7 +288,7 @@ export class Peer {
288
288
  * @param {(sessionNonce: string) => void} callback - The callback to invoke when the initial response is received.
289
289
  * @returns {number} The ID of the callback listener.
290
290
  */
291
- private listenForInitialResponse(sessionNonce: string, callback: (sessionNonce: string) => void) {
291
+ private listenForInitialResponse (sessionNonce: string, callback: (sessionNonce: string) => void) {
292
292
  const callbackID = this.callbackIdCounter++
293
293
  this.onInitialResponseReceivedCallbacks.set(callbackID, { callback, sessionNonce })
294
294
  return callbackID
@@ -300,7 +300,7 @@ export class Peer {
300
300
  * @private
301
301
  * @param {number} callbackID - The ID of the callback to remove.
302
302
  */
303
- private stopListeningForInitialResponses(callbackID: number) {
303
+ private stopListeningForInitialResponses (callbackID: number) {
304
304
  this.onInitialResponseReceivedCallbacks.delete(callbackID)
305
305
  }
306
306
 
@@ -310,7 +310,7 @@ export class Peer {
310
310
  * @param {AuthMessage} message - The incoming message to process.
311
311
  * @returns {Promise<void>}
312
312
  */
313
- private async handleIncomingMessage(message: AuthMessage): Promise<void> {
313
+ private async handleIncomingMessage (message: AuthMessage): Promise<void> {
314
314
  if (!message.version || message.version !== AUTH_VERSION) {
315
315
  console.error(`Invalid message auth version! Received: ${message.version}, expected: ${AUTH_VERSION}`)
316
316
  return
@@ -343,7 +343,7 @@ export class Peer {
343
343
  * @param {AuthMessage} message - The incoming initial request message.
344
344
  * @returns {Promise<void>}
345
345
  */
346
- async processInitialRequest(message: AuthMessage) {
346
+ async processInitialRequest (message: AuthMessage) {
347
347
  if (!message.identityKey || !message.initialNonce) {
348
348
  throw new Error('Missing required fields in initialResponse message.')
349
349
  }
@@ -406,7 +406,7 @@ export class Peer {
406
406
  * @returns {Promise<void>}
407
407
  * @throws Will throw an error if nonce verification or signature verification fails.
408
408
  */
409
- private async processInitialResponse(message: AuthMessage) {
409
+ private async processInitialResponse (message: AuthMessage) {
410
410
  const validNonce = await verifyNonce(message.yourNonce, this.wallet)
411
411
  if (!validNonce) {
412
412
  throw new Error(`Initial response nonce verification failed from peer: ${message.identityKey}`)
@@ -478,7 +478,7 @@ export class Peer {
478
478
  * @param {AuthMessage} message - The certificate request message received from the peer.
479
479
  * @throws {Error} Throws an error if nonce verification fails, or the message signature is invalid.
480
480
  */
481
- private async processCertificateRequest(message: AuthMessage) {
481
+ private async processCertificateRequest (message: AuthMessage) {
482
482
  const validNonce = await verifyNonce(message.yourNonce, this.wallet)
483
483
  if (!validNonce) {
484
484
  throw new Error(`Unable to verify nonce for certificate request message from: ${message.identityKey}`)
@@ -520,7 +520,7 @@ export class Peer {
520
520
  *
521
521
  * @throws {Error} Throws an error if the peer session could not be authenticated or if message signing fails.
522
522
  */
523
- async sendCertificateResponse(
523
+ async sendCertificateResponse (
524
524
  verifierIdentityKey: string,
525
525
  certificates: VerifiableCertificate[]
526
526
  ) {
@@ -559,7 +559,7 @@ export class Peer {
559
559
  * @returns {Promise<void>}
560
560
  * @throws Will throw an error if nonce verification or signature verification fails.
561
561
  */
562
- private async processCertificateResponse(
562
+ private async processCertificateResponse (
563
563
  message: AuthMessage
564
564
  ) {
565
565
  const validNonce = await verifyNonce(message.yourNonce, this.wallet)
@@ -597,7 +597,7 @@ export class Peer {
597
597
  * @returns {Promise<void>}
598
598
  * @throws Will throw an error if nonce verification or signature verification fails.
599
599
  */
600
- private async processGeneralMessage(message: AuthMessage) {
600
+ private async processGeneralMessage (message: AuthMessage) {
601
601
  const validNonce = await verifyNonce(message.yourNonce, this.wallet)
602
602
  if (!validNonce) {
603
603
  throw new Error(`Unable to verify nonce for general message from: ${message.identityKey}`)
@@ -7,44 +7,8 @@ import { Utils, PrivateKey, SymmetricKey } from '../../../dist/cjs/src/primitive
7
7
  import { VerifiableCertificate, } from "../../../dist/cjs/src/auth/certificates/VerifiableCertificate.js"
8
8
  import { MasterCertificate } from '../../../dist/cjs/src/auth/certificates/MasterCertificate.js'
9
9
  import { getVerifiableCertificates } from '../../../dist/cjs/src/auth/utils/getVerifiableCertificates.js'
10
- import { Certificate } from "../../../dist/cjs/src/auth/certificates/index.js"
11
10
  jest.mock('../../../dist/cjs/src/auth/utils/getVerifiableCertificates.js')
12
11
 
13
- /**
14
- * A helper function to decrypt a VerifiableCertificate's fields using the provided wallets.
15
- */
16
- async function decryptCertificateFields(
17
- cert: VerifiableCertificate,
18
- localWallet: Wallet,
19
- counterpartyWallet: Wallet
20
- ): Promise<Record<string, string>> {
21
- const entries = await Promise.all(
22
- Object.entries(cert.keyring).map(async ([fieldName, encryptedKey]) => {
23
- // Decrypt the per-field symmetric key
24
- const { plaintext: masterFieldKey } = await localWallet.decrypt({
25
- ciphertext: Utils.toArray(encryptedKey, 'base64'),
26
- ...Certificate.getCertificateFieldEncryptionDetails(cert.serialNumber, fieldName),
27
- counterparty: (await counterpartyWallet.getPublicKey({ identityKey: true })).publicKey,
28
- })
29
-
30
- // Decrypt the actual field contents using the decrypted symmetric key
31
- try {
32
- const decryptedData = new SymmetricKey(masterFieldKey).decrypt(
33
- Utils.toArray(cert.fields[fieldName], 'base64')
34
- )
35
- return { key: fieldName, value: Utils.toUTF8(decryptedData as number[]) }
36
- } catch (_) {
37
- throw new Error(`Decryption of the "${fieldName}" field with its revelation key failed.`)
38
- }
39
- })
40
- )
41
-
42
- return entries.reduce((acc, { key, value }) => {
43
- acc[key] = value
44
- return acc
45
- }, {} as Record<string, string>)
46
- }
47
-
48
12
  class LocalTransport implements Transport {
49
13
  private peerTransport?: LocalTransport
50
14
  private onDataCallback?: (message: AuthMessage) => void
@@ -117,7 +81,15 @@ describe('Peer class mutual authentication and certificate exchange', () => {
117
81
  ): Promise<VerifiableCertificate> {
118
82
  const certifierWallet = new ProtoWallet(certifierPrivateKey)
119
83
 
120
- const keyringForVerifier = await masterCertificate.createKeyringForVerifier(wallet, verifierIdentityKey, fieldsToReveal)
84
+ const keyringForVerifier = await MasterCertificate.createKeyringForVerifier(
85
+ wallet,
86
+ certifierWallet.keyDeriver.identityKey,
87
+ verifierIdentityKey,
88
+ masterCertificate.fields,
89
+ fieldsToReveal,
90
+ masterCertificate.masterKeyring,
91
+ masterCertificate.serialNumber
92
+ )
121
93
  return new VerifiableCertificate(
122
94
  masterCertificate.type,
123
95
  masterCertificate.serialNumber,
@@ -125,8 +97,8 @@ describe('Peer class mutual authentication and certificate exchange', () => {
125
97
  masterCertificate.certifier,
126
98
  masterCertificate.revocationOutpoint,
127
99
  masterCertificate.fields,
128
- masterCertificate.signature,
129
- keyringForVerifier
100
+ keyringForVerifier,
101
+ masterCertificate.signature
130
102
  )
131
103
  }
132
104
 
@@ -234,7 +206,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
234
206
  if (certificatesReceivedByBob?.length !== 0) {
235
207
  certificatesReceivedByBob?.forEach(async cert => {
236
208
  // Decrypt to ensure it has the correct fields
237
- const decryptedFields = await decryptCertificateFields(cert, walletB, walletA)
209
+ const decryptedFields = await cert.decryptFields(walletB)
238
210
  if (cert.certifier !== 'bob') {
239
211
  console.log('Bob accepted the message:', Utils.toUTF8(payload))
240
212
  console.log('Decrypted fields:', decryptedFields)
@@ -279,7 +251,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
279
251
  alice.listenForCertificatesReceived(async (senderPublicKey, certificates) => {
280
252
  for (const cert of certificates) {
281
253
  // Decrypt Bob's certificate fields
282
- const decryptedFields = await decryptCertificateFields(cert, walletA, walletB)
254
+ const decryptedFields = await cert.decryptFields(walletA)
283
255
 
284
256
  // Check and use the decrypted fields
285
257
  if (Object.keys(decryptedFields).length !== 0 && decryptedFields.libraryCardNumber) {
@@ -342,7 +314,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
342
314
  if (certificates.length > 0) {
343
315
  // Decrypt to confirm
344
316
  for (const cert of certificates) {
345
- const decrypted = await decryptCertificateFields(cert, walletB, walletA)
317
+ const decrypted = await cert.decryptFields(walletB)
346
318
  console.log('Bob received additional certificates from Alice:', cert)
347
319
  console.log('Decrypted fields:', decrypted)
348
320
  }
@@ -384,7 +356,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
384
356
  bob.listenForCertificatesReceived(async (senderPublicKey, certificates) => {
385
357
  for (const cert of certificates) {
386
358
  // Decrypt Alice's certificate fields
387
- const decryptedFields = await decryptCertificateFields(cert, walletB, walletA)
359
+ const decryptedFields = await cert.decryptFields(walletB)
388
360
  if (decryptedFields.membershipStatus) {
389
361
  console.log(`Bob received Alice's membership status: ${decryptedFields.membershipStatus}`)
390
362
  bobAcceptedMembershipStatus()
@@ -451,7 +423,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
451
423
  const waitForAliceToAcceptBobDL = new Promise<void>((resolve) => {
452
424
  alice.listenForCertificatesReceived(async (senderPublicKey, certificates) => {
453
425
  for (const cert of certificates) {
454
- const decryptedFields = await decryptCertificateFields(cert, walletA, walletB)
426
+ const decryptedFields = await cert.decryptFields(walletA)
455
427
  if (decryptedFields.driversLicenseNumber) {
456
428
  console.log(`Alice received Bob's driver's license number: ${decryptedFields.driversLicenseNumber}`)
457
429
  aliceAcceptedBobDL()
@@ -464,7 +436,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
464
436
  const waitForBobToAcceptAliceDL = new Promise<void>((resolve) => {
465
437
  bob.listenForCertificatesReceived(async (senderPublicKey, certificates) => {
466
438
  for (const cert of certificates) {
467
- const decryptedFields = await decryptCertificateFields(cert, walletB, walletA)
439
+ const decryptedFields = await cert.decryptFields(walletB)
468
440
  if (decryptedFields.driversLicenseNumber) {
469
441
  console.log(`Bob received Alice's driver's license number: ${decryptedFields.driversLicenseNumber}`)
470
442
  bobAcceptedAliceDL()
@@ -544,7 +516,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
544
516
  const waitForAlicePartialCert = new Promise<void>((resolve) => {
545
517
  alice.listenForCertificatesReceived(async (senderPublicKey, certificates) => {
546
518
  for (const cert of certificates) {
547
- const decryptedFields = await decryptCertificateFields(cert, walletA, walletB)
519
+ const decryptedFields = await cert.decryptFields(walletA)
548
520
  if (decryptedFields.email || decryptedFields.name) {
549
521
  console.log(`Alice received Bob's certificate with fields: ${Object.keys(decryptedFields).join(', ')}`)
550
522
  aliceAcceptedPartialCert()
@@ -557,7 +529,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
557
529
  const waitForBobPartialCert = new Promise<void>((resolve) => {
558
530
  bob.listenForCertificatesReceived(async (senderPublicKey, certificates) => {
559
531
  for (const cert of certificates) {
560
- const decryptedFields = await decryptCertificateFields(cert, walletB, walletA)
532
+ const decryptedFields = await cert.decryptFields(walletB)
561
533
  if (decryptedFields.email || decryptedFields.name) {
562
534
  console.log(`Bob received Alice's certificate with fields: ${Object.keys(decryptedFields).join(', ')}`)
563
535
  bobAcceptedPartialCert()
@@ -43,9 +43,9 @@ export default class Certificate {
43
43
  revocationOutpoint: OutpointString
44
44
 
45
45
  /**
46
- * All the fields present in the certificate, with field names as keys and field values as strings.
46
+ * All the fields present in the certificate, with field names as keys and encrypted field values as Base64 strings.
47
47
  */
48
- fields: Record<CertificateFieldNameUnder50Bytes, string>
48
+ fields: Record<CertificateFieldNameUnder50Bytes, Base64String>
49
49
 
50
50
  /**
51
51
  * Certificate signature by the certifier's private key, DER encoded hex string.
@@ -258,7 +258,7 @@ export default class Certificate {
258
258
  * - `protocolID` (WalletProtocol): The protocol ID for certificate field encryption.
259
259
  * - `keyID` (string): A unique key identifier derived from the serial number and field name.
260
260
  */
261
- static getCertificateFieldEncryptionDetails(serialNumber: string, fieldName: string): { protocolID: WalletProtocol, keyID: string } {
261
+ static getCertificateFieldEncryptionDetails(fieldName: string, serialNumber?: string): { protocolID: WalletProtocol, keyID: string } {
262
262
  return { protocolID: [2, 'certificate field encryption'], keyID: `${serialNumber} ${fieldName}` }
263
263
  }
264
264
  }