@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.
- package/build/cjs/agent/ICheqd.d.ts +44 -2
- package/build/cjs/agent/ICheqd.d.ts.map +1 -1
- package/build/cjs/agent/ICheqd.js +451 -169
- package/build/cjs/agent/ICheqd.js.map +1 -1
- package/build/cjs/did-manager/cheqd-did-provider.d.ts +1 -2
- package/build/cjs/did-manager/cheqd-did-provider.d.ts.map +1 -1
- package/build/cjs/did-manager/cheqd-did-provider.js +5 -6
- package/build/cjs/did-manager/cheqd-did-provider.js.map +1 -1
- package/build/cjs/dkg-threshold/index.d.ts +1 -1
- package/build/cjs/dkg-threshold/index.d.ts.map +1 -1
- package/build/cjs/dkg-threshold/index.js +1 -1
- package/build/cjs/dkg-threshold/index.js.map +1 -1
- package/build/cjs/dkg-threshold/lit-protocol/v2.d.ts +95 -0
- package/build/cjs/dkg-threshold/lit-protocol/v2.d.ts.map +1 -0
- package/build/cjs/dkg-threshold/{lit-protocol.js → lit-protocol/v2.js} +39 -39
- package/build/cjs/dkg-threshold/lit-protocol/v2.js.map +1 -0
- package/build/cjs/dkg-threshold/{lit-protocol.d.ts → lit-protocol/v3.d.ts} +17 -17
- package/build/cjs/dkg-threshold/lit-protocol/v3.d.ts.map +1 -0
- package/build/cjs/dkg-threshold/lit-protocol/v3.js +231 -0
- package/build/cjs/dkg-threshold/lit-protocol/v3.js.map +1 -0
- package/build/cjs/utils/helpers.d.ts +5 -0
- package/build/cjs/utils/helpers.d.ts.map +1 -1
- package/build/cjs/utils/helpers.js +38 -1
- package/build/cjs/utils/helpers.js.map +1 -1
- package/build/esm/agent/ICheqd.d.ts +44 -2
- package/build/esm/agent/ICheqd.d.ts.map +1 -1
- package/build/esm/agent/ICheqd.js +425 -143
- package/build/esm/agent/ICheqd.js.map +1 -1
- package/build/esm/did-manager/cheqd-did-provider.d.ts +1 -2
- package/build/esm/did-manager/cheqd-did-provider.d.ts.map +1 -1
- package/build/esm/did-manager/cheqd-did-provider.js +3 -4
- package/build/esm/did-manager/cheqd-did-provider.js.map +1 -1
- package/build/esm/dkg-threshold/index.d.ts +1 -1
- package/build/esm/dkg-threshold/index.d.ts.map +1 -1
- package/build/esm/dkg-threshold/index.js +1 -1
- package/build/esm/dkg-threshold/index.js.map +1 -1
- package/build/esm/dkg-threshold/lit-protocol/v2.d.ts +95 -0
- package/build/esm/dkg-threshold/lit-protocol/v2.d.ts.map +1 -0
- package/build/esm/dkg-threshold/{lit-protocol.js → lit-protocol/v2.js} +31 -31
- package/build/esm/dkg-threshold/lit-protocol/v2.js.map +1 -0
- package/build/esm/dkg-threshold/{lit-protocol.d.ts → lit-protocol/v3.d.ts} +17 -17
- package/build/esm/dkg-threshold/lit-protocol/v3.d.ts.map +1 -0
- package/build/esm/dkg-threshold/lit-protocol/v3.js +227 -0
- package/build/esm/dkg-threshold/lit-protocol/v3.js.map +1 -0
- package/build/esm/utils/helpers.d.ts +5 -0
- package/build/esm/utils/helpers.d.ts.map +1 -1
- package/build/esm/utils/helpers.js +33 -0
- package/build/esm/utils/helpers.js.map +1 -1
- package/build/tsconfig.cjs.tsbuildinfo +1 -1
- package/build/tsconfig.esm.tsbuildinfo +1 -1
- package/build/tsconfig.types.tsbuildinfo +1 -1
- package/build/types/agent/ICheqd.d.ts +44 -2
- package/build/types/agent/ICheqd.d.ts.map +1 -1
- package/build/types/did-manager/cheqd-did-provider.d.ts +1 -2
- package/build/types/did-manager/cheqd-did-provider.d.ts.map +1 -1
- package/build/types/dkg-threshold/index.d.ts +1 -1
- package/build/types/dkg-threshold/index.d.ts.map +1 -1
- package/build/types/dkg-threshold/lit-protocol/v2.d.ts +95 -0
- package/build/types/dkg-threshold/lit-protocol/v2.d.ts.map +1 -0
- package/build/types/dkg-threshold/{lit-protocol.d.ts → lit-protocol/v3.d.ts} +17 -17
- package/build/types/dkg-threshold/lit-protocol/v3.d.ts.map +1 -0
- package/build/types/utils/helpers.d.ts +5 -0
- package/build/types/utils/helpers.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/agent/ICheqd.ts +970 -202
- package/src/did-manager/cheqd-did-provider.ts +3 -4
- package/src/dkg-threshold/index.ts +1 -1
- package/src/dkg-threshold/lit-protocol/v2.ts +287 -0
- package/src/dkg-threshold/{lit-protocol.ts → lit-protocol/v3.ts} +114 -45
- package/src/utils/helpers.ts +45 -0
- package/build/cjs/dkg-threshold/lit-protocol.d.ts.map +0 -1
- package/build/cjs/dkg-threshold/lit-protocol.js.map +0 -1
- package/build/esm/dkg-threshold/lit-protocol.d.ts.map +0 -1
- package/build/esm/dkg-threshold/lit-protocol.js.map +0 -1
- 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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
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
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
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 ===
|
|
1125
|
-
?
|
|
1126
|
-
:
|
|
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
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
return {
|
|
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
|
|
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:
|
|
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 !==
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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 !==
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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 !==
|
|
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
|
|
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:
|
|
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 !==
|
|
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,
|
|
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,
|
|
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:
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
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 ===
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
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 !==
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
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 ===
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
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 !==
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
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 ===
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
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 !==
|
|
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
|
|
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(
|
|
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,
|
|
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 !==
|
|
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
|
|
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,
|
|
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 !==
|
|
3960
|
-
credential.credentialStatus.statusPurpose !==
|
|
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());
|