@cheqd/did-provider-cheqd 3.7.0 → 4.0.0-develop.1

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 (75) hide show
  1. package/build/cjs/agent/ICheqd.d.ts +44 -2
  2. package/build/cjs/agent/ICheqd.d.ts.map +1 -1
  3. package/build/cjs/agent/ICheqd.js +451 -169
  4. package/build/cjs/agent/ICheqd.js.map +1 -1
  5. package/build/cjs/did-manager/cheqd-did-provider.d.ts +1 -2
  6. package/build/cjs/did-manager/cheqd-did-provider.d.ts.map +1 -1
  7. package/build/cjs/did-manager/cheqd-did-provider.js +5 -6
  8. package/build/cjs/did-manager/cheqd-did-provider.js.map +1 -1
  9. package/build/cjs/dkg-threshold/index.d.ts +1 -1
  10. package/build/cjs/dkg-threshold/index.d.ts.map +1 -1
  11. package/build/cjs/dkg-threshold/index.js +1 -1
  12. package/build/cjs/dkg-threshold/index.js.map +1 -1
  13. package/build/cjs/dkg-threshold/lit-protocol/v2.d.ts +95 -0
  14. package/build/cjs/dkg-threshold/lit-protocol/v2.d.ts.map +1 -0
  15. package/build/cjs/dkg-threshold/{lit-protocol.js → lit-protocol/v2.js} +39 -39
  16. package/build/cjs/dkg-threshold/lit-protocol/v2.js.map +1 -0
  17. package/build/cjs/dkg-threshold/{lit-protocol.d.ts → lit-protocol/v3.d.ts} +17 -17
  18. package/build/cjs/dkg-threshold/lit-protocol/v3.d.ts.map +1 -0
  19. package/build/cjs/dkg-threshold/lit-protocol/v3.js +231 -0
  20. package/build/cjs/dkg-threshold/lit-protocol/v3.js.map +1 -0
  21. package/build/cjs/utils/helpers.d.ts +5 -0
  22. package/build/cjs/utils/helpers.d.ts.map +1 -1
  23. package/build/cjs/utils/helpers.js +38 -1
  24. package/build/cjs/utils/helpers.js.map +1 -1
  25. package/build/esm/agent/ICheqd.d.ts +44 -2
  26. package/build/esm/agent/ICheqd.d.ts.map +1 -1
  27. package/build/esm/agent/ICheqd.js +425 -143
  28. package/build/esm/agent/ICheqd.js.map +1 -1
  29. package/build/esm/did-manager/cheqd-did-provider.d.ts +1 -2
  30. package/build/esm/did-manager/cheqd-did-provider.d.ts.map +1 -1
  31. package/build/esm/did-manager/cheqd-did-provider.js +3 -4
  32. package/build/esm/did-manager/cheqd-did-provider.js.map +1 -1
  33. package/build/esm/dkg-threshold/index.d.ts +1 -1
  34. package/build/esm/dkg-threshold/index.d.ts.map +1 -1
  35. package/build/esm/dkg-threshold/index.js +1 -1
  36. package/build/esm/dkg-threshold/index.js.map +1 -1
  37. package/build/esm/dkg-threshold/lit-protocol/v2.d.ts +95 -0
  38. package/build/esm/dkg-threshold/lit-protocol/v2.d.ts.map +1 -0
  39. package/build/esm/dkg-threshold/{lit-protocol.js → lit-protocol/v2.js} +31 -31
  40. package/build/esm/dkg-threshold/lit-protocol/v2.js.map +1 -0
  41. package/build/esm/dkg-threshold/{lit-protocol.d.ts → lit-protocol/v3.d.ts} +17 -17
  42. package/build/esm/dkg-threshold/lit-protocol/v3.d.ts.map +1 -0
  43. package/build/esm/dkg-threshold/lit-protocol/v3.js +227 -0
  44. package/build/esm/dkg-threshold/lit-protocol/v3.js.map +1 -0
  45. package/build/esm/utils/helpers.d.ts +5 -0
  46. package/build/esm/utils/helpers.d.ts.map +1 -1
  47. package/build/esm/utils/helpers.js +33 -0
  48. package/build/esm/utils/helpers.js.map +1 -1
  49. package/build/tsconfig.cjs.tsbuildinfo +1 -1
  50. package/build/tsconfig.esm.tsbuildinfo +1 -1
  51. package/build/tsconfig.types.tsbuildinfo +1 -1
  52. package/build/types/agent/ICheqd.d.ts +44 -2
  53. package/build/types/agent/ICheqd.d.ts.map +1 -1
  54. package/build/types/did-manager/cheqd-did-provider.d.ts +1 -2
  55. package/build/types/did-manager/cheqd-did-provider.d.ts.map +1 -1
  56. package/build/types/dkg-threshold/index.d.ts +1 -1
  57. package/build/types/dkg-threshold/index.d.ts.map +1 -1
  58. package/build/types/dkg-threshold/lit-protocol/v2.d.ts +95 -0
  59. package/build/types/dkg-threshold/lit-protocol/v2.d.ts.map +1 -0
  60. package/build/types/dkg-threshold/{lit-protocol.d.ts → lit-protocol/v3.d.ts} +17 -17
  61. package/build/types/dkg-threshold/lit-protocol/v3.d.ts.map +1 -0
  62. package/build/types/utils/helpers.d.ts +5 -0
  63. package/build/types/utils/helpers.d.ts.map +1 -1
  64. package/package.json +5 -3
  65. package/src/agent/ICheqd.ts +970 -202
  66. package/src/did-manager/cheqd-did-provider.ts +3 -4
  67. package/src/dkg-threshold/index.ts +1 -1
  68. package/src/dkg-threshold/lit-protocol/v2.ts +287 -0
  69. package/src/dkg-threshold/{lit-protocol.ts → lit-protocol/v3.ts} +114 -45
  70. package/src/utils/helpers.ts +45 -0
  71. package/build/cjs/dkg-threshold/lit-protocol.d.ts.map +0 -1
  72. package/build/cjs/dkg-threshold/lit-protocol.js.map +0 -1
  73. package/build/esm/dkg-threshold/lit-protocol.d.ts.map +0 -1
  74. package/build/esm/dkg-threshold/lit-protocol.js.map +0 -1
  75. package/build/types/dkg-threshold/lit-protocol.d.ts.map +0 -1
@@ -10,9 +10,10 @@ import { StatusList } from '@digitalbazaar/vc-status-list';
10
10
  import { v4 } from 'uuid';
11
11
  import fs from 'fs';
12
12
  import Debug from 'debug';
13
- import { LitCompatibleCosmosChains, LitProtocol, } from '../dkg-threshold/lit-protocol.js';
14
- import { blobToHexString, randomFromRange, toBlob } from '../utils/helpers.js';
13
+ import { LitCompatibleCosmosChains, LitProtocol, } from '../dkg-threshold/lit-protocol/v3.js';
14
+ import { blobToHexString, getEncodedList, isEncodedList, randomFromRange, safeDeserialise, toBlob, } from '../utils/helpers.js';
15
15
  import { DefaultResolverUrl } from '../did-manager/cheqd-did-resolver.js';
16
+ import { LitNetworksV2, LitProtocolV2 } from '../dkg-threshold/lit-protocol/v2.js';
16
17
  const debug = Debug('veramo:did-provider-cheqd');
17
18
  export const AccessControlConditionTypes = {
18
19
  timelockPayment: 'timelockPayment',
@@ -653,6 +654,8 @@ export class Cheqd {
653
654
  // construct data and metadata tuple
654
655
  const data = args.encrypted
655
656
  ? await (async function (that) {
657
+ // encrypt bitstring - case: symmetric
658
+ const { encryptedString: symmetricEncryptionCiphertext, symmetricKey } = await LitProtocol.encryptDirect(fromString(bitstring, args?.statusListEncoding || DefaultStatusList2021Encodings.base64url));
656
659
  // instantiate dkg-threshold client, in which case lit-protocol is used
657
660
  const lit = await LitProtocol.create({
658
661
  chain: args?.dkgOptions?.chain || that.didProvider.dkgOptions.chain,
@@ -671,8 +674,10 @@ export class Cheqd {
671
674
  throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
672
675
  }
673
676
  }));
674
- // encrypt bitstring
675
- const { encryptedString, encryptedSymmetricKey, symmetricKey } = await lit.encrypt(bitstring, unifiedAccessControlConditions, true);
677
+ // encrypt bitstring - case: threshold
678
+ const { encryptedString: thresholdEncryptionCiphertext, stringHash } = await lit.encrypt(fromString(bitstring, args?.statusListEncoding || DefaultStatusList2021Encodings.base64url), unifiedAccessControlConditions);
679
+ // construct encoded list
680
+ const encodedList = `${await blobToHexString(symmetricEncryptionCiphertext)}-${toString(thresholdEncryptionCiphertext, 'hex')}`;
676
681
  // return result tuple
677
682
  switch (args.statusPurpose) {
678
683
  case DefaultStatusList2021StatusPurposeTypes.revocation:
@@ -680,7 +685,7 @@ export class Cheqd {
680
685
  {
681
686
  StatusList2021: {
682
687
  statusPurpose: args.statusPurpose,
683
- encodedList: await blobToHexString(encryptedString),
688
+ encodedList,
684
689
  validFrom: new Date().toISOString(),
685
690
  validUntil: args?.validUntil,
686
691
  },
@@ -688,14 +693,15 @@ export class Cheqd {
688
693
  type: DefaultStatusList2021ResourceTypes.revocation,
689
694
  encrypted: true,
690
695
  encoding: args?.statusListEncoding || DefaultStatusList2021Encodings.base64url,
691
- encryptedSymmetricKey,
696
+ statusListHash: stringHash,
692
697
  paymentConditions: args.paymentConditions,
693
698
  },
694
699
  },
695
700
  {
701
+ symmetricEncryptionCiphertext: await blobToHexString(symmetricEncryptionCiphertext),
702
+ thresholdEncryptionCiphertext: toString(thresholdEncryptionCiphertext, 'hex'),
703
+ stringHash,
696
704
  symmetricKey: toString(symmetricKey, 'hex'),
697
- encryptedSymmetricKey,
698
- encryptedString: await blobToHexString(encryptedString),
699
705
  },
700
706
  ];
701
707
  case DefaultStatusList2021StatusPurposeTypes.suspension:
@@ -703,7 +709,7 @@ export class Cheqd {
703
709
  {
704
710
  StatusList2021: {
705
711
  statusPurpose: args.statusPurpose,
706
- encodedList: await blobToHexString(encryptedString),
712
+ encodedList,
707
713
  validFrom: new Date().toISOString(),
708
714
  validUntil: args?.validUntil,
709
715
  },
@@ -711,14 +717,15 @@ export class Cheqd {
711
717
  type: DefaultStatusList2021ResourceTypes.suspension,
712
718
  encrypted: true,
713
719
  encoding: args?.statusListEncoding || DefaultStatusList2021Encodings.base64url,
714
- encryptedSymmetricKey,
720
+ statusListHash: stringHash,
715
721
  paymentConditions: args.paymentConditions,
716
722
  },
717
723
  },
718
724
  {
725
+ symmetricEncryptionCiphertext: await blobToHexString(symmetricEncryptionCiphertext),
726
+ thresholdEncryptionCiphertext: toString(thresholdEncryptionCiphertext, 'hex'),
727
+ stringHash,
719
728
  symmetricKey: toString(symmetricKey, 'hex'),
720
- encryptedSymmetricKey,
721
- encryptedString: await blobToHexString(encryptedString),
722
729
  },
723
730
  ];
724
731
  default:
@@ -790,7 +797,7 @@ export class Cheqd {
790
797
  },
791
798
  }),
792
799
  encrypted: args.encrypted,
793
- symmetricKey: args?.returnSymmetricKey ? data[1]?.symmetricKey : undefined,
800
+ symmetricKey: args.encrypted && args.returnSymmetricKey ? data[1]?.symmetricKey : undefined,
794
801
  };
795
802
  }
