@ajna-inc/openbadges 0.1.0

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 (224) hide show
  1. package/LICENSE +202 -0
  2. package/build/OpenBadgesModule.d.ts +10 -0
  3. package/build/OpenBadgesModule.js +75 -0
  4. package/build/OpenBadgesModule.js.map +1 -0
  5. package/build/OpenBadgesModuleConfig.d.ts +96 -0
  6. package/build/OpenBadgesModuleConfig.js +50 -0
  7. package/build/OpenBadgesModuleConfig.js.map +1 -0
  8. package/build/api/OpenBadgesApi.d.ts +48 -0
  9. package/build/api/OpenBadgesApi.js +81 -0
  10. package/build/api/OpenBadgesApi.js.map +1 -0
  11. package/build/api/index.d.ts +1 -0
  12. package/build/api/index.js +18 -0
  13. package/build/api/index.js.map +1 -0
  14. package/build/constants.d.ts +12 -0
  15. package/build/constants.js +27 -0
  16. package/build/constants.js.map +1 -0
  17. package/build/cryptosuites/EcdsaSd2023.d.ts +143 -0
  18. package/build/cryptosuites/EcdsaSd2023.js +518 -0
  19. package/build/cryptosuites/EcdsaSd2023.js.map +1 -0
  20. package/build/cryptosuites/EddsaRdfc2022.d.ts +112 -0
  21. package/build/cryptosuites/EddsaRdfc2022.js +356 -0
  22. package/build/cryptosuites/EddsaRdfc2022.js.map +1 -0
  23. package/build/cryptosuites/constants.d.ts +14 -0
  24. package/build/cryptosuites/constants.js +22 -0
  25. package/build/cryptosuites/constants.js.map +1 -0
  26. package/build/cryptosuites/contextPreprocessor.d.ts +24 -0
  27. package/build/cryptosuites/contextPreprocessor.js +127 -0
  28. package/build/cryptosuites/contextPreprocessor.js.map +1 -0
  29. package/build/cryptosuites/dataIntegrityV2Context.d.ts +144 -0
  30. package/build/cryptosuites/dataIntegrityV2Context.js +86 -0
  31. package/build/cryptosuites/dataIntegrityV2Context.js.map +1 -0
  32. package/build/cryptosuites/index.d.ts +11 -0
  33. package/build/cryptosuites/index.js +33 -0
  34. package/build/cryptosuites/index.js.map +1 -0
  35. package/build/http/OpenBadgesHttpModule.d.ts +9 -0
  36. package/build/http/OpenBadgesHttpModule.js +120 -0
  37. package/build/http/OpenBadgesHttpModule.js.map +1 -0
  38. package/build/http/OpenBadgesHttpModuleConfig.d.ts +55 -0
  39. package/build/http/OpenBadgesHttpModuleConfig.js +78 -0
  40. package/build/http/OpenBadgesHttpModuleConfig.js.map +1 -0
  41. package/build/http/endpoints/authorize.d.ts +3 -0
  42. package/build/http/endpoints/authorize.js +79 -0
  43. package/build/http/endpoints/authorize.js.map +1 -0
  44. package/build/http/endpoints/consent.d.ts +3 -0
  45. package/build/http/endpoints/consent.js +25 -0
  46. package/build/http/endpoints/consent.js.map +1 -0
  47. package/build/http/endpoints/credentials.d.ts +4 -0
  48. package/build/http/endpoints/credentials.js +85 -0
  49. package/build/http/endpoints/credentials.js.map +1 -0
  50. package/build/http/endpoints/did.d.ts +3 -0
  51. package/build/http/endpoints/did.js +48 -0
  52. package/build/http/endpoints/did.js.map +1 -0
  53. package/build/http/endpoints/introspect.d.ts +3 -0
  54. package/build/http/endpoints/introspect.js +37 -0
  55. package/build/http/endpoints/introspect.js.map +1 -0
  56. package/build/http/endpoints/jwks.d.ts +3 -0
  57. package/build/http/endpoints/jwks.js +46 -0
  58. package/build/http/endpoints/jwks.js.map +1 -0
  59. package/build/http/endpoints/profile.d.ts +4 -0
  60. package/build/http/endpoints/profile.js +58 -0
  61. package/build/http/endpoints/profile.js.map +1 -0
  62. package/build/http/endpoints/refresh.d.ts +15 -0
  63. package/build/http/endpoints/refresh.js +134 -0
  64. package/build/http/endpoints/refresh.js.map +1 -0
  65. package/build/http/endpoints/registration.d.ts +3 -0
  66. package/build/http/endpoints/registration.js +42 -0
  67. package/build/http/endpoints/registration.js.map +1 -0
  68. package/build/http/endpoints/revoke.d.ts +3 -0
  69. package/build/http/endpoints/revoke.js +38 -0
  70. package/build/http/endpoints/revoke.js.map +1 -0
  71. package/build/http/endpoints/serviceDescription.d.ts +3 -0
  72. package/build/http/endpoints/serviceDescription.js +52 -0
  73. package/build/http/endpoints/serviceDescription.js.map +1 -0
  74. package/build/http/endpoints/statusList.d.ts +10 -0
  75. package/build/http/endpoints/statusList.js +95 -0
  76. package/build/http/endpoints/statusList.js.map +1 -0
  77. package/build/http/endpoints/token.d.ts +3 -0
  78. package/build/http/endpoints/token.js +147 -0
  79. package/build/http/endpoints/token.js.map +1 -0
  80. package/build/http/middleware/auth.d.ts +5 -0
  81. package/build/http/middleware/auth.js +48 -0
  82. package/build/http/middleware/auth.js.map +1 -0
  83. package/build/http/router.d.ts +13 -0
  84. package/build/http/router.js +36 -0
  85. package/build/http/router.js.map +1 -0
  86. package/build/http/tenants.d.ts +2 -0
  87. package/build/http/tenants.js +20 -0
  88. package/build/http/tenants.js.map +1 -0
  89. package/build/http/util/auth.d.ts +8 -0
  90. package/build/http/util/auth.js +43 -0
  91. package/build/http/util/auth.js.map +1 -0
  92. package/build/index.d.ts +46 -0
  93. package/build/index.js +71 -0
  94. package/build/index.js.map +1 -0
  95. package/build/models/ClrCredential.d.ts +112 -0
  96. package/build/models/ClrCredential.js +52 -0
  97. package/build/models/ClrCredential.js.map +1 -0
  98. package/build/models/EndorsementCredential.d.ts +89 -0
  99. package/build/models/EndorsementCredential.js +11 -0
  100. package/build/models/EndorsementCredential.js.map +1 -0
  101. package/build/models/StatusListCredential.d.ts +81 -0
  102. package/build/models/StatusListCredential.js +28 -0
  103. package/build/models/StatusListCredential.js.map +1 -0
  104. package/build/models/index.d.ts +8 -0
  105. package/build/models/index.js +25 -0
  106. package/build/models/index.js.map +1 -0
  107. package/build/repository/OpenBadgeCredentialRecord.d.ts +44 -0
  108. package/build/repository/OpenBadgeCredentialRecord.js +46 -0
  109. package/build/repository/OpenBadgeCredentialRecord.js.map +1 -0
  110. package/build/repository/OpenBadgeCredentialRepository.d.ts +8 -0
  111. package/build/repository/OpenBadgeCredentialRepository.js +38 -0
  112. package/build/repository/OpenBadgeCredentialRepository.js.map +1 -0
  113. package/build/repository/OpenBadgesAuthCodeRecord.d.ts +35 -0
  114. package/build/repository/OpenBadgesAuthCodeRecord.js +28 -0
  115. package/build/repository/OpenBadgesAuthCodeRecord.js.map +1 -0
  116. package/build/repository/OpenBadgesAuthCodeRepository.d.ts +6 -0
  117. package/build/repository/OpenBadgesAuthCodeRepository.js +32 -0
  118. package/build/repository/OpenBadgesAuthCodeRepository.js.map +1 -0
  119. package/build/repository/OpenBadgesConsentRecord.d.ts +24 -0
  120. package/build/repository/OpenBadgesConsentRecord.js +23 -0
  121. package/build/repository/OpenBadgesConsentRecord.js.map +1 -0
  122. package/build/repository/OpenBadgesConsentRepository.d.ts +6 -0
  123. package/build/repository/OpenBadgesConsentRepository.js +32 -0
  124. package/build/repository/OpenBadgesConsentRepository.js.map +1 -0
  125. package/build/repository/OpenBadgesKeyBindingRecord.d.ts +24 -0
  126. package/build/repository/OpenBadgesKeyBindingRecord.js +32 -0
  127. package/build/repository/OpenBadgesKeyBindingRecord.js.map +1 -0
  128. package/build/repository/OpenBadgesKeyBindingRepository.d.ts +7 -0
  129. package/build/repository/OpenBadgesKeyBindingRepository.js +35 -0
  130. package/build/repository/OpenBadgesKeyBindingRepository.js.map +1 -0
  131. package/build/repository/OpenBadgesOAuthRecord.d.ts +35 -0
  132. package/build/repository/OpenBadgesOAuthRecord.js +25 -0
  133. package/build/repository/OpenBadgesOAuthRecord.js.map +1 -0
  134. package/build/repository/OpenBadgesOAuthRepository.d.ts +8 -0
  135. package/build/repository/OpenBadgesOAuthRepository.js +38 -0
  136. package/build/repository/OpenBadgesOAuthRepository.js.map +1 -0
  137. package/build/repository/OpenBadgesProfileRecord.d.ts +21 -0
  138. package/build/repository/OpenBadgesProfileRecord.js +22 -0
  139. package/build/repository/OpenBadgesProfileRecord.js.map +1 -0
  140. package/build/repository/OpenBadgesProfileRepository.d.ts +6 -0
  141. package/build/repository/OpenBadgesProfileRepository.js +32 -0
  142. package/build/repository/OpenBadgesProfileRepository.js.map +1 -0
  143. package/build/repository/OpenBadgesRevocationCacheRecord.d.ts +23 -0
  144. package/build/repository/OpenBadgesRevocationCacheRecord.js +23 -0
  145. package/build/repository/OpenBadgesRevocationCacheRecord.js.map +1 -0
  146. package/build/repository/OpenBadgesRevocationCacheRepository.d.ts +6 -0
  147. package/build/repository/OpenBadgesRevocationCacheRepository.js +32 -0
  148. package/build/repository/OpenBadgesRevocationCacheRepository.js.map +1 -0
  149. package/build/repository/OpenBadgesServiceDescriptionRecord.d.ts +21 -0
  150. package/build/repository/OpenBadgesServiceDescriptionRecord.js +22 -0
  151. package/build/repository/OpenBadgesServiceDescriptionRecord.js.map +1 -0
  152. package/build/repository/OpenBadgesServiceDescriptionRepository.d.ts +6 -0
  153. package/build/repository/OpenBadgesServiceDescriptionRepository.js +32 -0
  154. package/build/repository/OpenBadgesServiceDescriptionRepository.js.map +1 -0
  155. package/build/repository/OpenBadgesTokenRecord.d.ts +39 -0
  156. package/build/repository/OpenBadgesTokenRecord.js +36 -0
  157. package/build/repository/OpenBadgesTokenRecord.js.map +1 -0
  158. package/build/repository/OpenBadgesTokenRepository.d.ts +9 -0
  159. package/build/repository/OpenBadgesTokenRepository.js +45 -0
  160. package/build/repository/OpenBadgesTokenRepository.js.map +1 -0
  161. package/build/repository/StatusListRecord.d.ts +49 -0
  162. package/build/repository/StatusListRecord.js +47 -0
  163. package/build/repository/StatusListRecord.js.map +1 -0
  164. package/build/repository/StatusListRepository.d.ts +24 -0
  165. package/build/repository/StatusListRepository.js +52 -0
  166. package/build/repository/StatusListRepository.js.map +1 -0
  167. package/build/repository/index.d.ts +18 -0
  168. package/build/repository/index.js +35 -0
  169. package/build/repository/index.js.map +1 -0
  170. package/build/services/AchievementValidator.d.ts +158 -0
  171. package/build/services/AchievementValidator.js +238 -0
  172. package/build/services/AchievementValidator.js.map +1 -0
  173. package/build/services/ConsumerService.d.ts +24 -0
  174. package/build/services/ConsumerService.js +143 -0
  175. package/build/services/ConsumerService.js.map +1 -0
  176. package/build/services/ContextService.d.ts +14 -0
  177. package/build/services/ContextService.js +54 -0
  178. package/build/services/ContextService.js.map +1 -0
  179. package/build/services/DataIntegrityService.d.ts +51 -0
  180. package/build/services/DataIntegrityService.js +134 -0
  181. package/build/services/DataIntegrityService.js.map +1 -0
  182. package/build/services/DidCommLinkService.d.ts +7 -0
  183. package/build/services/DidCommLinkService.js +20 -0
  184. package/build/services/DidCommLinkService.js.map +1 -0
  185. package/build/services/DisplayMapper.d.ts +9 -0
  186. package/build/services/DisplayMapper.js +26 -0
  187. package/build/services/DisplayMapper.js.map +1 -0
  188. package/build/services/IssuerService.d.ts +38 -0
  189. package/build/services/IssuerService.js +225 -0
  190. package/build/services/IssuerService.js.map +1 -0
  191. package/build/services/JwtService.d.ts +19 -0
  192. package/build/services/JwtService.js +229 -0
  193. package/build/services/JwtService.js.map +1 -0
  194. package/build/services/KeyService.d.ts +102 -0
  195. package/build/services/KeyService.js +439 -0
  196. package/build/services/KeyService.js.map +1 -0
  197. package/build/services/OAuthClient.d.ts +26 -0
  198. package/build/services/OAuthClient.js +127 -0
  199. package/build/services/OAuthClient.js.map +1 -0
  200. package/build/services/ProofService.d.ts +15 -0
  201. package/build/services/ProofService.js +43 -0
  202. package/build/services/ProofService.js.map +1 -0
  203. package/build/services/RevocationService.d.ts +59 -0
  204. package/build/services/RevocationService.js +319 -0
  205. package/build/services/RevocationService.js.map +1 -0
  206. package/build/services/VerifyService.d.ts +17 -0
  207. package/build/services/VerifyService.js +54 -0
  208. package/build/services/VerifyService.js.map +1 -0
  209. package/build/services/crypto/CryptoDriver.d.ts +9 -0
  210. package/build/services/crypto/CryptoDriver.js +7 -0
  211. package/build/services/crypto/CryptoDriver.js.map +1 -0
  212. package/build/services/crypto/JsonLdCryptoDriver.d.ts +17 -0
  213. package/build/services/crypto/JsonLdCryptoDriver.js +45 -0
  214. package/build/services/crypto/JsonLdCryptoDriver.js.map +1 -0
  215. package/build/services/crypto/JwtCryptoDriver.d.ts +13 -0
  216. package/build/services/crypto/JwtCryptoDriver.js +42 -0
  217. package/build/services/crypto/JwtCryptoDriver.js.map +1 -0
  218. package/build/services/index.d.ts +12 -0
  219. package/build/services/index.js +29 -0
  220. package/build/services/index.js.map +1 -0
  221. package/build/utils/validate.d.ts +17 -0
  222. package/build/utils/validate.js +107 -0
  223. package/build/utils/validate.js.map +1 -0
  224. package/package.json +57 -0
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VM_TYPE_ED25519_2020 = exports.VM_TYPE_MULTIKEY = exports.PROOF_TYPE_ED25519_2020 = exports.PROOF_TYPE_DATA_INTEGRITY = exports.CRYPTOSUITE_EDDSA_RDFC_2022 = exports.CRYPTOSUITE_ECDSA_SD_2023 = exports.STATUS_LIST_2021 = exports.ONE_EDTECH_REVOCATION_LIST = exports.DI_ECDSA_SD_2023 = exports.DI_EDDSA_RDFC_2022 = exports.CLR_TYPES = exports.ENDORSEMENT_TYPES = exports.REQUIRED_TYPES = exports.DATA_INTEGRITY_V2_CONTEXT = exports.CLR_V2_CONTEXT = exports.OBV3_CONTEXT = exports.VC_V2_CONTEXT = void 0;
4
+ // W3C and OpenBadges context URLs
5
+ exports.VC_V2_CONTEXT = 'https://www.w3.org/ns/credentials/v2';
6
+ exports.OBV3_CONTEXT = 'https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json';
7
+ exports.CLR_V2_CONTEXT = 'https://purl.imsglobal.org/spec/clr/v2p0/context-2.0.1.json';
8
+ exports.DATA_INTEGRITY_V2_CONTEXT = 'https://w3id.org/security/data-integrity/v2';
9
+ // Required credential types
10
+ exports.REQUIRED_TYPES = ['VerifiableCredential', 'OpenBadgeCredential'];
11
+ exports.ENDORSEMENT_TYPES = ['VerifiableCredential', 'EndorsementCredential'];
12
+ exports.CLR_TYPES = ['VerifiableCredential', 'ClrCredential'];
13
+ // Cryptosuite identifiers
14
+ exports.DI_EDDSA_RDFC_2022 = 'eddsa-rdfc-2022';
15
+ exports.DI_ECDSA_SD_2023 = 'ecdsa-sd-2023';
16
+ // Revocation
17
+ exports.ONE_EDTECH_REVOCATION_LIST = '1EdTechRevocationList';
18
+ exports.STATUS_LIST_2021 = 'StatusList2021';
19
+ // Re-export cryptosuite constants for convenience
20
+ var cryptosuites_1 = require("./cryptosuites");
21
+ Object.defineProperty(exports, "CRYPTOSUITE_ECDSA_SD_2023", { enumerable: true, get: function () { return cryptosuites_1.CRYPTOSUITE_ECDSA_SD_2023; } });
22
+ Object.defineProperty(exports, "CRYPTOSUITE_EDDSA_RDFC_2022", { enumerable: true, get: function () { return cryptosuites_1.CRYPTOSUITE_EDDSA_RDFC_2022; } });
23
+ Object.defineProperty(exports, "PROOF_TYPE_DATA_INTEGRITY", { enumerable: true, get: function () { return cryptosuites_1.PROOF_TYPE_DATA_INTEGRITY; } });
24
+ Object.defineProperty(exports, "PROOF_TYPE_ED25519_2020", { enumerable: true, get: function () { return cryptosuites_1.PROOF_TYPE_ED25519_2020; } });
25
+ Object.defineProperty(exports, "VM_TYPE_MULTIKEY", { enumerable: true, get: function () { return cryptosuites_1.VM_TYPE_MULTIKEY; } });
26
+ Object.defineProperty(exports, "VM_TYPE_ED25519_2020", { enumerable: true, get: function () { return cryptosuites_1.VM_TYPE_ED25519_2020; } });
27
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAA,kCAAkC;AACrB,QAAA,aAAa,GAAG,sCAAsC,CAAA;AACtD,QAAA,YAAY,GAAG,4DAA4D,CAAA;AAC3E,QAAA,cAAc,GAAG,6DAA6D,CAAA;AAC9E,QAAA,yBAAyB,GAAG,6CAA6C,CAAA;AAEtF,4BAA4B;AACf,QAAA,cAAc,GAAG,CAAC,sBAAsB,EAAE,qBAAqB,CAAC,CAAA;AAChE,QAAA,iBAAiB,GAAG,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAA;AACrE,QAAA,SAAS,GAAG,CAAC,sBAAsB,EAAE,eAAe,CAAC,CAAA;AAElE,0BAA0B;AACb,QAAA,kBAAkB,GAAG,iBAAiB,CAAA;AACtC,QAAA,gBAAgB,GAAG,eAAe,CAAA;AAE/C,aAAa;AACA,QAAA,0BAA0B,GAAG,uBAAuB,CAAA;AACpD,QAAA,gBAAgB,GAAG,gBAAgB,CAAA;AAEhD,kDAAkD;AAClD,+CAOuB;AANrB,yHAAA,yBAAyB,OAAA;AACzB,2HAAA,2BAA2B,OAAA;AAC3B,yHAAA,yBAAyB,OAAA;AACzB,uHAAA,uBAAuB,OAAA;AACvB,gHAAA,gBAAgB,OAAA;AAChB,oHAAA,oBAAoB,OAAA"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * ECDSA SD 2023 Cryptosuite
3
+ *
4
+ * Implements the ecdsa-sd-2023 cryptosuite for Data Integrity proofs with
5
+ * selective disclosure support.
6
+ *
7
+ * Spec: https://www.w3.org/TR/vc-di-ecdsa/#ecdsa-sd-2023
8
+ *
9
+ * Key features:
10
+ * - Uses ECDSA P-256 (secp256r1) signature algorithm
11
+ * - Supports selective disclosure of claims
12
+ * - Uses mandatory and selective pointers for claim selection
13
+ * - Produces DataIntegrityProof with cryptosuite: 'ecdsa-sd-2023'
14
+ *
15
+ * Note: This implementation provides the structure and interface.
16
+ * Full selective disclosure requires BBS+ style commitments which would need
17
+ * additional crypto libraries. For now, this provides basic ECDSA signing
18
+ * with the correct proof structure.
19
+ */
20
+ import { CRYPTOSUITE_ECDSA_SD_2023, PROOF_TYPE_DATA_INTEGRITY } from './constants';
21
+ export interface EcdsaSd2023KeyPair {
22
+ id: string;
23
+ controller: string;
24
+ publicKeyMultibase: string;
25
+ privateKeyMultibase?: string;
26
+ }
27
+ export interface EcdsaSd2023Proof {
28
+ type: typeof PROOF_TYPE_DATA_INTEGRITY;
29
+ cryptosuite: typeof CRYPTOSUITE_ECDSA_SD_2023;
30
+ created: string;
31
+ verificationMethod: string;
32
+ proofPurpose: string;
33
+ proofValue: string;
34
+ }
35
+ export interface SignOptions {
36
+ document: Record<string, unknown>;
37
+ keyPair: EcdsaSd2023KeyPair;
38
+ purpose?: string;
39
+ date?: Date | string;
40
+ mandatoryPointers?: string[];
41
+ }
42
+ export interface DeriveOptions {
43
+ signedDocument: Record<string, unknown>;
44
+ selectivePointers: string[];
45
+ }
46
+ export interface VerifyOptions {
47
+ document: Record<string, unknown>;
48
+ proof: EcdsaSd2023Proof;
49
+ publicKeyMultibase: string;
50
+ }
51
+ /**
52
+ * ECDSA SD 2023 Cryptosuite implementation
53
+ *
54
+ * Note: Full selective disclosure support requires BBS+ style cryptography.
55
+ * This implementation provides the structure and basic ECDSA signing.
56
+ * For production use with actual selective disclosure, integrate with
57
+ * @mattrglobal/bbs-signatures or similar.
58
+ */
59
+ export declare class EcdsaSd2023Cryptosuite {
60
+ static readonly proofType = "DataIntegrityProof";
61
+ static readonly cryptosuite = "ecdsa-sd-2023";
62
+ static readonly contextUrl = "https://w3id.org/security/data-integrity/v2";
63
+ static readonly verificationMethodTypes: string[];
64
+ /**
65
+ * Sign a document using ecdsa-sd-2023 cryptosuite
66
+ *
67
+ * @param options - Sign options including document, keyPair, and mandatoryPointers
68
+ * @returns Signed document with base proof
69
+ */
70
+ sign(options: SignOptions): Promise<Record<string, unknown>>;
71
+ /**
72
+ * Derive a selective disclosure proof from a base proof
73
+ *
74
+ * @param options - Derive options including signed document and selective pointers
75
+ * @returns Derived document with only selected claims
76
+ */
77
+ derive(options: DeriveOptions): Promise<Record<string, unknown>>;
78
+ /**
79
+ * Verify a document with ecdsa-sd-2023 proof
80
+ */
81
+ verify(options: VerifyOptions): Promise<{
82
+ verified: boolean;
83
+ error?: string;
84
+ }>;
85
+ /**
86
+ * Check if this suite matches a given proof
87
+ */
88
+ matchProof(proof: Record<string, unknown>): boolean;
89
+ /**
90
+ * Create hash data for signing/verification
91
+ */
92
+ private createHashData;
93
+ /**
94
+ * Deep sort object keys for consistent serialization
95
+ */
96
+ private sortObject;
97
+ /**
98
+ * Get Web Crypto SubtleCrypto API if available
99
+ */
100
+ private getSubtleCrypto;
101
+ /**
102
+ * Sign data with P-256 key using Web Crypto API with JWK import
103
+ */
104
+ private signWithP256;
105
+ /**
106
+ * Verify signature with P-256 public key using Web Crypto API with JWK import
107
+ */
108
+ private verifyWithP256;
109
+ /**
110
+ * SHA-256 hash using Node crypto
111
+ */
112
+ private sha256;
113
+ /**
114
+ * Decode private key from multibase and return raw 32-byte scalar
115
+ */
116
+ private decodePrivateKeyRaw;
117
+ /**
118
+ * Decode public key from multibase and return raw bytes
119
+ * Returns uncompressed format (65 bytes: 0x04 || x || y)
120
+ */
121
+ private decodePublicKeyRaw;
122
+ /**
123
+ * Convert raw P-256 private key to JWK format for Web Crypto
124
+ */
125
+ private privateKeyToJwk;
126
+ /**
127
+ * Convert raw P-256 public key to JWK format for Web Crypto
128
+ */
129
+ private publicKeyToJwk;
130
+ /**
131
+ * Encode proof value (base64url encoded JSON)
132
+ */
133
+ private encodeProofValue;
134
+ /**
135
+ * Decode proof value
136
+ */
137
+ private decodeProofValue;
138
+ /**
139
+ * Generate a new P-256 key pair with multibase encoding
140
+ * Uses Web Crypto API for key generation
141
+ */
142
+ static generateKeyPair(controller: string, keyId?: string): Promise<EcdsaSd2023KeyPair>;
143
+ }
@@ -0,0 +1,518 @@
1
+ "use strict";
2
+ /**
3
+ * ECDSA SD 2023 Cryptosuite
4
+ *
5
+ * Implements the ecdsa-sd-2023 cryptosuite for Data Integrity proofs with
6
+ * selective disclosure support.
7
+ *
8
+ * Spec: https://www.w3.org/TR/vc-di-ecdsa/#ecdsa-sd-2023
9
+ *
10
+ * Key features:
11
+ * - Uses ECDSA P-256 (secp256r1) signature algorithm
12
+ * - Supports selective disclosure of claims
13
+ * - Uses mandatory and selective pointers for claim selection
14
+ * - Produces DataIntegrityProof with cryptosuite: 'ecdsa-sd-2023'
15
+ *
16
+ * Note: This implementation provides the structure and interface.
17
+ * Full selective disclosure requires BBS+ style commitments which would need
18
+ * additional crypto libraries. For now, this provides basic ECDSA signing
19
+ * with the correct proof structure.
20
+ */
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.EcdsaSd2023Cryptosuite = void 0;
26
+ const constants_1 = require("./constants");
27
+ const bs58_1 = __importDefault(require("bs58"));
28
+ const crypto_1 = require("crypto");
29
+ // P-256 multicodec prefixes
30
+ const P256_PUB_MULTICODEC = new Uint8Array([0x80, 0x24]);
31
+ const P256_PRIV_MULTICODEC = new Uint8Array([0x86, 0x26]);
32
+ /**
33
+ * JSON Pointer helper to get value at path
34
+ */
35
+ function getValueAtPointer(obj, pointer) {
36
+ if (!pointer.startsWith('/')) {
37
+ throw new Error('JSON pointer must start with /');
38
+ }
39
+ const parts = pointer.slice(1).split('/');
40
+ let current = obj;
41
+ for (const part of parts) {
42
+ if (current === null || current === undefined) {
43
+ return undefined;
44
+ }
45
+ const decodedPart = part.replace(/~1/g, '/').replace(/~0/g, '~');
46
+ if (Array.isArray(current)) {
47
+ const index = parseInt(decodedPart, 10);
48
+ current = current[index];
49
+ }
50
+ else if (typeof current === 'object') {
51
+ current = current[decodedPart];
52
+ }
53
+ else {
54
+ return undefined;
55
+ }
56
+ }
57
+ return current;
58
+ }
59
+ /**
60
+ * JSON Pointer helper to set value at path
61
+ */
62
+ function setValueAtPointer(obj, pointer, value) {
63
+ if (!pointer.startsWith('/')) {
64
+ throw new Error('JSON pointer must start with /');
65
+ }
66
+ const parts = pointer.slice(1).split('/');
67
+ let current = obj;
68
+ for (let i = 0; i < parts.length - 1; i++) {
69
+ const part = parts[i].replace(/~1/g, '/').replace(/~0/g, '~');
70
+ if (Array.isArray(current)) {
71
+ const index = parseInt(part, 10);
72
+ if (current[index] === undefined) {
73
+ current[index] = {};
74
+ }
75
+ current = current[index];
76
+ }
77
+ else if (typeof current === 'object' && current !== null) {
78
+ const record = current;
79
+ if (record[part] === undefined) {
80
+ record[part] = {};
81
+ }
82
+ current = record[part];
83
+ }
84
+ }
85
+ const lastPart = parts[parts.length - 1].replace(/~1/g, '/').replace(/~0/g, '~');
86
+ if (Array.isArray(current)) {
87
+ const index = parseInt(lastPart, 10);
88
+ current[index] = value;
89
+ }
90
+ else if (typeof current === 'object' && current !== null) {
91
+ ;
92
+ current[lastPart] = value;
93
+ }
94
+ }
95
+ /**
96
+ * ECDSA SD 2023 Cryptosuite implementation
97
+ *
98
+ * Note: Full selective disclosure support requires BBS+ style cryptography.
99
+ * This implementation provides the structure and basic ECDSA signing.
100
+ * For production use with actual selective disclosure, integrate with
101
+ * @mattrglobal/bbs-signatures or similar.
102
+ */
103
+ class EcdsaSd2023Cryptosuite {
104
+ /**
105
+ * Sign a document using ecdsa-sd-2023 cryptosuite
106
+ *
107
+ * @param options - Sign options including document, keyPair, and mandatoryPointers
108
+ * @returns Signed document with base proof
109
+ */
110
+ async sign(options) {
111
+ const { document, keyPair, purpose = 'assertionMethod', date, mandatoryPointers = [] } = options;
112
+ // Create proof options
113
+ const proofOptions = {
114
+ type: constants_1.PROOF_TYPE_DATA_INTEGRITY,
115
+ cryptosuite: constants_1.CRYPTOSUITE_ECDSA_SD_2023,
116
+ created: date ? new Date(date).toISOString() : new Date().toISOString(),
117
+ verificationMethod: keyPair.id,
118
+ proofPurpose: purpose,
119
+ };
120
+ // Store mandatory pointers in proof (for derive to use later)
121
+ const proofWithPointers = {
122
+ ...proofOptions,
123
+ // Store mandatory claim references
124
+ _mandatoryPointers: mandatoryPointers,
125
+ };
126
+ // Create hash data
127
+ const documentCopy = { ...document };
128
+ delete documentCopy.proof;
129
+ const hashData = this.createHashData(documentCopy, proofWithPointers);
130
+ // Sign using Web Crypto API (P-256/ECDSA)
131
+ const signature = await this.signWithP256(hashData, keyPair);
132
+ // Create proof value
133
+ // In ecdsa-sd-2023, the proofValue contains:
134
+ // 1. The base signature
135
+ // 2. Commitments to selective claims
136
+ // 3. Mandatory claim hashes
137
+ // For this simplified version, we just include the signature
138
+ const proofValue = this.encodeProofValue({
139
+ signature,
140
+ mandatoryPointers,
141
+ });
142
+ // Create final proof
143
+ const proof = {
144
+ type: constants_1.PROOF_TYPE_DATA_INTEGRITY,
145
+ cryptosuite: constants_1.CRYPTOSUITE_ECDSA_SD_2023,
146
+ created: proofOptions.created,
147
+ verificationMethod: proofOptions.verificationMethod,
148
+ proofPurpose: proofOptions.proofPurpose,
149
+ proofValue,
150
+ };
151
+ return {
152
+ ...document,
153
+ proof,
154
+ };
155
+ }
156
+ /**
157
+ * Derive a selective disclosure proof from a base proof
158
+ *
159
+ * @param options - Derive options including signed document and selective pointers
160
+ * @returns Derived document with only selected claims
161
+ */
162
+ async derive(options) {
163
+ const { signedDocument, selectivePointers } = options;
164
+ const proof = signedDocument.proof;
165
+ if (!proof || proof.cryptosuite !== constants_1.CRYPTOSUITE_ECDSA_SD_2023) {
166
+ throw new Error('Document must have an ecdsa-sd-2023 proof for derivation');
167
+ }
168
+ // Parse the original proof value
169
+ const { signature, mandatoryPointers } = this.decodeProofValue(proof.proofValue);
170
+ // Create derived document with only selected + mandatory claims
171
+ const allPointers = [...new Set([...mandatoryPointers, ...selectivePointers])];
172
+ // Build derived document
173
+ const derivedDoc = {
174
+ '@context': signedDocument['@context'],
175
+ type: signedDocument.type,
176
+ };
177
+ // Copy mandatory fields
178
+ if (signedDocument.id)
179
+ derivedDoc.id = signedDocument.id;
180
+ if (signedDocument.issuer)
181
+ derivedDoc.issuer = signedDocument.issuer;
182
+ if (signedDocument.validFrom)
183
+ derivedDoc.validFrom = signedDocument.validFrom;
184
+ // Copy selected claims
185
+ for (const pointer of allPointers) {
186
+ const value = getValueAtPointer(signedDocument, pointer);
187
+ if (value !== undefined) {
188
+ setValueAtPointer(derivedDoc, pointer, value);
189
+ }
190
+ }
191
+ // Create derived proof
192
+ const derivedProof = {
193
+ type: constants_1.PROOF_TYPE_DATA_INTEGRITY,
194
+ cryptosuite: constants_1.CRYPTOSUITE_ECDSA_SD_2023,
195
+ created: proof.created,
196
+ verificationMethod: proof.verificationMethod,
197
+ proofPurpose: proof.proofPurpose,
198
+ proofValue: this.encodeProofValue({
199
+ signature,
200
+ mandatoryPointers,
201
+ derivedFrom: proof.proofValue,
202
+ selectedPointers: selectivePointers,
203
+ }),
204
+ };
205
+ return {
206
+ ...derivedDoc,
207
+ proof: derivedProof,
208
+ };
209
+ }
210
+ /**
211
+ * Verify a document with ecdsa-sd-2023 proof
212
+ */
213
+ async verify(options) {
214
+ const { document, proof, publicKeyMultibase } = options;
215
+ try {
216
+ // Validate proof structure
217
+ if (proof.type !== constants_1.PROOF_TYPE_DATA_INTEGRITY) {
218
+ return { verified: false, error: `Invalid proof type: ${proof.type}` };
219
+ }
220
+ if (proof.cryptosuite !== constants_1.CRYPTOSUITE_ECDSA_SD_2023) {
221
+ return { verified: false, error: `Invalid cryptosuite: ${proof.cryptosuite}` };
222
+ }
223
+ // Parse proof value
224
+ const { signature } = this.decodeProofValue(proof.proofValue);
225
+ // Recreate hash data
226
+ const documentCopy = { ...document };
227
+ delete documentCopy.proof;
228
+ const proofOptions = {
229
+ type: proof.type,
230
+ cryptosuite: proof.cryptosuite,
231
+ created: proof.created,
232
+ verificationMethod: proof.verificationMethod,
233
+ proofPurpose: proof.proofPurpose,
234
+ };
235
+ const hashData = this.createHashData(documentCopy, proofOptions);
236
+ // Verify signature
237
+ const verified = await this.verifyWithP256(hashData, signature, publicKeyMultibase);
238
+ return { verified };
239
+ }
240
+ catch (error) {
241
+ const err = error;
242
+ return { verified: false, error: err.message };
243
+ }
244
+ }
245
+ /**
246
+ * Check if this suite matches a given proof
247
+ */
248
+ matchProof(proof) {
249
+ return (proof.type === constants_1.PROOF_TYPE_DATA_INTEGRITY && proof.cryptosuite === constants_1.CRYPTOSUITE_ECDSA_SD_2023);
250
+ }
251
+ /**
252
+ * Create hash data for signing/verification
253
+ */
254
+ createHashData(document, proofOptions) {
255
+ const combined = {
256
+ document: this.sortObject(document),
257
+ proofOptions: this.sortObject(proofOptions),
258
+ };
259
+ const encoder = new TextEncoder();
260
+ return encoder.encode(JSON.stringify(combined));
261
+ }
262
+ /**
263
+ * Deep sort object keys for consistent serialization
264
+ */
265
+ sortObject(obj) {
266
+ if (Array.isArray(obj)) {
267
+ return obj.map((item) => typeof item === 'object' && item !== null
268
+ ? this.sortObject(item)
269
+ : item);
270
+ }
271
+ if (typeof obj !== 'object' || obj === null) {
272
+ return obj;
273
+ }
274
+ const sorted = {};
275
+ const keys = Object.keys(obj).sort();
276
+ for (const key of keys) {
277
+ // Skip internal fields
278
+ if (key.startsWith('_'))
279
+ continue;
280
+ const value = obj[key];
281
+ sorted[key] =
282
+ typeof value === 'object' && value !== null
283
+ ? this.sortObject(value)
284
+ : value;
285
+ }
286
+ return sorted;
287
+ }
288
+ /**
289
+ * Get Web Crypto SubtleCrypto API if available
290
+ */
291
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
292
+ getSubtleCrypto() {
293
+ // Try to get crypto.subtle from globalThis (works in Node.js 15+ and browsers)
294
+ try {
295
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
296
+ const globalCrypto = globalThis.crypto;
297
+ if (globalCrypto?.subtle) {
298
+ return globalCrypto.subtle;
299
+ }
300
+ }
301
+ catch {
302
+ // Crypto not available
303
+ }
304
+ return undefined;
305
+ }
306
+ /**
307
+ * Sign data with P-256 key using Web Crypto API with JWK import
308
+ */
309
+ async signWithP256(data, keyPair) {
310
+ if (!keyPair.privateKeyMultibase) {
311
+ throw new Error('Private key is required for signing');
312
+ }
313
+ const subtle = this.getSubtleCrypto();
314
+ if (!subtle) {
315
+ throw new Error('Web Crypto API (subtle) not available');
316
+ }
317
+ try {
318
+ // Decode private and public keys from multibase
319
+ const privateKeyRaw = this.decodePrivateKeyRaw(keyPair.privateKeyMultibase);
320
+ const publicKeyRaw = this.decodePublicKeyRaw(keyPair.publicKeyMultibase);
321
+ // Convert to JWK format
322
+ const jwk = this.privateKeyToJwk(privateKeyRaw, publicKeyRaw);
323
+ // Import the key using JWK format
324
+ const cryptoKey = await subtle.importKey('jwk', jwk, { name: 'ECDSA', namedCurve: 'P-256' }, false, ['sign']);
325
+ // Sign the data
326
+ const signatureBuffer = await subtle.sign({ name: 'ECDSA', hash: 'SHA-256' }, cryptoKey, data);
327
+ return new Uint8Array(signatureBuffer);
328
+ }
329
+ catch (error) {
330
+ throw new Error(`P-256 signing failed: ${error.message}`);
331
+ }
332
+ }
333
+ /**
334
+ * Verify signature with P-256 public key using Web Crypto API with JWK import
335
+ */
336
+ async verifyWithP256(data, signature, publicKeyMultibase) {
337
+ const subtle = this.getSubtleCrypto();
338
+ if (!subtle) {
339
+ throw new Error('Web Crypto API (subtle) not available');
340
+ }
341
+ try {
342
+ // Decode public key from multibase
343
+ const publicKeyRaw = this.decodePublicKeyRaw(publicKeyMultibase);
344
+ // Convert to JWK format
345
+ const jwk = this.publicKeyToJwk(publicKeyRaw);
346
+ // Import the public key using JWK format
347
+ const cryptoKey = await subtle.importKey('jwk', jwk, { name: 'ECDSA', namedCurve: 'P-256' }, false, ['verify']);
348
+ // Verify the signature
349
+ return await subtle.verify({ name: 'ECDSA', hash: 'SHA-256' }, cryptoKey, signature, data);
350
+ }
351
+ catch (error) {
352
+ throw new Error(`P-256 verification failed: ${error.message}`);
353
+ }
354
+ }
355
+ /**
356
+ * SHA-256 hash using Node crypto
357
+ */
358
+ sha256(data) {
359
+ return (0, crypto_1.createHash)('sha256').update(data).digest();
360
+ }
361
+ /**
362
+ * Decode private key from multibase and return raw 32-byte scalar
363
+ */
364
+ decodePrivateKeyRaw(privateKeyMultibase) {
365
+ if (!privateKeyMultibase.startsWith('z')) {
366
+ throw new Error('Invalid multibase prefix: expected base58btc (z)');
367
+ }
368
+ const decoded = bs58_1.default.decode(privateKeyMultibase.slice(1));
369
+ // Check for P-256 private key multicodec prefix (0x8626)
370
+ if (decoded.length > 2 && decoded[0] === P256_PRIV_MULTICODEC[0] && decoded[1] === P256_PRIV_MULTICODEC[1]) {
371
+ return decoded.slice(2);
372
+ }
373
+ // If no multicodec prefix, assume raw key material
374
+ return decoded;
375
+ }
376
+ /**
377
+ * Decode public key from multibase and return raw bytes
378
+ * Returns uncompressed format (65 bytes: 0x04 || x || y)
379
+ */
380
+ decodePublicKeyRaw(publicKeyMultibase) {
381
+ if (!publicKeyMultibase.startsWith('z')) {
382
+ throw new Error('Invalid multibase prefix: expected base58btc (z)');
383
+ }
384
+ const decoded = bs58_1.default.decode(publicKeyMultibase.slice(1));
385
+ // Check for P-256 public key multicodec prefix (0x8024)
386
+ if (decoded.length > 2 && decoded[0] === P256_PUB_MULTICODEC[0] && decoded[1] === P256_PUB_MULTICODEC[1]) {
387
+ return decoded.slice(2);
388
+ }
389
+ // If no multicodec prefix, assume raw key material
390
+ return decoded;
391
+ }
392
+ /**
393
+ * Convert raw P-256 private key to JWK format for Web Crypto
394
+ */
395
+ privateKeyToJwk(privateKeyRaw, publicKeyRaw) {
396
+ // Private key is 32 bytes (scalar d)
397
+ // Public key is 65 bytes uncompressed (0x04 || x || y) or 64 bytes (x || y)
398
+ let x;
399
+ let y;
400
+ if (publicKeyRaw.length === 65 && publicKeyRaw[0] === 0x04) {
401
+ // Uncompressed format with 0x04 prefix
402
+ x = publicKeyRaw.slice(1, 33);
403
+ y = publicKeyRaw.slice(33, 65);
404
+ }
405
+ else if (publicKeyRaw.length === 64) {
406
+ // Raw x || y without prefix
407
+ x = publicKeyRaw.slice(0, 32);
408
+ y = publicKeyRaw.slice(32, 64);
409
+ }
410
+ else {
411
+ throw new Error(`Invalid P-256 public key length: ${publicKeyRaw.length}`);
412
+ }
413
+ return {
414
+ kty: 'EC',
415
+ crv: 'P-256',
416
+ x: Buffer.from(x).toString('base64url'),
417
+ y: Buffer.from(y).toString('base64url'),
418
+ d: Buffer.from(privateKeyRaw).toString('base64url'),
419
+ };
420
+ }
421
+ /**
422
+ * Convert raw P-256 public key to JWK format for Web Crypto
423
+ */
424
+ publicKeyToJwk(publicKeyRaw) {
425
+ let x;
426
+ let y;
427
+ if (publicKeyRaw.length === 65 && publicKeyRaw[0] === 0x04) {
428
+ // Uncompressed format with 0x04 prefix
429
+ x = publicKeyRaw.slice(1, 33);
430
+ y = publicKeyRaw.slice(33, 65);
431
+ }
432
+ else if (publicKeyRaw.length === 64) {
433
+ // Raw x || y without prefix
434
+ x = publicKeyRaw.slice(0, 32);
435
+ y = publicKeyRaw.slice(32, 64);
436
+ }
437
+ else {
438
+ throw new Error(`Invalid P-256 public key length: ${publicKeyRaw.length}`);
439
+ }
440
+ return {
441
+ kty: 'EC',
442
+ crv: 'P-256',
443
+ x: Buffer.from(x).toString('base64url'),
444
+ y: Buffer.from(y).toString('base64url'),
445
+ };
446
+ }
447
+ /**
448
+ * Encode proof value (base64url encoded JSON)
449
+ */
450
+ encodeProofValue(data) {
451
+ const payload = {
452
+ s: Buffer.from(data.signature).toString('base64'),
453
+ m: data.mandatoryPointers,
454
+ d: data.derivedFrom,
455
+ p: data.selectedPointers,
456
+ };
457
+ // Use 'u' prefix for base64url encoding
458
+ return 'u' + Buffer.from(JSON.stringify(payload)).toString('base64url');
459
+ }
460
+ /**
461
+ * Decode proof value
462
+ */
463
+ decodeProofValue(proofValue) {
464
+ if (!proofValue.startsWith('u')) {
465
+ throw new Error('Invalid proof value: expected base64url (u) prefix');
466
+ }
467
+ const json = Buffer.from(proofValue.slice(1), 'base64url').toString('utf-8');
468
+ const payload = JSON.parse(json);
469
+ return {
470
+ signature: Buffer.from(payload.s, 'base64'),
471
+ mandatoryPointers: payload.m || [],
472
+ derivedFrom: payload.d,
473
+ selectedPointers: payload.p,
474
+ };
475
+ }
476
+ /**
477
+ * Generate a new P-256 key pair with multibase encoding
478
+ * Uses Web Crypto API for key generation
479
+ */
480
+ static async generateKeyPair(controller, keyId) {
481
+ // Use Web Crypto to generate P-256 key pair
482
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
483
+ const subtle = globalThis.crypto?.subtle;
484
+ if (!subtle) {
485
+ throw new Error('Web Crypto API (subtle) not available for key generation');
486
+ }
487
+ // Generate key pair
488
+ const keyPair = await subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, // extractable
489
+ ['sign', 'verify']);
490
+ // Export keys to JWK format
491
+ const publicJwk = await subtle.exportKey('jwk', keyPair.publicKey);
492
+ const privateJwk = await subtle.exportKey('jwk', keyPair.privateKey);
493
+ // Extract raw key bytes from JWK
494
+ const x = Buffer.from(publicJwk.x, 'base64url');
495
+ const y = Buffer.from(publicJwk.y, 'base64url');
496
+ const d = Buffer.from(privateJwk.d, 'base64url');
497
+ // Create uncompressed public key (0x04 || x || y)
498
+ const publicKeyRaw = Buffer.concat([Buffer.from([0x04]), x, y]);
499
+ // Encode with multicodec prefixes
500
+ const pubWithHeader = Buffer.concat([Buffer.from(P256_PUB_MULTICODEC), publicKeyRaw]);
501
+ const privWithHeader = Buffer.concat([Buffer.from(P256_PRIV_MULTICODEC), d]);
502
+ const publicKeyMultibase = 'z' + bs58_1.default.encode(pubWithHeader);
503
+ const privateKeyMultibase = 'z' + bs58_1.default.encode(privWithHeader);
504
+ const id = keyId || `${controller}#key-1`;
505
+ return {
506
+ id,
507
+ controller,
508
+ publicKeyMultibase,
509
+ privateKeyMultibase,
510
+ };
511
+ }
512
+ }
513
+ exports.EcdsaSd2023Cryptosuite = EcdsaSd2023Cryptosuite;
514
+ EcdsaSd2023Cryptosuite.proofType = constants_1.PROOF_TYPE_DATA_INTEGRITY;
515
+ EcdsaSd2023Cryptosuite.cryptosuite = constants_1.CRYPTOSUITE_ECDSA_SD_2023;
516
+ EcdsaSd2023Cryptosuite.contextUrl = constants_1.DATA_INTEGRITY_V2_CONTEXT_URL;
517
+ EcdsaSd2023Cryptosuite.verificationMethodTypes = [constants_1.VM_TYPE_MULTIKEY];
518
+ //# sourceMappingURL=EcdsaSd2023.js.map