796
803
  async BroadcastStatusList2021(args, context) {
@@ -916,8 +923,6 @@ export class Cheqd {
916
923
  switch (args?.bitstringEncoding) {
917
924
  case 'base64url':
918
925
  return encoded;
919
- case 'base64':
920
- return toString(fromString(encoded, 'base64url'), 'base64');
921
926
  case 'hex':
922
927
  return toString(fromString(encoded, 'base64url'), 'hex');
923
928
  default:
@@ -933,12 +938,12 @@ export class Cheqd {
933
938
  ? args.issuanceOptions.credential.issuer.id
934
939
  : args.issuanceOptions.credential.issuer;
935
940
  // generate status list credential
936
- const statusListCredential = `${DefaultResolverUrl}${issuer}?resourceName=${args.statusOptions.statusListName}&resourceType=StatusList2021Revocation`;
941
+ const statusListCredential = `${DefaultResolverUrl}${issuer}?resourceName=${args.statusOptions.statusListName}&resourceType=${DefaultStatusList2021ResourceTypes.revocation}`;
937
942
  // construct credential status
938
943
  const credentialStatus = {
939
944
  id: `${statusListCredential}#${statusListIndex}`,
940
945
  type: 'StatusList2021Entry',
941
- statusPurpose: 'revocation',
946
+ statusPurpose: DefaultStatusList2021StatusPurposeTypes.revocation,
942
947
  statusListIndex: `${statusListIndex}`,
943
948
  };
944
949
  // add credential status to credential
@@ -975,12 +980,12 @@ export class Cheqd {
975
980
  ? args.issuanceOptions.credential.issuer.id
976
981
  : args.issuanceOptions.credential.issuer;
977
982
  // generate status list credential
978
- const statusListCredential = `${DefaultResolverUrl}${issuer}?resourceName=${args.statusOptions.statusListName}&resourceType=StatusList2021Suspension`;
983
+ const statusListCredential = `${DefaultResolverUrl}${issuer}?resourceName=${args.statusOptions.statusListName}&resourceType=${DefaultStatusList2021ResourceTypes.suspension}`;
979
984
  // construct credential status
980
985
  const credentialStatus = {
981
986
  id: `${statusListCredential}#${statusListIndex}`,
982
987
  type: 'StatusList2021Entry',
983
- statusPurpose: 'suspension',
988
+ statusPurpose: DefaultStatusList2021StatusPurposeTypes.suspension,
984
989
  statusListIndex: `${statusListIndex}`,
985
990
  };
986
991
  // add credential status to credential
@@ -1034,14 +1039,16 @@ export class Cheqd {
1034
1039
  args.dkgOptions ||= this.didProvider.dkgOptions;
1035
1040
  // verify credential status
1036
1041
  switch (credential.credentialStatus?.statusPurpose) {
1037
- case 'revocation':
1038
- if (await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }))
1039
- return { ...verificationResult, revoked: true };
1040
- return { ...verificationResult, revoked: false };
1041
- case 'suspension':
1042
- if (await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }))
1043
- return { ...verificationResult, suspended: true };
1044
- return { ...verificationResult, suspended: false };
1042
+ case DefaultStatusList2021StatusPurposeTypes.revocation:
1043
+ return {
1044
+ ...verificationResult,
1045
+ revoked: await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }),
1046
+ };
1047
+ case DefaultStatusList2021StatusPurposeTypes.suspension:
1048
+ return {
1049
+ ...verificationResult,
1050
+ suspended: await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }),
1051
+ };
1045
1052
  default:
1046
1053
  throw new Error(`[did-provider-cheqd]: verify credential: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
1047
1054
  }
@@ -1077,14 +1084,16 @@ export class Cheqd {
1077
1084
  // define dkg options, if provided
1078
1085
  args.dkgOptions ||= this.didProvider.dkgOptions;
1079
1086
  switch (credential.credentialStatus?.statusPurpose) {
1080
- case 'revocation':
1081
- if (await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }))
1082
- return { ...verificationResult, revoked: true };
1083
- break;
1084
- case 'suspension':
1085
- if (await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }))
1086
- return { ...verificationResult, suspended: true };
1087
- break;
1087
+ case DefaultStatusList2021StatusPurposeTypes.revocation:
1088
+ return {
1089
+ ...verificationResult,
1090
+ revoked: await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }),
1091
+ };
1092
+ case DefaultStatusList2021StatusPurposeTypes.suspension:
1093
+ return {
1094
+ ...verificationResult,
1095
+ suspended: await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }),
1096
+ };
1088
1097
  default:
1089
1098
  throw new Error(`[did-provider-cheqd]: verify presentation: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
1090
1099
  }
@@ -1121,9 +1130,9 @@ export class Cheqd {
1121
1130
  if (!args.statusOptions.statusListIndex)
1122
1131
  throw new Error('[did-provider-cheqd]: check status: statusOptions.statusListIndex is required');
1123
1132
  // generate resource type
1124
- const resourceType = args.statusOptions.statusPurpose === 'revocation'
1125
- ? 'StatusList2021Revocation'
1126
- : 'StatusList2021Suspension';
1133
+ const resourceType = args.statusOptions.statusPurpose === DefaultStatusList2021StatusPurposeTypes.revocation
1134
+ ? DefaultStatusList2021ResourceTypes.revocation
1135
+ : DefaultStatusList2021ResourceTypes.suspension;
1127
1136
  // construct status list credential
1128
1137
  const statusListCredential = `${DefaultResolverUrl}${args.statusOptions.issuerDid}?resourceName=${args.statusOptions.statusListName}&resourceType=${resourceType}`;
1129
1138
  // construct credential status
@@ -1155,14 +1164,10 @@ export class Cheqd {
1155
1164
  // define dkg options, if provided
1156
1165
  args.dkgOptions ||= this.didProvider.dkgOptions;
1157
1166
  switch (credential.credentialStatus?.statusPurpose) {
1158
- case 'revocation':
1159
- if (await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }))
1160
- return { revoked: true };
1161
- return { revoked: false };
1162
- case 'suspension':
1163
- if (await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }))
1164
- return { suspended: true };
1165
- return { suspended: false };
1167
+ case DefaultStatusList2021StatusPurposeTypes.revocation:
1168
+ return { revoked: await Cheqd.checkRevoked(credential, { ...args.options, topArgs: args }) };
1169
+ case DefaultStatusList2021StatusPurposeTypes.suspension:
1170
+ return { suspended: await Cheqd.checkSuspended(credential, { ...args.options, topArgs: args }) };
1166
1171
  default:
1167
1172
  throw new Error(`[did-provider-cheqd]: check status: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
1168
1173
  }
@@ -1194,7 +1199,7 @@ export class Cheqd {
1194
1199
  if (!args.revocationOptions.statusListIndex)
1195
1200
  throw new Error('[did-provider-cheqd]: revocation: revocationOptions.statusListIndex is required');
1196
1201
  // construct status list credential
1197
- const statusListCredential = `${DefaultResolverUrl}${args.revocationOptions.issuerDid}?resourceName=${args.revocationOptions.statusListName}&resourceType=StatusList2021Revocation`;
1202
+ const statusListCredential = `${DefaultResolverUrl}${args.revocationOptions.issuerDid}?resourceName=${args.revocationOptions.statusListName}&resourceType=${DefaultStatusList2021ResourceTypes.revocation}`;
1198
1203
  // construct credential status
1199
1204
  args.credential = {
1200
1205
  '@context': [],
@@ -1203,7 +1208,7 @@ export class Cheqd {
1203
1208
  credentialStatus: {
1204
1209
  id: `${statusListCredential}#${args.revocationOptions.statusListIndex}`,
1205
1210
  type: 'StatusList2021Entry',
1206
- statusPurpose: 'revocation',
1211
+ statusPurpose: DefaultStatusList2021StatusPurposeTypes.revocation,
1207
1212
  statusListIndex: `${args.revocationOptions.statusListIndex}`,
1208
1213
  },
1209
1214
  issuanceDate: '',
@@ -1216,7 +1221,7 @@ export class Cheqd {
1216
1221
  // if jwt credential, decode it
1217
1222
  const credential = typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
1218
1223
  // validate status purpose
1219
- if (credential.credentialStatus?.statusPurpose !== 'revocation') {
1224
+ if (credential.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.revocation) {
1220
1225
  throw new Error(`[did-provider-cheqd]: revocation: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
1221
1226
  }
1222
1227
  // validate args in pairs - case: statusListFile and statusList
@@ -1297,7 +1302,7 @@ export class Cheqd {
1297
1302
  !args.revocationOptions.statusListIndices.every((index) => !isNaN(+index)))
1298
1303
  throw new Error('[did-provider-cheqd]: revocation: revocationOptions.statusListIndex is required and must be an array of indices');
1299
1304
  // construct status list credential
1300
- const statusListCredential = `${DefaultResolverUrl}${args.revocationOptions.issuerDid}?resourceName=${args.revocationOptions.statusListName}&resourceType=StatusList2021Revocation`;
1305
+ const statusListCredential = `${DefaultResolverUrl}${args.revocationOptions.issuerDid}?resourceName=${args.revocationOptions.statusListName}&resourceType=${DefaultStatusList2021ResourceTypes.revocation}`;
1301
1306
  // construct credential status
1302
1307
  args.credentials = args.revocationOptions.statusListIndices.map((index) => ({
1303
1308
  '@context': [],
@@ -1306,7 +1311,7 @@ export class Cheqd {
1306
1311
  credentialStatus: {
1307
1312
  id: `${statusListCredential}#${index}`,
1308
1313
  type: 'StatusList2021Entry',
1309
- statusPurpose: 'revocation',
1314
+ statusPurpose: DefaultStatusList2021StatusPurposeTypes.revocation,
1310
1315
  statusListIndex: `${index}`,
1311
1316
  },
1312
1317
  issuanceDate: '',
@@ -1385,7 +1390,7 @@ export class Cheqd {
1385
1390
  if (!args.suspensionOptions.statusListIndex)
1386
1391
  throw new Error('[did-provider-cheqd]: suspension: suspensionOptions.statusListIndex is required');
1387
1392
  // construct status list credential
1388
- const statusListCredential = `${DefaultResolverUrl}${args.suspensionOptions.issuerDid}?resourceName=${args.suspensionOptions.statusListName}&resourceType=StatusList2021Suspension`;
1393
+ const statusListCredential = `${DefaultResolverUrl}${args.suspensionOptions.issuerDid}?resourceName=${args.suspensionOptions.statusListName}&resourceType=${DefaultStatusList2021ResourceTypes.suspension}`;
1389
1394
  // construct credential status
1390
1395
  args.credential = {
1391
1396
  '@context': [],
@@ -1394,7 +1399,7 @@ export class Cheqd {
1394
1399
  credentialStatus: {
1395
1400
  id: `${statusListCredential}#${args.suspensionOptions.statusListIndex}`,
1396
1401
  type: 'StatusList2021Entry',
1397
- statusPurpose: 'suspension',
1402
+ statusPurpose: DefaultStatusList2021StatusPurposeTypes.suspension,
1398
1403
  statusListIndex: `${args.suspensionOptions.statusListIndex}`,
1399
1404
  },
1400
1405
  issuanceDate: '',
@@ -1407,7 +1412,7 @@ export class Cheqd {
1407
1412
  // if jwt credential, decode it
1408
1413
  const credential = typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
1409
1414
  // validate status purpose
1410
- if (credential.credentialStatus?.statusPurpose !== 'suspension') {
1415
+ if (credential.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.suspension) {
1411
1416
  throw new Error(`[did-provider-cheqd]: suspension: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
1412
1417
  }
1413
1418
  // validate args in pairs - case: statusListFile and statusList
@@ -1488,7 +1493,7 @@ export class Cheqd {
1488
1493
  !args.suspensionOptions.statusListIndices.every((index) => !isNaN(+index)))
1489
1494
  throw new Error('[did-provider-cheqd]: suspension: suspensionOptions.statusListIndex is required and must be an array of indices');
1490
1495
  // construct status list credential
1491
- const statusListCredential = `${DefaultResolverUrl}${args.suspensionOptions.issuerDid}?resourceName=${args.suspensionOptions.statusListName}&resourceType=StatusList2021Suspension`;
1496
+ const statusListCredential = `${DefaultResolverUrl}${args.suspensionOptions.issuerDid}?resourceName=${args.suspensionOptions.statusListName}&resourceType=${DefaultStatusList2021ResourceTypes.suspension}`;
1492
1497
  // construct credential status
1493
1498
  args.credentials = args.suspensionOptions.statusListIndices.map((index) => ({
1494
1499
  '@context': [],
@@ -1497,7 +1502,7 @@ export class Cheqd {
1497
1502
  credentialStatus: {
1498
1503
  id: `${statusListCredential}#${index}`,
1499
1504
  type: 'StatusList2021Entry',
1500
- statusPurpose: 'suspension',
1505
+ statusPurpose: DefaultStatusList2021StatusPurposeTypes.suspension,
1501
1506
  statusListIndex: `${index}`,
1502
1507
  },
1503
1508
  issuanceDate: '',
@@ -1576,7 +1581,7 @@ export class Cheqd {
1576
1581
  if (!args.unsuspensionOptions.statusListIndex)
1577
1582
  throw new Error('[did-provider-cheqd]: unsuspension: unsuspensionOptions.statusListIndex is required');
1578
1583
  // construct status list credential
1579
- const statusListCredential = `${DefaultResolverUrl}${args.unsuspensionOptions.issuerDid}?resourceName=${args.unsuspensionOptions.statusListName}&resourceType=StatusList2021Suspension`;
1584
+ const statusListCredential = `${DefaultResolverUrl}${args.unsuspensionOptions.issuerDid}?resourceName=${args.unsuspensionOptions.statusListName}&resourceType=${DefaultStatusList2021ResourceTypes.suspension}`;
1580
1585
  // construct credential status
1581
1586
  args.credential = {
1582
1587
  '@context': [],
@@ -1585,7 +1590,7 @@ export class Cheqd {
1585
1590
  credentialStatus: {
1586
1591
  id: `${statusListCredential}#${args.unsuspensionOptions.statusListIndex}`,
1587
1592
  type: 'StatusList2021Entry',
1588
- statusPurpose: 'suspension',
1593
+ statusPurpose: DefaultStatusList2021StatusPurposeTypes.suspension,
1589
1594
  statusListIndex: `${args.unsuspensionOptions.statusListIndex}`,
1590
1595
  },
1591
1596
  issuanceDate: '',
@@ -1598,7 +1603,7 @@ export class Cheqd {
1598
1603
  // if jwt credential, decode it
1599
1604
  const credential = typeof args.credential === 'string' ? await Cheqd.decodeCredentialJWT(args.credential) : args.credential;
1600
1605
  // validate status purpose
1601
- if (credential.credentialStatus?.statusPurpose !== 'suspension') {
1606
+ if (credential.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.suspension) {
1602
1607
  throw new Error(`[did-provider-cheqd]: suspension: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
1603
1608
  }
1604
1609
  // validate args in pairs - case: statusListFile and statusList
@@ -1679,7 +1684,7 @@ export class Cheqd {
1679
1684
  !args.unsuspensionOptions.statusListIndices.every((index) => !isNaN(+index)))
1680
1685
  throw new Error('[did-provider-cheqd]: unsuspension: unsuspensionOptions.statusListIndex is required and must be an array of indices');
1681
1686
  // construct status list credential
1682
- const statusListCredential = `${DefaultResolverUrl}${args.unsuspensionOptions.issuerDid}?resourceName=${args.unsuspensionOptions.statusListName}&resourceType=StatusList2021Suspension`;
1687
+ const statusListCredential = `${DefaultResolverUrl}${args.unsuspensionOptions.issuerDid}?resourceName=${args.unsuspensionOptions.statusListName}&resourceType=${DefaultStatusList2021ResourceTypes.suspension}`;
1683
1688
  // construct credential status
1684
1689
  args.credentials = args.unsuspensionOptions.statusListIndices.map((index) => ({
1685
1690
  '@context': [],
@@ -1688,7 +1693,7 @@ export class Cheqd {
1688
1693
  credentialStatus: {
1689
1694
  id: `${statusListCredential}#${index}`,
1690
1695
  type: 'StatusList2021Entry',
1691
- statusPurpose: 'suspension',
1696
+ statusPurpose: DefaultStatusList2021StatusPurposeTypes.suspension,
1692
1697
  statusListIndex: `${index}`,
1693
1698
  },
1694
1699
  issuanceDate: '',
@@ -1956,7 +1961,7 @@ export class Cheqd {
1956
1961
  static async revokeCredential(credential, options) {
1957
1962
  try {
1958
1963
  // validate status purpose
1959
- if (credential?.credentialStatus?.statusPurpose !== 'revocation')
1964
+ if (credential?.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.revocation)
1960
1965
  throw new Error('[did-provider-cheqd]: revocation: Invalid status purpose');
1961
1966
  // fetch status list 2021
1962
1967
  const publishedList = (await Cheqd.fetchStatusList2021(credential));
@@ -1971,10 +1976,17 @@ export class Cheqd {
1971
1976
  return publishedList.metadata.encoding === 'base64url'
1972
1977
  ? publishedList.StatusList2021.encodedList
1973
1978
  : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
1979
+ // decrypt + return bitstring, if qualified for migration
1980
+ if (publishedList.metadata.encryptedSymmetricKey)
1981
+ return await LitProtocolV2.decryptDirect(await toBlob(fromString(publishedList.StatusList2021
1982
+ .encodedList, 'hex')), fromString(options?.topArgs?.symmetricKey, 'hex'));
1983
+ // validate encoded list
1984
+ if (!isEncodedList(publishedList.StatusList2021.encodedList))
1985
+ throw new Error('[did-provider-cheqd]: revocation: Invalid encoded list');
1974
1986
  // otherwise, decrypt and return raw bitstring
1975
- const scopedRawBlob = await toBlob(fromString(publishedList.StatusList2021.encodedList, 'hex'));
1987
+ const scopedRawBlob = await toBlob(fromString(getEncodedList(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
1976
1988
  // decrypt
1977
- return await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
1989
+ return toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
1978
1990
  })()
1979
1991
  : await (async function () {
1980
1992
  // transcode to base64url, if needed
@@ -1998,7 +2010,7 @@ export class Cheqd {
1998
2010
  // otherwise, decrypt and return bitstring
1999
2011
  const scopedRawBlob = await toBlob(await Cheqd.getFile(options.statusListFile));
2000
2012
  // decrypt
2001
- const decrypted = await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
2013
+ const decrypted = toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
2002
2014
  // validate against published list
2003
2015
  if (decrypted !== publishedListTranscoded)
2004
2016
  throw new Error('[did-provider-cheqd]: revocation: statusListFile does not match published status list 2021');
@@ -2017,7 +2029,7 @@ export class Cheqd {
2017
2029
  const statusList = await StatusList.decode({ encodedList: statusList2021 });
2018
2030
  // early exit, if credential is already revoked
2019
2031
  if (statusList.getStatus(Number(credential.credentialStatus.statusListIndex)))
2020
- return { revoked: false };
2032
+ return { revoked: true };
2021
2033
  // update revocation status
2022
2034
  statusList.setStatus(Number(credential.credentialStatus.statusListIndex), true);
2023
2035
  // set in-memory status list ref
@@ -2079,6 +2091,8 @@ export class Cheqd {
2079
2091
  !topArgs?.dkgOptions?.network) {
2080
2092
  throw new Error('[did-provider-cheqd]: dkgOptions is required');
2081
2093
  }
2094
+ // encrypt bitstring - case: symmetric
2095
+ const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await LitProtocol.encryptDirect(fromString(bitstring, 'base64url'));
2082
2096
  // instantiate dkg-threshold client, in which case lit-protocol is used
2083
2097
  const lit = await LitProtocol.create({
2084
2098
  chain: topArgs?.dkgOptions?.chain,
@@ -2129,13 +2143,15 @@ export class Cheqd {
2129
2143
  topArgs.paymentConditions,
2130
2144
  ];
2131
2145
  })();
2132
- // encrypt bitstring
2133
- const { encryptedString, encryptedSymmetricKey, symmetricKey } = await lit.encrypt(bitstring, unifiedAccessControlConditionsTuple[0], true);
2146
+ // encrypt bitstring - case: threshold
2147
+ const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt(fromString(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
2148
+ // construct encoded list
2149
+ const encodedList = `${await blobToHexString(symmetricEncryptionCiphertext)}-${toString(thresholdEncryptionCiphertext, 'hex')}`;
2134
2150
  // define status list content
2135
2151
  const content = {
2136
2152
  StatusList2021: {
2137
2153
  statusPurpose: publishedList.StatusList2021.statusPurpose,
2138
- encodedList: await blobToHexString(encryptedString),
2154
+ encodedList,
2139
2155
  validFrom: publishedList.StatusList2021.validFrom,
2140
2156
  validUntil: options?.publishOptions?.statusListValidUntil ||
2141
2157
  publishedList.StatusList2021.validUntil,
@@ -2144,7 +2160,11 @@ export class Cheqd {
2144
2160
  type: publishedList.metadata.type,
2145
2161
  encrypted: true,
2146
2162
  encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
2147
- encryptedSymmetricKey,
2163
+ statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
2164
+ ? symmetricEncryptionStringHash
2165
+ : (function () {
2166
+ throw new Error('[did-provider-cheqd]: revocation: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
2167
+ })(),
2148
2168
  paymentConditions: unifiedAccessControlConditionsTuple[1],
2149
2169
  },
2150
2170
  };
@@ -2152,9 +2172,10 @@ export class Cheqd {
2152
2172
  return [
2153
2173
  await Cheqd.publishStatusList2021(fromString(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
2154
2174
  {
2155
- encryptedString,
2156
- encryptedSymmetricKey,
2157
- symmetricKey: toString(symmetricKey, 'hex'),
2175
+ symmetricEncryptionCiphertext,
2176
+ thresholdEncryptionCiphertext,
2177
+ stringHash: symmetricEncryptionStringHash,
2178
+ symmetricKey,
2158
2179
  },
2159
2180
  ];
2160
2181
  })()
@@ -2218,7 +2239,7 @@ export class Cheqd {
2218
2239
  ? (await Cheqd.fetchStatusList2021(credential))
2219
2240
  : undefined,
2220
2241
  symmetricKey: topArgs?.returnSymmetricKey
2221
- ? published?.[1]?.symmetricKey
2242
+ ? toString(published?.[1]?.symmetricKey, 'hex')
2222
2243
  : undefined,
2223
2244
  resourceMetadata: topArgs?.returnStatusListMetadata
2224
2245
  ? await Cheqd.fetchStatusList2021Metadata(credential)
@@ -2250,7 +2271,7 @@ export class Cheqd {
2250
2271
  .filter((value, index, self) => self.indexOf(value) !== index).length > 0)
2251
2272
  throw new Error('[did-provider-cheqd]: revocation: Credentials must have unique status list index');
2252
2273
  // validate credentials - case: status purpose
2253
- if (!credentials.every((credential) => credential.credentialStatus?.statusPurpose === 'revocation'))
2274
+ if (!credentials.every((credential) => credential.credentialStatus?.statusPurpose === DefaultStatusList2021StatusPurposeTypes.revocation))
2254
2275
  throw new Error('[did-provider-cheqd]: revocation: Invalid status purpose');
2255
2276
  // validate credentials - case: status list id
2256
2277
  const remote = credentials[0].credentialStatus?.id
@@ -2282,10 +2303,17 @@ export class Cheqd {
2282
2303
  return publishedList.metadata.encoding === 'base64url'
2283
2304
  ? publishedList.StatusList2021.encodedList
2284
2305
  : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
2306
+ // decrypt + return bitstring, if qualified for migration
2307
+ if (publishedList.metadata.encryptedSymmetricKey)
2308
+ return await LitProtocolV2.decryptDirect(await toBlob(fromString(publishedList.StatusList2021
2309
+ .encodedList, 'hex')), fromString(options?.topArgs?.symmetricKey, 'hex'));
2310
+ // validate encoded list
2311
+ if (!isEncodedList(publishedList.StatusList2021.encodedList))
2312
+ throw new Error('[did-provider-cheqd]: revocation: Invalid encoded list');
2285
2313
  // otherwise, decrypt and return raw bitstring
2286
- const scopedRawBlob = await toBlob(fromString(publishedList.StatusList2021.encodedList, 'hex'));
2314
+ const scopedRawBlob = await toBlob(fromString(getEncodedList(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
2287
2315
  // decrypt
2288
- return await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
2316
+ return toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
2289
2317
  })()
2290
2318
  : await (async function () {
2291
2319
  // transcode to base64url, if needed
@@ -2309,7 +2337,7 @@ export class Cheqd {
2309
2337
  // otherwise, decrypt and return bitstring
2310
2338
  const scopedRawBlob = await toBlob(await Cheqd.getFile(options.statusListFile));
2311
2339
  // decrypt
2312
- const decrypted = await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
2340
+ const decrypted = toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
2313
2341
  // validate against published list
2314
2342
  if (decrypted !== publishedListTranscoded)
2315
2343
  throw new Error('[did-provider-cheqd]: revocation: statusListFile does not match published status list 2021');
@@ -2405,6 +2433,8 @@ export class Cheqd {
2405
2433
  !topArgs?.dkgOptions?.network) {
2406
2434
  throw new Error('[did-provider-cheqd]: dkgOptions is required');
2407
2435
  }
2436
+ // encrypt bitstring - case: symmetric
2437
+ const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await LitProtocol.encryptDirect(fromString(bitstring, 'base64url'));
2408
2438
  // instantiate dkg-threshold client, in which case lit-protocol is used
2409
2439
  const lit = await LitProtocol.create({
2410
2440
  chain: topArgs?.dkgOptions?.chain,
@@ -2455,13 +2485,15 @@ export class Cheqd {
2455
2485
  topArgs.paymentConditions,
2456
2486
  ];
2457
2487
  })();
2458
- // encrypt bitstring
2459
- const { encryptedString, encryptedSymmetricKey, symmetricKey } = await lit.encrypt(bitstring, unifiedAccessControlConditionsTuple[0], true);
2488
+ // encrypt bitstring - case: threshold
2489
+ const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt(fromString(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
2490
+ // construct encoded list
2491
+ const encodedList = `${await blobToHexString(symmetricEncryptionCiphertext)}-${toString(thresholdEncryptionCiphertext, 'hex')}`;
2460
2492
  // define status list content
2461
2493
  const content = {
2462
2494
  StatusList2021: {
2463
2495
  statusPurpose: publishedList.StatusList2021.statusPurpose,
2464
- encodedList: await blobToHexString(encryptedString),
2496
+ encodedList,
2465
2497
  validFrom: publishedList.StatusList2021.validFrom,
2466
2498
  validUntil: options?.publishOptions?.statusListValidUntil ||
2467
2499
  publishedList.StatusList2021.validUntil,
@@ -2470,7 +2502,11 @@ export class Cheqd {
2470
2502
  type: publishedList.metadata.type,
2471
2503
  encrypted: true,
2472
2504
  encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
2473
- encryptedSymmetricKey,
2505
+ statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
2506
+ ? symmetricEncryptionStringHash
2507
+ : (function () {
2508
+ throw new Error('[did-provider-cheqd]: revocation: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
2509
+ })(),
2474
2510
  paymentConditions: unifiedAccessControlConditionsTuple[1],
2475
2511
  },
2476
2512
  };
@@ -2478,9 +2514,10 @@ export class Cheqd {
2478
2514
  return [
2479
2515
  await Cheqd.publishStatusList2021(fromString(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
2480
2516
  {
2481
- encryptedString,
2482
- encryptedSymmetricKey,
2483
- symmetricKey: toString(symmetricKey, 'hex'),
2517
+ symmetricEncryptionCiphertext,
2518
+ thresholdEncryptionCiphertext,
2519
+ stringHash: symmetricEncryptionStringHash,
2520
+ symmetricKey,
2484
2521
  },
2485
2522
  ];
2486
2523
  })()
@@ -2544,7 +2581,7 @@ export class Cheqd {
2544
2581
  ? (await Cheqd.fetchStatusList2021(credentials[0]))
2545
2582
  : undefined,
2546
2583
  symmetricKey: topArgs?.returnSymmetricKey
2547
- ? published?.[1]?.symmetricKey
2584
+ ? toString(published?.[1]?.symmetricKey, 'hex')
2548
2585
  : undefined,
2549
2586
  resourceMetadata: topArgs?.returnStatusListMetadata
2550
2587
  ? await Cheqd.fetchStatusList2021Metadata(credentials[0])
@@ -2560,7 +2597,7 @@ export class Cheqd {
2560
2597
  static async suspendCredential(credential, options) {
2561
2598
  try {
2562
2599
  // validate status purpose
2563
- if (credential?.credentialStatus?.statusPurpose !== 'suspension')
2600
+ if (credential?.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.suspension)
2564
2601
  throw new Error('[did-provider-cheqd]: suspension: Invalid status purpose');
2565
2602
  // fetch status list 2021
2566
2603
  const publishedList = (await Cheqd.fetchStatusList2021(credential));
@@ -2575,10 +2612,17 @@ export class Cheqd {
2575
2612
  return publishedList.metadata.encoding === 'base64url'
2576
2613
  ? publishedList.StatusList2021.encodedList
2577
2614
  : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
2615
+ // decrypt + return bitstring, if qualified for migration
2616
+ if (publishedList.metadata.encryptedSymmetricKey)
2617
+ return await LitProtocolV2.decryptDirect(await toBlob(fromString(publishedList.StatusList2021
2618
+ .encodedList, 'hex')), fromString(options?.topArgs?.symmetricKey, 'hex'));
2619
+ // validate encoded list
2620
+ if (!isEncodedList(publishedList.StatusList2021.encodedList))
2621
+ throw new Error('[did-provider-cheqd]: suspension: Invalid encoded list');
2578
2622
  // otherwise, decrypt and return raw bitstring
2579
- const scopedRawBlob = await toBlob(fromString(publishedList.StatusList2021.encodedList, 'hex'));
2623
+ const scopedRawBlob = await toBlob(fromString(getEncodedList(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
2580
2624
  // decrypt
2581
- return await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
2625
+ return toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
2582
2626
  })()
2583
2627
  : await (async function () {
2584
2628
  // transcode to base64url, if needed
@@ -2602,7 +2646,7 @@ export class Cheqd {
2602
2646
  // otherwise, decrypt and return bitstring
2603
2647
  const scopedRawBlob = await toBlob(await Cheqd.getFile(options.statusListFile));
2604
2648
  // decrypt
2605
- const decrypted = await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
2649
+ const decrypted = toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
2606
2650
  // validate against published list
2607
2651
  if (decrypted !== publishedListTranscoded)
2608
2652
  throw new Error('[did-provider-cheqd]: suspension: statusListFile does not match published status list 2021');
@@ -2683,6 +2727,8 @@ export class Cheqd {
2683
2727
  !topArgs?.dkgOptions?.network) {
2684
2728
  throw new Error('[did-provider-cheqd]: dkgOptions is required');
2685
2729
  }
2730
+ // encrypt bitstring - case: symmetric
2731
+ const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await LitProtocol.encryptDirect(fromString(bitstring, 'base64url'));
2686
2732
  // instantiate dkg-threshold client, in which case lit-protocol is used
2687
2733
  const lit = await LitProtocol.create({
2688
2734
  chain: topArgs?.dkgOptions?.chain,
@@ -2733,13 +2779,15 @@ export class Cheqd {
2733
2779
  topArgs.paymentConditions,
2734
2780
  ];
2735
2781
  })();
2736
- // encrypt bitstring
2737
- const { encryptedString, encryptedSymmetricKey, symmetricKey } = await lit.encrypt(bitstring, unifiedAccessControlConditionsTuple[0], true);
2782
+ // encrypt bitstring - case: threshold
2783
+ const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt(fromString(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
2784
+ // construct encoded list
2785
+ const encodedList = `${await blobToHexString(symmetricEncryptionCiphertext)}-${toString(thresholdEncryptionCiphertext, 'hex')}`;
2738
2786
  // define status list content
2739
2787
  const content = {
2740
2788
  StatusList2021: {
2741
2789
  statusPurpose: publishedList.StatusList2021.statusPurpose,
2742
- encodedList: await blobToHexString(encryptedString),
2790
+ encodedList,
2743
2791
  validFrom: publishedList.StatusList2021.validFrom,
2744
2792
  validUntil: options?.publishOptions?.statusListValidUntil ||
2745
2793
  publishedList.StatusList2021.validUntil,
@@ -2748,7 +2796,11 @@ export class Cheqd {
2748
2796
  type: publishedList.metadata.type,
2749
2797
  encrypted: true,
2750
2798
  encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
2751
- encryptedSymmetricKey,
2799
+ statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
2800
+ ? symmetricEncryptionStringHash
2801
+ : (function () {
2802
+ throw new Error('[did-provider-cheqd]: suspension: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
2803
+ })(),
2752
2804
  paymentConditions: unifiedAccessControlConditionsTuple[1],
2753
2805
  },
2754
2806
  };
@@ -2756,9 +2808,10 @@ export class Cheqd {
2756
2808
  return [
2757
2809
  await Cheqd.publishStatusList2021(fromString(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
2758
2810
  {
2759
- encryptedString,
2760
- encryptedSymmetricKey,
2761
- symmetricKey: toString(symmetricKey, 'hex'),
2811
+ symmetricEncryptionCiphertext,
2812
+ thresholdEncryptionCiphertext,
2813
+ stringHash: symmetricEncryptionStringHash,
2814
+ symmetricKey,
2762
2815
  },
2763
2816
  ];
2764
2817
  })()
@@ -2822,7 +2875,7 @@ export class Cheqd {
2822
2875
  ? (await Cheqd.fetchStatusList2021(credential))
2823
2876
  : undefined,
2824
2877
  symmetricKey: topArgs?.returnSymmetricKey
2825
- ? published?.[1]?.symmetricKey
2878
+ ? toString(published?.[1]?.symmetricKey, 'hex')
2826
2879
  : undefined,
2827
2880
  resourceMetadata: topArgs?.returnStatusListMetadata
2828
2881
  ? await Cheqd.fetchStatusList2021Metadata(credential)
@@ -2854,7 +2907,7 @@ export class Cheqd {
2854
2907
  .filter((value, index, self) => self.indexOf(value) !== index).length > 0)
2855
2908
  throw new Error('[did-provider-cheqd]: suspension: Credentials must have unique status list index');
2856
2909
  // validate credentials - case: status purpose
2857
- if (!credentials.every((credential) => credential.credentialStatus?.statusPurpose === 'suspension'))
2910
+ if (!credentials.every((credential) => credential.credentialStatus?.statusPurpose === DefaultStatusList2021StatusPurposeTypes.suspension))
2858
2911
  throw new Error('[did-provider-cheqd]: suspension: Invalid status purpose');
2859
2912
  // validate credentials - case: status list id
2860
2913
  const remote = credentials[0].credentialStatus?.id
@@ -2886,10 +2939,17 @@ export class Cheqd {
2886
2939
  return publishedList.metadata.encoding === 'base64url'
2887
2940
  ? publishedList.StatusList2021.encodedList
2888
2941
  : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
2942
+ // decrypt + return bitstring, if qualified for migration
2943
+ if (publishedList.metadata.encryptedSymmetricKey)
2944
+ return await LitProtocolV2.decryptDirect(await toBlob(fromString(publishedList.StatusList2021
2945
+ .encodedList, 'hex')), fromString(options?.topArgs?.symmetricKey, 'hex'));
2946
+ // validate encoded list
2947
+ if (!isEncodedList(publishedList.StatusList2021.encodedList))
2948
+ throw new Error('[did-provider-cheqd]: suspension: Invalid encoded list');
2889
2949
  // otherwise, decrypt and return raw bitstring
2890
- const scopedRawBlob = await toBlob(fromString(publishedList.StatusList2021.encodedList, 'hex'));
2950
+ const scopedRawBlob = await toBlob(fromString(getEncodedList(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
2891
2951
  // decrypt
2892
- return await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
2952
+ return toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
2893
2953
  })()
2894
2954
  : await (async function () {
2895
2955
  // transcode to base64url, if needed
@@ -2913,7 +2973,7 @@ export class Cheqd {
2913
2973
  // otherwise, decrypt and return bitstring
2914
2974
  const scopedRawBlob = await toBlob(await Cheqd.getFile(options.statusListFile));
2915
2975
  // decrypt
2916
- const decrypted = await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
2976
+ const decrypted = toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
2917
2977
  // validate against published list
2918
2978
  if (decrypted !== publishedListTranscoded)
2919
2979
  throw new Error('[did-provider-cheqd]: suspension: statusListFile does not match published status list 2021');
@@ -3009,6 +3069,8 @@ export class Cheqd {
3009
3069
  !topArgs?.dkgOptions?.network) {
3010
3070
  throw new Error('[did-provider-cheqd]: dkgOptions is required');
3011
3071
  }
3072
+ // encrypt bitstring - case: symmetric
3073
+ const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await LitProtocol.encryptDirect(fromString(bitstring, 'base64url'));
3012
3074
  // instantiate dkg-threshold client, in which case lit-protocol is used
3013
3075
  const lit = await LitProtocol.create({
3014
3076
  chain: topArgs?.dkgOptions?.chain,
@@ -3059,13 +3121,15 @@ export class Cheqd {
3059
3121
  topArgs.paymentConditions,
3060
3122
  ];
3061
3123
  })();
3062
- // encrypt bitstring
3063
- const { encryptedString, encryptedSymmetricKey, symmetricKey } = await lit.encrypt(bitstring, unifiedAccessControlConditionsTuple[0], true);
3124
+ // encrypt bitstring - case: threshold
3125
+ const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt(fromString(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
3126
+ // construct encoded list
3127
+ const encodedList = `${await blobToHexString(symmetricEncryptionCiphertext)}-${toString(thresholdEncryptionCiphertext, 'hex')}`;
3064
3128
  // define status list content
3065
3129
  const content = {
3066
3130
  StatusList2021: {
3067
3131
  statusPurpose: publishedList.StatusList2021.statusPurpose,
3068
- encodedList: await blobToHexString(encryptedString),
3132
+ encodedList,
3069
3133
  validFrom: publishedList.StatusList2021.validFrom,
3070
3134
  validUntil: options?.publishOptions?.statusListValidUntil ||
3071
3135
  publishedList.StatusList2021.validUntil,
@@ -3074,7 +3138,11 @@ export class Cheqd {
3074
3138
  type: publishedList.metadata.type,
3075
3139
  encrypted: true,
3076
3140
  encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
3077
- encryptedSymmetricKey,
3141
+ statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
3142
+ ? symmetricEncryptionStringHash
3143
+ : (function () {
3144
+ throw new Error('[did-provider-cheqd]: suspension: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
3145
+ })(),
3078
3146
  paymentConditions: unifiedAccessControlConditionsTuple[1],
3079
3147
  },
3080
3148
  };
@@ -3082,9 +3150,10 @@ export class Cheqd {
3082
3150
  return [
3083
3151
  await Cheqd.publishStatusList2021(fromString(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
3084
3152
  {
3085
- encryptedString,
3086
- encryptedSymmetricKey,
3087
- symmetricKey: toString(symmetricKey, 'hex'),
3153
+ symmetricEncryptionCiphertext,
3154
+ thresholdEncryptionCiphertext,
3155
+ stringHash: symmetricEncryptionStringHash,
3156
+ symmetricKey,
3088
3157
  },
3089
3158
  ];
3090
3159
  })()
@@ -3148,7 +3217,7 @@ export class Cheqd {
3148
3217
  ? (await Cheqd.fetchStatusList2021(credentials[0]))
3149
3218
  : undefined,
3150
3219
  symmetricKey: topArgs?.returnSymmetricKey
3151
- ? published?.[1]?.symmetricKey
3220
+ ? toString(published?.[1]?.symmetricKey, 'hex')
3152
3221
  : undefined,
3153
3222
  resourceMetadata: topArgs?.returnStatusListMetadata
3154
3223
  ? await Cheqd.fetchStatusList2021Metadata(credentials[0])
@@ -3164,7 +3233,7 @@ export class Cheqd {
3164
3233
  static async unsuspendCredential(credential, options) {
3165
3234
  try {
3166
3235
  // validate status purpose
3167
- if (credential?.credentialStatus?.statusPurpose !== 'suspension')
3236
+ if (credential?.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.suspension)
3168
3237
  throw new Error('[did-provider-cheqd]: unsuspension: Invalid status purpose');
3169
3238
  // fetch status list 2021
3170
3239
  const publishedList = (await Cheqd.fetchStatusList2021(credential));
@@ -3179,10 +3248,17 @@ export class Cheqd {
3179
3248
  return publishedList.metadata.encoding === 'base64url'
3180
3249
  ? publishedList.StatusList2021.encodedList
3181
3250
  : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
3251
+ // decrypt + return bitstring, if qualified for migration
3252
+ if (publishedList.metadata.encryptedSymmetricKey)
3253
+ return await LitProtocolV2.decryptDirect(await toBlob(fromString(publishedList.StatusList2021
3254
+ .encodedList, 'hex')), fromString(options?.topArgs?.symmetricKey, 'hex'));
3255
+ // validate encoded list
3256
+ if (!isEncodedList(publishedList.StatusList2021.encodedList))
3257
+ throw new Error('[did-provider-cheqd]: unsuspension: Invalid encoded list');
3182
3258
  // otherwise, decrypt and return raw bitstring
3183
- const scopedRawBlob = await toBlob(fromString(publishedList.StatusList2021.encodedList, 'hex'));
3259
+ const scopedRawBlob = await toBlob(fromString(getEncodedList(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
3184
3260
  // decrypt
3185
- return await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
3261
+ return toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
3186
3262
  })()
3187
3263
  : await (async function () {
3188
3264
  // transcode to base64url, if needed
@@ -3206,7 +3282,7 @@ export class Cheqd {
3206
3282
  // otherwise, decrypt and return bitstring
3207
3283
  const scopedRawBlob = await toBlob(await Cheqd.getFile(options.statusListFile));
3208
3284
  // decrypt
3209
- const decrypted = await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
3285
+ const decrypted = toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
3210
3286
  // validate against published list
3211
3287
  if (decrypted !== publishedListTranscoded)
3212
3288
  throw new Error('[did-provider-cheqd]: unsuspension: statusListFile does not match published status list 2021');
@@ -3287,6 +3363,8 @@ export class Cheqd {
3287
3363
  !topArgs?.dkgOptions?.network) {
3288
3364
  throw new Error('[did-provider-cheqd]: dkgOptions is required');
3289
3365
  }
3366
+ // encrypt bitstring - case: symmetric
3367
+ const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await LitProtocol.encryptDirect(fromString(bitstring, 'base64url'));
3290
3368
  // instantiate dkg-threshold client, in which case lit-protocol is used
3291
3369
  const lit = await LitProtocol.create({
3292
3370
  chain: topArgs?.dkgOptions?.chain,
@@ -3337,13 +3415,15 @@ export class Cheqd {
3337
3415
  topArgs.paymentConditions,
3338
3416
  ];
3339
3417
  })();
3340
- // encrypt bitstring
3341
- const { encryptedString, encryptedSymmetricKey, symmetricKey } = await lit.encrypt(bitstring, unifiedAccessControlConditionsTuple[0], true);
3418
+ // encrypt bitstring - case: threshold
3419
+ const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt(fromString(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
3420
+ // construct encoded list
3421
+ const encodedList = `${await blobToHexString(symmetricEncryptionCiphertext)}-${toString(thresholdEncryptionCiphertext, 'hex')}`;
3342
3422
  // define status list content
3343
3423
  const content = {
3344
3424
  StatusList2021: {
3345
3425
  statusPurpose: publishedList.StatusList2021.statusPurpose,
3346
- encodedList: await blobToHexString(encryptedString),
3426
+ encodedList,
3347
3427
  validFrom: publishedList.StatusList2021.validFrom,
3348
3428
  validUntil: options?.publishOptions?.statusListValidUntil ||
3349
3429
  publishedList.StatusList2021.validUntil,
@@ -3352,7 +3432,11 @@ export class Cheqd {
3352
3432
  type: publishedList.metadata.type,
3353
3433
  encrypted: true,
3354
3434
  encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
3355
- encryptedSymmetricKey,
3435
+ statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
3436
+ ? symmetricEncryptionStringHash
3437
+ : (function () {
3438
+ throw new Error('[did-provider-cheqd]: unsuspension: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
3439
+ })(),
3356
3440
  paymentConditions: unifiedAccessControlConditionsTuple[1],
3357
3441
  },
3358
3442
  };
@@ -3360,9 +3444,10 @@ export class Cheqd {
3360
3444
  return [
3361
3445
  await Cheqd.publishStatusList2021(fromString(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
3362
3446
  {
3363
- encryptedString,
3364
- encryptedSymmetricKey,
3365
- symmetricKey: toString(symmetricKey, 'hex'),
3447
+ symmetricEncryptionCiphertext,
3448
+ thresholdEncryptionCiphertext,
3449
+ stringHash: symmetricEncryptionStringHash,
3450
+ symmetricKey,
3366
3451
  },
3367
3452
  ];
3368
3453
  })()
@@ -3426,7 +3511,7 @@ export class Cheqd {
3426
3511
  ? (await Cheqd.fetchStatusList2021(credential))
3427
3512
  : undefined,
3428
3513
  symmetricKey: topArgs?.returnSymmetricKey
3429
- ? published?.[1]?.symmetricKey
3514
+ ? toString(published?.[1]?.symmetricKey, 'hex')
3430
3515
  : undefined,
3431
3516
  resourceMetadata: topArgs?.returnStatusListMetadata
3432
3517
  ? await Cheqd.fetchStatusList2021Metadata(credential)
@@ -3458,7 +3543,7 @@ export class Cheqd {
3458
3543
  .filter((value, index, self) => self.indexOf(value) !== index).length > 0)
3459
3544
  throw new Error('[did-provider-cheqd]: unsuspension: Credentials must have unique status list index');
3460
3545
  // validate credentials - case: status purpose
3461
- if (!credentials.every((credential) => credential.credentialStatus?.statusPurpose === 'suspension'))
3546
+ if (!credentials.every((credential) => credential.credentialStatus?.statusPurpose === DefaultStatusList2021StatusPurposeTypes.suspension))
3462
3547
  throw new Error('[did-provider-cheqd]: unsuspension: Invalid status purpose');
3463
3548
  // validate credentials - case: status list id
3464
3549
  const remote = credentials[0].credentialStatus?.id
@@ -3490,10 +3575,17 @@ export class Cheqd {
3490
3575
  return publishedList.metadata.encoding === 'base64url'
3491
3576
  ? publishedList.StatusList2021.encodedList
3492
3577
  : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
3578
+ // decrypt + return bitstring, if qualified for migration
3579
+ if (publishedList.metadata.encryptedSymmetricKey)
3580
+ return await LitProtocolV2.decryptDirect(await toBlob(fromString(publishedList.StatusList2021
3581
+ .encodedList, 'hex')), fromString(options?.topArgs?.symmetricKey, 'hex'));
3582
+ // validate encoded list
3583
+ if (!isEncodedList(publishedList.StatusList2021.encodedList))
3584
+ throw new Error('[did-provider-cheqd]: unsuspension: Invalid encoded list');
3493
3585
  // otherwise, decrypt and return raw bitstring
3494
- const scopedRawBlob = await toBlob(fromString(publishedList.StatusList2021.encodedList, 'hex'));
3586
+ const scopedRawBlob = await toBlob(fromString(getEncodedList(publishedList.StatusList2021.encodedList, false)[0], 'hex'));
3495
3587
  // decrypt
3496
- return await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
3588
+ return toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
3497
3589
  })()
3498
3590
  : await (async function () {
3499
3591
  // transcode to base64url, if needed
@@ -3517,7 +3609,7 @@ export class Cheqd {
3517
3609
  // otherwise, decrypt and return bitstring
3518
3610
  const scopedRawBlob = await toBlob(await Cheqd.getFile(options.statusListFile));
3519
3611
  // decrypt
3520
- const decrypted = await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
3612
+ const decrypted = toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
3521
3613
  // validate against published list
3522
3614
  if (decrypted !== publishedListTranscoded)
3523
3615
  throw new Error('[did-provider-cheqd]: unsuspension: statusListFile does not match published status list 2021');
@@ -3613,6 +3705,8 @@ export class Cheqd {
3613
3705
  !topArgs?.dkgOptions?.network) {
3614
3706
  throw new Error('[did-provider-cheqd]: dkgOptions is required');
3615
3707
  }
3708
+ // encrypt bitstring - case: symmetric
3709
+ const { encryptedString: symmetricEncryptionCiphertext, stringHash: symmetricEncryptionStringHash, symmetricKey, } = await LitProtocol.encryptDirect(fromString(bitstring, 'base64url'));
3616
3710
  // instantiate dkg-threshold client, in which case lit-protocol is used
3617
3711
  const lit = await LitProtocol.create({
3618
3712
  chain: topArgs?.dkgOptions?.chain,
@@ -3663,13 +3757,15 @@ export class Cheqd {
3663
3757
  topArgs.paymentConditions,
3664
3758
  ];
3665
3759
  })();
3666
- // encrypt bitstring
3667
- const { encryptedString, encryptedSymmetricKey, symmetricKey } = await lit.encrypt(bitstring, unifiedAccessControlConditionsTuple[0], true);
3760
+ // encrypt bitstring - case: threshold
3761
+ const { encryptedString: thresholdEncryptionCiphertext, stringHash: thresholdEncryptionStringHash, } = await lit.encrypt(fromString(bitstring, 'base64url'), unifiedAccessControlConditionsTuple[0]);
3762
+ // construct encoded list
3763
+ const encodedList = `${await blobToHexString(symmetricEncryptionCiphertext)}-${toString(thresholdEncryptionCiphertext, 'hex')}`;
3668
3764
  // define status list content
3669
3765
  const content = {
3670
3766
  StatusList2021: {
3671
3767
  statusPurpose: publishedList.StatusList2021.statusPurpose,
3672
- encodedList: await blobToHexString(encryptedString),
3768
+ encodedList,
3673
3769
  validFrom: publishedList.StatusList2021.validFrom,
3674
3770
  validUntil: options?.publishOptions?.statusListValidUntil ||
3675
3771
  publishedList.StatusList2021.validUntil,
@@ -3678,7 +3774,11 @@ export class Cheqd {
3678
3774
  type: publishedList.metadata.type,
3679
3775
  encrypted: true,
3680
3776
  encoding: options?.publishOptions?.statusListEncoding || publishedList.metadata.encoding,
3681
- encryptedSymmetricKey,
3777
+ statusListHash: symmetricEncryptionStringHash === thresholdEncryptionStringHash
3778
+ ? symmetricEncryptionStringHash
3779
+ : (function () {
3780
+ throw new Error('[did-provider-cheqd]: unsuspension: symmetricEncryptionStringHash and thresholdEncryptionStringHash do not match');
3781
+ })(),
3682
3782
  paymentConditions: unifiedAccessControlConditionsTuple[1],
3683
3783
  },
3684
3784
  };
@@ -3686,9 +3786,10 @@ export class Cheqd {
3686
3786
  return [
3687
3787
  await Cheqd.publishStatusList2021(fromString(JSON.stringify(content), 'utf-8'), statusListMetadata, options?.publishOptions),
3688
3788
  {
3689
- encryptedString,
3690
- encryptedSymmetricKey,
3691
- symmetricKey: toString(symmetricKey, 'hex'),
3789
+ symmetricEncryptionCiphertext,
3790
+ thresholdEncryptionCiphertext,
3791
+ stringHash: symmetricEncryptionStringHash,
3792
+ symmetricKey,
3692
3793
  },
3693
3794
  ];
3694
3795
  })()
@@ -3752,7 +3853,7 @@ export class Cheqd {
3752
3853
  ? (await Cheqd.fetchStatusList2021(credentials[0]))
3753
3854
  : undefined,
3754
3855
  symmetricKey: topArgs?.returnSymmetricKey
3755
- ? published?.[1]?.symmetricKey
3856
+ ? toString(published?.[1]?.symmetricKey, 'hex')
3756
3857
  : undefined,
3757
3858
  resourceMetadata: topArgs?.returnStatusListMetadata
3758
3859
  ? await Cheqd.fetchStatusList2021Metadata(credentials[0])
@@ -3767,11 +3868,14 @@ export class Cheqd {
3767
3868
  }
3768
3869
  static async checkRevoked(credential, options = { fetchList: true }) {
3769
3870
  // validate status purpose
3770
- if (credential.credentialStatus?.statusPurpose !== 'revocation') {
3871
+ if (credential.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.revocation) {
3771
3872
  throw new Error(`[did-provider-cheqd]: check: revocation: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
3772
3873
  }
3773
3874
  // fetch status list 2021
3774
3875
  const publishedList = (await Cheqd.fetchStatusList2021(credential));
3876
+ // route to non-migrated action, if applicable
3877
+ if (publishedList.metadata.encryptedSymmetricKey)
3878
+ return await this.checkRevokedNonMigrated(credential, publishedList, options);
3775
3879
  // fetch status list 2021 inscribed in credential
3776
3880
  const statusList2021 = options?.topArgs?.fetchList
3777
3881
  ? await (async function () {
@@ -3780,8 +3884,11 @@ export class Cheqd {
3780
3884
  return publishedList.metadata.encoding === 'base64url'
3781
3885
  ? publishedList.StatusList2021.encodedList
3782
3886
  : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
3887
+ // validate encoded list
3888
+ if (!isEncodedList(publishedList.StatusList2021.encodedList))
3889
+ throw new Error('[did-provider-cheqd]: check: revocation: Invalid encoded list');
3783
3890
  // otherwise, decrypt and return raw bitstring
3784
- const scopedRawBlob = await toBlob(fromString(publishedList.StatusList2021.encodedList, 'hex'));
3891
+ const thresholdEncryptionCiphertext = getEncodedList(publishedList.StatusList2021.encodedList, false)[1];
3785
3892
  // instantiate dkg-threshold client, in which case lit-protocol is used
3786
3893
  const lit = await LitProtocol.create({
3787
3894
  chain: options?.topArgs?.dkgOptions?.chain,
@@ -3801,7 +3908,7 @@ export class Cheqd {
3801
3908
  }
3802
3909
  }));
3803
3910
  // decrypt
3804
- return await lit.decrypt(scopedRawBlob, publishedList.metadata.encryptedSymmetricKey, unifiedAccessControlConditions);
3911
+ return await lit.decrypt(thresholdEncryptionCiphertext, publishedList.metadata.statusListHash, unifiedAccessControlConditions);
3805
3912
  })()
3806
3913
  : await (async function () {
3807
3914
  // transcode to base64url, if needed
@@ -3825,7 +3932,7 @@ export class Cheqd {
3825
3932
  // otherwise, decrypt and return bitstring
3826
3933
  const scopedRawBlob = await toBlob(await Cheqd.getFile(options.statusListFile));
3827
3934
  // decrypt
3828
- const decrypted = await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
3935
+ const decrypted = toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
3829
3936
  // validate against published list
3830
3937
  if (decrypted !== publishedListTranscoded)
3831
3938
  throw new Error('[did-provider-cheqd]: check: revocation: statusListFile does not match published status list 2021');
@@ -3851,11 +3958,14 @@ export class Cheqd {
3851
3958
  }
3852
3959
  static async checkSuspended(credential, options = { fetchList: true }) {
3853
3960
  // validate status purpose
3854
- if (credential.credentialStatus?.statusPurpose !== 'suspension') {
3961
+ if (credential.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.suspension) {
3855
3962
  throw new Error(`[did-provider-cheqd]: check: suspension: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
3856
3963
  }
3857
3964
  // fetch status list 2021
3858
3965
  const publishedList = (await Cheqd.fetchStatusList2021(credential));
3966
+ // route to non-migrated action, if applicable
3967
+ if (publishedList.metadata.encryptedSymmetricKey)
3968
+ return await this.checkSuspendedNonMigrated(credential, publishedList, options);
3859
3969
  // fetch status list 2021 inscribed in credential
3860
3970
  const statusList2021 = options?.topArgs?.fetchList
3861
3971
  ? await (async function () {
@@ -3865,7 +3975,7 @@ export class Cheqd {
3865
3975
  ? publishedList.StatusList2021.encodedList
3866
3976
  : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
3867
3977
  // otherwise, decrypt and return bitstring
3868
- const scopedRawBlob = await toBlob(fromString(publishedList.StatusList2021.encodedList, 'hex'));
3978
+ const thresholdEncryptionCiphertext = getEncodedList(publishedList.StatusList2021.encodedList, false)[1];
3869
3979
  // instantiate dkg-threshold client, in which case lit-protocol is used
3870
3980
  const lit = await LitProtocol.create({
3871
3981
  chain: options?.topArgs?.dkgOptions?.chain,
@@ -3885,6 +3995,178 @@ export class Cheqd {
3885
3995
  }
3886
3996
  }));
3887
3997
  // decrypt
3998
+ return await lit.decrypt(thresholdEncryptionCiphertext, publishedList.metadata.statusListHash, unifiedAccessControlConditions);
3999
+ })()
4000
+ : await (async function () {
4001
+ // transcode to base64url, if needed
4002
+ const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
4003
+ ? publishedList.StatusList2021.encodedList
4004
+ : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
4005
+ // if status list 2021 is not fetched, read from file
4006
+ if (options?.statusListFile) {
4007
+ // if not encrypted, return bitstring
4008
+ if (!publishedList.metadata.encrypted) {
4009
+ // construct encoded status list
4010
+ const encoded = new StatusList({
4011
+ buffer: await Cheqd.getFile(options.statusListFile),
4012
+ }).encode();
4013
+ // validate against published list
4014
+ if (encoded !== publishedListTranscoded)
4015
+ throw new Error('[did-provider-cheqd]: check: suspension: statusListFile does not match published status list 2021');
4016
+ // return encoded
4017
+ return encoded;
4018
+ }
4019
+ // otherwise, decrypt and return bitstring
4020
+ const scopedRawBlob = await toBlob(await Cheqd.getFile(options.statusListFile));
4021
+ // decrypt
4022
+ const decrypted = toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
4023
+ // validate against published list
4024
+ if (decrypted !== publishedListTranscoded)
4025
+ throw new Error('[did-provider-cheqd]: check: suspension: statusListFile does not match published status list 2021');
4026
+ // return decrypted
4027
+ return decrypted;
4028
+ }
4029
+ if (!options?.statusListInlineBitstring)
4030
+ throw new Error('[did-provider-cheqd]: check: suspension: statusListInlineBitstring is required, if statusListFile is not provided');
4031
+ // validate against published list
4032
+ if (options?.statusListInlineBitstring !== publishedListTranscoded)
4033
+ throw new Error('[did-provider-cheqd]: check: suspension: statusListInlineBitstring does not match published status list 2021');
4034
+ // otherwise, read from inline bitstring
4035
+ return options?.statusListInlineBitstring;
4036
+ })();
4037
+ // parse status list 2021
4038
+ const statusList = await StatusList.decode({ encodedList: statusList2021 });
4039
+ // get status by index
4040
+ return !!statusList.getStatus(Number(credential.credentialStatus.statusListIndex));
4041
+ }
4042
+ static async checkRevokedNonMigrated(credential, associatedStatusList, options = { fetchList: true }) {
4043
+ // validate status purpose
4044
+ if (credential.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.revocation) {
4045
+ throw new Error(`[did-provider-cheqd]: check: revocation: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
4046
+ }
4047
+ // fetch status list 2021
4048
+ const publishedList = associatedStatusList ||
4049
+ (await Cheqd.fetchStatusList2021(credential));
4050
+ // validate migrated
4051
+ if (!publishedList.metadata.encryptedSymmetricKey)
4052
+ throw new Error('[did-provider-cheqd]: check: revocation: Invalid migrated status list');
4053
+ // fetch status list 2021 inscribed in credential
4054
+ const statusList2021 = options?.topArgs?.fetchList
4055
+ ? await (async function () {
4056
+ // if not encrypted, return bitstring
4057
+ if (!publishedList.metadata.encrypted)
4058
+ return publishedList.metadata.encoding === 'base64url'
4059
+ ? publishedList.StatusList2021.encodedList
4060
+ : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
4061
+ // otherwise, decrypt and return raw bitstring
4062
+ const scopedRawBlob = await toBlob(fromString(publishedList.StatusList2021.encodedList, 'hex'));
4063
+ // instantiate dkg-threshold client, in which case lit-protocol is used
4064
+ const lit = await LitProtocolV2.create({
4065
+ chain: options?.topArgs?.dkgOptions?.chain,
4066
+ litNetwork: LitNetworksV2.serrano,
4067
+ });
4068
+ // construct access control conditions
4069
+ const unifiedAccessControlConditions = await Promise.all(publishedList.metadata.paymentConditions.map(async (condition) => {
4070
+ switch (condition.type) {
4071
+ case AccessControlConditionTypes.timelockPayment:
4072
+ return await LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
4073
+ key: '$.tx_responses.*.timestamp',
4074
+ comparator: '<=',
4075
+ value: `${condition.intervalInSeconds}`,
4076
+ }, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, options?.topArgs?.dkgOptions?.chain);
4077
+ default:
4078
+ throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
4079
+ }
4080
+ }));
4081
+ // decrypt
4082
+ return await lit.decrypt(scopedRawBlob, publishedList.metadata.encryptedSymmetricKey, unifiedAccessControlConditions);
4083
+ })()
4084
+ : await (async function () {
4085
+ // transcode to base64url, if needed
4086
+ const publishedListTranscoded = publishedList.metadata.encoding === 'base64url'
4087
+ ? publishedList.StatusList2021.encodedList
4088
+ : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
4089
+ // if status list 2021 is not fetched, read from file
4090
+ if (options?.statusListFile) {
4091
+ // if not encrypted, return bitstring
4092
+ if (!publishedList.metadata.encrypted) {
4093
+ // construct encoded status list
4094
+ const encoded = new StatusList({
4095
+ buffer: await Cheqd.getFile(options.statusListFile),
4096
+ }).encode();
4097
+ // validate against published list
4098
+ if (encoded !== publishedListTranscoded)
4099
+ throw new Error('[did-provider-cheqd]: check: revocation: statusListFile does not match published status list 2021');
4100
+ // return encoded
4101
+ return encoded;
4102
+ }
4103
+ // otherwise, decrypt and return bitstring
4104
+ const scopedRawBlob = await toBlob(await Cheqd.getFile(options.statusListFile));
4105
+ // decrypt
4106
+ const decrypted = await LitProtocolV2.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
4107
+ // validate against published list
4108
+ if (decrypted !== publishedListTranscoded)
4109
+ throw new Error('[did-provider-cheqd]: check: revocation: statusListFile does not match published status list 2021');
4110
+ // return decrypted
4111
+ return decrypted;
4112
+ }
4113
+ if (!options?.statusListInlineBitstring)
4114
+ throw new Error('[did-provider-cheqd]: check: revocation: statusListInlineBitstring is required, if statusListFile is not provided');
4115
+ // validate against published list
4116
+ if (options?.statusListInlineBitstring !== publishedListTranscoded)
4117
+ throw new Error('[did-provider-cheqd]: check: revocation: statusListInlineBitstring does not match published status list 2021');
4118
+ // otherwise, read from inline bitstring
4119
+ return options?.statusListInlineBitstring;
4120
+ })();
4121
+ // transcode, if needed
4122
+ const transcodedStatusList2021 = publishedList.metadata.encoding === 'base64url'
4123
+ ? statusList2021
4124
+ : toString(fromString(statusList2021, publishedList.metadata.encoding), 'base64url');
4125
+ // parse status list 2021
4126
+ const statusList = await StatusList.decode({ encodedList: transcodedStatusList2021 });
4127
+ // get status by index
4128
+ return !!statusList.getStatus(Number(credential.credentialStatus.statusListIndex));
4129
+ }
4130
+ static async checkSuspendedNonMigrated(credential, associatedStatusList, options = { fetchList: true }) {
4131
+ // validate status purpose
4132
+ if (credential.credentialStatus?.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.suspension) {
4133
+ throw new Error(`[did-provider-cheqd]: check: suspension: Unsupported status purpose: ${credential.credentialStatus?.statusPurpose}`);
4134
+ }
4135
+ // fetch status list 2021
4136
+ const publishedList = associatedStatusList ||
4137
+ (await Cheqd.fetchStatusList2021(credential));
4138
+ // validate migrated
4139
+ if (!publishedList.metadata.encryptedSymmetricKey)
4140
+ throw new Error('[did-provider-cheqd]: check: suspension: Invalid migrated status list');
4141
+ // fetch status list 2021 inscribed in credential
4142
+ const statusList2021 = options?.topArgs?.fetchList
4143
+ ? await (async function () {
4144
+ // if not encrypted, return bitstring
4145
+ if (!publishedList.metadata.encrypted)
4146
+ return publishedList.metadata.encoding === 'base64url'
4147
+ ? publishedList.StatusList2021.encodedList
4148
+ : toString(fromString(publishedList.StatusList2021.encodedList, publishedList.metadata.encoding), 'base64url');
4149
+ // otherwise, decrypt and return raw bitstring
4150
+ const scopedRawBlob = await toBlob(fromString(publishedList.StatusList2021.encodedList, 'hex'));
4151
+ // instantiate dkg-threshold client, in which case lit-protocol is used
4152
+ const lit = await LitProtocolV2.create({
4153
+ chain: options?.topArgs?.dkgOptions?.chain,
4154
+ litNetwork: LitNetworksV2.serrano,
4155
+ });
4156
+ // construct access control conditions
4157
+ const unifiedAccessControlConditions = await Promise.all(publishedList.metadata.paymentConditions.map(async (condition) => {
4158
+ switch (condition.type) {
4159
+ case AccessControlConditionTypes.timelockPayment:
4160
+ return await LitProtocol.generateCosmosAccessControlConditionInverseTimelock({
4161
+ key: '$.tx_responses.*.timestamp',
4162
+ comparator: '<=',
4163
+ value: `${condition.intervalInSeconds}`,
4164
+ }, condition.feePaymentAmount, condition.feePaymentAddress, condition?.blockHeight, options?.topArgs?.dkgOptions?.chain);
4165
+ default:
4166
+ throw new Error(`[did-provider-cheqd]: unsupported access control condition type ${condition.type}`);
4167
+ }
4168
+ }));
4169
+ // decrypt
3888
4170
  return await lit.decrypt(scopedRawBlob, publishedList.metadata.encryptedSymmetricKey, unifiedAccessControlConditions);
3889
4171
  })()
3890
4172
  : await (async function () {
@@ -3909,7 +4191,7 @@ export class Cheqd {
3909
4191
  // otherwise, decrypt and return bitstring
3910
4192
  const scopedRawBlob = await toBlob(await Cheqd.getFile(options.statusListFile));
3911
4193
  // decrypt
3912
- const decrypted = await LitProtocol.decryptDirect(scopedRawBlob, fromString(options?.topArgs?.symmetricKey, 'hex'));
4194
+ const decrypted = toString(await LitProtocol.decryptDirect(scopedRawBlob, await safeDeserialise(options?.topArgs?.symmetricKey, fromString, ['hex'], 'Invalid symmetric key')), 'base64url');
3913
4195
  // validate against published list
3914
4196
  if (decrypted !== publishedListTranscoded)
3915
4197
  throw new Error('[did-provider-cheqd]: check: suspension: statusListFile does not match published status list 2021');
@@ -3956,8 +4238,8 @@ export class Cheqd {
3956
4238
  if (credential.credentialStatus.type !== 'StatusList2021Entry')
3957
4239
  throw new Error('[did-provider-cheqd]: fetch status list: Credential status type is not valid');
3958
4240
  // validate credential status list status purpose
3959
- if (credential.credentialStatus.statusPurpose !== 'revocation' &&
3960
- credential.credentialStatus.statusPurpose !== 'suspension')
4241
+ if (credential.credentialStatus.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.revocation &&
4242
+ credential.credentialStatus.statusPurpose !== DefaultStatusList2021StatusPurposeTypes.suspension)
3961
4243
  throw new Error('[did-provider-cheqd]: fetch status list: Credential status purpose is not valid');
3962
4244
  // fetch status list 2021
3963
4245
  const content = (await (await fetch(credential.credentialStatus.id.split('#')[0])).json());