@epochcore/identity-sdk 1.1.0 → 1.2.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.
package/dist/index.d.mts CHANGED
@@ -29,6 +29,34 @@ interface SignedPayload {
29
29
  publicKey: string;
30
30
  timestamp: string;
31
31
  }
32
+ interface QuantumResistantKeypair {
33
+ /** ML-DSA-65 (CRYSTALS-Dilithium3) secret key — hex-encoded */
34
+ secretKey: string;
35
+ /** ML-DSA-65 public key — hex-encoded */
36
+ publicKey: string;
37
+ /** Algorithm identifier */
38
+ algorithm: 'ML-DSA-65';
39
+ }
40
+ interface HybridIdentity {
41
+ /** Standard Ed25519 identity */
42
+ classical: EpochCoreIdentity;
43
+ /** Post-quantum ML-DSA-65 public key — hex-encoded */
44
+ quantumPublicKey: string;
45
+ /** DID with quantum-resistant tag */
46
+ quantumDid: string;
47
+ }
48
+ interface HybridSignedPayload {
49
+ payload: string;
50
+ /** Ed25519 signature — hex */
51
+ classicalSignature: string;
52
+ /** ML-DSA-65 signature — hex */
53
+ quantumSignature: string;
54
+ /** Ed25519 public key — hex */
55
+ classicalPublicKey: string;
56
+ /** ML-DSA-65 public key — hex */
57
+ quantumPublicKey: string;
58
+ timestamp: string;
59
+ }
32
60
  /**
33
61
  * Generate a new Ed25519 keypair for infrastructure identity
34
62
  */
@@ -81,9 +109,44 @@ declare function generateJWKS(publicKeys: string[]): {
81
109
  kid: string;
82
110
  }>;
83
111
  };
112
+ /**
113
+ * Generate a post-quantum ML-DSA-65 keypair.
114
+ * ML-DSA-65 (Dilithium3) provides NIST Security Level 3 — resistant to
115
+ * both classical and quantum attacks (Shor's algorithm).
116
+ *
117
+ * @param seed - Optional 32-byte seed (hex). If omitted, uses CSPRNG.
118
+ */
119
+ declare function generateQuantumKeypair(seed?: string): QuantumResistantKeypair;
120
+ /**
121
+ * Generate a hybrid identity with both Ed25519 (classical) and ML-DSA-65
122
+ * (post-quantum) keys. This provides quantum-resistance while maintaining
123
+ * backward compatibility with existing Ed25519 infrastructure.
124
+ */
125
+ declare function generateQuantumResistantIdentity(type: IdentityType, name: string): Promise<{
126
+ hybrid: HybridIdentity;
127
+ classicalPrivateKey: string;
128
+ quantumSecretKey: string;
129
+ }>;
130
+ /**
131
+ * Sign a payload with both Ed25519 and ML-DSA-65 (hybrid signature).
132
+ * Verifiers can check either or both signatures — providing quantum
133
+ * safety while maintaining classical compatibility.
134
+ *
135
+ * @param payload - String data to sign
136
+ * @param classicalPrivateKey - Ed25519 private key (64 hex chars)
137
+ * @param quantumSecretKey - ML-DSA-65 secret key (hex, 8064 chars / 4032 bytes)
138
+ * @param quantumPublicKey - ML-DSA-65 public key (hex, 3904 chars / 1952 bytes)
139
+ */
140
+ declare function signPayloadHybrid(payload: string, classicalPrivateKey: string, quantumSecretKey: string, quantumPublicKey: string): Promise<HybridSignedPayload>;
141
+ /**
142
+ * Verify a hybrid signature (Ed25519 + ML-DSA-65).
143
+ * Returns true only if BOTH signatures are valid.
144
+ */
145
+ declare function verifySignatureHybrid(payload: string, classicalSignature: string, quantumSignature: string, classicalPublicKey: string, quantumPublicKey: string): Promise<boolean>;
84
146
  declare const CONSTANTS: {
85
147
  DID_PREFIX: string;
86
148
  SIGNING_ALGORITHM: string;
149
+ PQ_SIGNING_ALGORITHM: string;
87
150
  WALLET_ALGORITHM: string;
88
151
  SUPPORTED_TYPES: IdentityType[];
89
152
  VERSION: string;
@@ -91,19 +154,24 @@ declare const CONSTANTS: {
91
154
  declare const _default: {
92
155
  generateKeypair: typeof generateKeypair;
93
156
  generateIdentity: typeof generateIdentity;
157
+ generateQuantumKeypair: typeof generateQuantumKeypair;
158
+ generateQuantumResistantIdentity: typeof generateQuantumResistantIdentity;
94
159
  createDID: typeof createDID;
95
160
  parseDID: typeof parseDID;
96
161
  deriveWallet: typeof deriveWallet;
97
162
  signPayload: typeof signPayload;
163
+ signPayloadHybrid: typeof signPayloadHybrid;
98
164
  verifySignature: typeof verifySignature;
165
+ verifySignatureHybrid: typeof verifySignatureHybrid;
99
166
  generateJWKS: typeof generateJWKS;
100
167
  CONSTANTS: {
101
168
  DID_PREFIX: string;
102
169
  SIGNING_ALGORITHM: string;
170
+ PQ_SIGNING_ALGORITHM: string;
103
171
  WALLET_ALGORITHM: string;
104
172
  SUPPORTED_TYPES: IdentityType[];
105
173
  VERSION: string;
106
174
  };
107
175
  };
108
176
 
109
- export { CONSTANTS, type EpochCoreIdentity, type EpochCoreWallet, type IdentityType, type SignedPayload, createDID, _default as default, deriveWallet, generateIdentity, generateJWKS, generateKeypair, parseDID, signPayload, verifySignature };
177
+ export { CONSTANTS, type EpochCoreIdentity, type EpochCoreWallet, type HybridIdentity, type HybridSignedPayload, type IdentityType, type QuantumResistantKeypair, type SignedPayload, createDID, _default as default, deriveWallet, generateIdentity, generateJWKS, generateKeypair, generateQuantumKeypair, generateQuantumResistantIdentity, parseDID, signPayload, signPayloadHybrid, verifySignature, verifySignatureHybrid };
package/dist/index.d.ts CHANGED
@@ -29,6 +29,34 @@ interface SignedPayload {
29
29
  publicKey: string;
30
30
  timestamp: string;
31
31
  }
32
+ interface QuantumResistantKeypair {
33
+ /** ML-DSA-65 (CRYSTALS-Dilithium3) secret key — hex-encoded */
34
+ secretKey: string;
35
+ /** ML-DSA-65 public key — hex-encoded */
36
+ publicKey: string;
37
+ /** Algorithm identifier */
38
+ algorithm: 'ML-DSA-65';
39
+ }
40
+ interface HybridIdentity {
41
+ /** Standard Ed25519 identity */
42
+ classical: EpochCoreIdentity;
43
+ /** Post-quantum ML-DSA-65 public key — hex-encoded */
44
+ quantumPublicKey: string;
45
+ /** DID with quantum-resistant tag */
46
+ quantumDid: string;
47
+ }
48
+ interface HybridSignedPayload {
49
+ payload: string;
50
+ /** Ed25519 signature — hex */
51
+ classicalSignature: string;
52
+ /** ML-DSA-65 signature — hex */
53
+ quantumSignature: string;
54
+ /** Ed25519 public key — hex */
55
+ classicalPublicKey: string;
56
+ /** ML-DSA-65 public key — hex */
57
+ quantumPublicKey: string;
58
+ timestamp: string;
59
+ }
32
60
  /**
33
61
  * Generate a new Ed25519 keypair for infrastructure identity
34
62
  */
@@ -81,9 +109,44 @@ declare function generateJWKS(publicKeys: string[]): {
81
109
  kid: string;
82
110
  }>;
83
111
  };
112
+ /**
113
+ * Generate a post-quantum ML-DSA-65 keypair.
114
+ * ML-DSA-65 (Dilithium3) provides NIST Security Level 3 — resistant to
115
+ * both classical and quantum attacks (Shor's algorithm).
116
+ *
117
+ * @param seed - Optional 32-byte seed (hex). If omitted, uses CSPRNG.
118
+ */
119
+ declare function generateQuantumKeypair(seed?: string): QuantumResistantKeypair;
120
+ /**
121
+ * Generate a hybrid identity with both Ed25519 (classical) and ML-DSA-65
122
+ * (post-quantum) keys. This provides quantum-resistance while maintaining
123
+ * backward compatibility with existing Ed25519 infrastructure.
124
+ */
125
+ declare function generateQuantumResistantIdentity(type: IdentityType, name: string): Promise<{
126
+ hybrid: HybridIdentity;
127
+ classicalPrivateKey: string;
128
+ quantumSecretKey: string;
129
+ }>;
130
+ /**
131
+ * Sign a payload with both Ed25519 and ML-DSA-65 (hybrid signature).
132
+ * Verifiers can check either or both signatures — providing quantum
133
+ * safety while maintaining classical compatibility.
134
+ *
135
+ * @param payload - String data to sign
136
+ * @param classicalPrivateKey - Ed25519 private key (64 hex chars)
137
+ * @param quantumSecretKey - ML-DSA-65 secret key (hex, 8064 chars / 4032 bytes)
138
+ * @param quantumPublicKey - ML-DSA-65 public key (hex, 3904 chars / 1952 bytes)
139
+ */
140
+ declare function signPayloadHybrid(payload: string, classicalPrivateKey: string, quantumSecretKey: string, quantumPublicKey: string): Promise<HybridSignedPayload>;
141
+ /**
142
+ * Verify a hybrid signature (Ed25519 + ML-DSA-65).
143
+ * Returns true only if BOTH signatures are valid.
144
+ */
145
+ declare function verifySignatureHybrid(payload: string, classicalSignature: string, quantumSignature: string, classicalPublicKey: string, quantumPublicKey: string): Promise<boolean>;
84
146
  declare const CONSTANTS: {
85
147
  DID_PREFIX: string;
86
148
  SIGNING_ALGORITHM: string;
149
+ PQ_SIGNING_ALGORITHM: string;
87
150
  WALLET_ALGORITHM: string;
88
151
  SUPPORTED_TYPES: IdentityType[];
89
152
  VERSION: string;
@@ -91,19 +154,24 @@ declare const CONSTANTS: {
91
154
  declare const _default: {
92
155
  generateKeypair: typeof generateKeypair;
93
156
  generateIdentity: typeof generateIdentity;
157
+ generateQuantumKeypair: typeof generateQuantumKeypair;
158
+ generateQuantumResistantIdentity: typeof generateQuantumResistantIdentity;
94
159
  createDID: typeof createDID;
95
160
  parseDID: typeof parseDID;
96
161
  deriveWallet: typeof deriveWallet;
97
162
  signPayload: typeof signPayload;
163
+ signPayloadHybrid: typeof signPayloadHybrid;
98
164
  verifySignature: typeof verifySignature;
165
+ verifySignatureHybrid: typeof verifySignatureHybrid;
99
166
  generateJWKS: typeof generateJWKS;
100
167
  CONSTANTS: {
101
168
  DID_PREFIX: string;
102
169
  SIGNING_ALGORITHM: string;
170
+ PQ_SIGNING_ALGORITHM: string;
103
171
  WALLET_ALGORITHM: string;
104
172
  SUPPORTED_TYPES: IdentityType[];
105
173
  VERSION: string;
106
174
  };
107
175
  };
108
176
 
109
- export { CONSTANTS, type EpochCoreIdentity, type EpochCoreWallet, type IdentityType, type SignedPayload, createDID, _default as default, deriveWallet, generateIdentity, generateJWKS, generateKeypair, parseDID, signPayload, verifySignature };
177
+ export { CONSTANTS, type EpochCoreIdentity, type EpochCoreWallet, type HybridIdentity, type HybridSignedPayload, type IdentityType, type QuantumResistantKeypair, type SignedPayload, createDID, _default as default, deriveWallet, generateIdentity, generateJWKS, generateKeypair, generateQuantumKeypair, generateQuantumResistantIdentity, parseDID, signPayload, signPayloadHybrid, verifySignature, verifySignatureHybrid };
package/dist/index.js CHANGED
@@ -37,15 +37,20 @@ __export(index_exports, {
37
37
  generateIdentity: () => generateIdentity,
38
38
  generateJWKS: () => generateJWKS,
39
39
  generateKeypair: () => generateKeypair,
40
+ generateQuantumKeypair: () => generateQuantumKeypair,
41
+ generateQuantumResistantIdentity: () => generateQuantumResistantIdentity,
40
42
  parseDID: () => parseDID,
41
43
  signPayload: () => signPayload,
42
- verifySignature: () => verifySignature
44
+ signPayloadHybrid: () => signPayloadHybrid,
45
+ verifySignature: () => verifySignature,
46
+ verifySignatureHybrid: () => verifySignatureHybrid
43
47
  });
44
48
  module.exports = __toCommonJS(index_exports);
45
49
  var ed25519 = __toESM(require("@noble/ed25519"));
46
50
  var secp256k1 = __toESM(require("@noble/secp256k1"));
47
51
  var import_sha256 = require("@noble/hashes/sha256");
48
52
  var import_utils = require("@noble/hashes/utils");
53
+ var import_ml_dsa = require("@noble/post-quantum/ml-dsa");
49
54
  var HEX_64_RE = /^[0-9a-f]{64}$/i;
50
55
  var NAME_RE = /^[\w.-]{1,128}$/;
51
56
  var MAX_DID_LENGTH = 512;
@@ -204,21 +209,115 @@ function generateJWKS(publicKeys) {
204
209
  }))
205
210
  };
206
211
  }
212
+ function generateQuantumKeypair(seed) {
213
+ let seedBytes;
214
+ if (seed) {
215
+ if (typeof seed !== "string" || !/^[0-9a-f]{64}$/i.test(seed)) {
216
+ throw new TypeError("seed must be a 64-character hex string (32 bytes)");
217
+ }
218
+ seedBytes = (0, import_utils.hexToBytes)(seed);
219
+ } else {
220
+ seedBytes = new Uint8Array(32);
221
+ globalThis.crypto.getRandomValues(seedBytes);
222
+ }
223
+ const { secretKey, publicKey } = import_ml_dsa.ml_dsa65.keygen(seedBytes);
224
+ return {
225
+ secretKey: (0, import_utils.bytesToHex)(secretKey),
226
+ publicKey: (0, import_utils.bytesToHex)(publicKey),
227
+ algorithm: "ML-DSA-65"
228
+ };
229
+ }
230
+ async function generateQuantumResistantIdentity(type, name) {
231
+ validateType(type);
232
+ validateName(name);
233
+ const { identity, privateKey: classicalPrivateKey } = await generateIdentity(type, name);
234
+ const quantumKeypair = generateQuantumKeypair();
235
+ const qFingerprint = (0, import_utils.bytesToHex)((0, import_sha256.sha256)((0, import_utils.hexToBytes)(quantumKeypair.publicKey.slice(0, 64)))).slice(0, 32);
236
+ const quantumDid = `did:epochcore:pq:${type}:${name}:${qFingerprint}`;
237
+ return {
238
+ hybrid: {
239
+ classical: identity,
240
+ quantumPublicKey: quantumKeypair.publicKey,
241
+ quantumDid
242
+ },
243
+ classicalPrivateKey,
244
+ quantumSecretKey: quantumKeypair.secretKey
245
+ };
246
+ }
247
+ async function signPayloadHybrid(payload, classicalPrivateKey, quantumSecretKey, quantumPublicKey) {
248
+ if (typeof payload !== "string" || payload.length === 0) {
249
+ throw new TypeError("payload must be a non-empty string");
250
+ }
251
+ const payloadBytes = new TextEncoder().encode(payload);
252
+ if (payloadBytes.byteLength > MAX_PAYLOAD_BYTES) {
253
+ throw new RangeError(`payload exceeds maximum size of ${MAX_PAYLOAD_BYTES} bytes`);
254
+ }
255
+ validateHex64(classicalPrivateKey, "classicalPrivateKey");
256
+ if (typeof quantumSecretKey !== "string" || quantumSecretKey.length === 0) {
257
+ throw new TypeError("quantumSecretKey must be a non-empty hex string");
258
+ }
259
+ if (typeof quantumPublicKey !== "string" || quantumPublicKey.length === 0) {
260
+ throw new TypeError("quantumPublicKey must be a non-empty hex string");
261
+ }
262
+ const classicalSig = await ed25519.signAsync(payloadBytes, (0, import_utils.hexToBytes)(classicalPrivateKey));
263
+ const classicalPub = await ed25519.getPublicKeyAsync((0, import_utils.hexToBytes)(classicalPrivateKey));
264
+ const quantumSig = import_ml_dsa.ml_dsa65.sign((0, import_utils.hexToBytes)(quantumSecretKey), payloadBytes);
265
+ return {
266
+ payload,
267
+ classicalSignature: (0, import_utils.bytesToHex)(classicalSig),
268
+ quantumSignature: (0, import_utils.bytesToHex)(quantumSig),
269
+ classicalPublicKey: (0, import_utils.bytesToHex)(classicalPub),
270
+ quantumPublicKey,
271
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
272
+ };
273
+ }
274
+ async function verifySignatureHybrid(payload, classicalSignature, quantumSignature, classicalPublicKey, quantumPublicKey) {
275
+ if (typeof payload !== "string" || payload.length === 0) {
276
+ throw new TypeError("payload must be a non-empty string");
277
+ }
278
+ const payloadBytes = new TextEncoder().encode(payload);
279
+ if (typeof classicalSignature !== "string" || !/^[0-9a-f]{128}$/i.test(classicalSignature)) {
280
+ throw new TypeError("classicalSignature must be a 128-character hex string");
281
+ }
282
+ validateHex64(classicalPublicKey, "classicalPublicKey");
283
+ const classicalValid = await ed25519.verifyAsync(
284
+ (0, import_utils.hexToBytes)(classicalSignature),
285
+ payloadBytes,
286
+ (0, import_utils.hexToBytes)(classicalPublicKey)
287
+ );
288
+ if (typeof quantumSignature !== "string" || quantumSignature.length === 0) {
289
+ throw new TypeError("quantumSignature must be a non-empty hex string");
290
+ }
291
+ if (typeof quantumPublicKey !== "string" || quantumPublicKey.length === 0) {
292
+ throw new TypeError("quantumPublicKey must be a non-empty hex string");
293
+ }
294
+ const quantumValid = import_ml_dsa.ml_dsa65.verify(
295
+ (0, import_utils.hexToBytes)(quantumPublicKey),
296
+ payloadBytes,
297
+ (0, import_utils.hexToBytes)(quantumSignature)
298
+ );
299
+ return classicalValid && quantumValid;
300
+ }
207
301
  var CONSTANTS = {
208
302
  DID_PREFIX: "did:epochcore",
209
303
  SIGNING_ALGORITHM: "Ed25519",
304
+ PQ_SIGNING_ALGORITHM: "ML-DSA-65",
210
305
  WALLET_ALGORITHM: "secp256k1",
211
306
  SUPPORTED_TYPES: ["worker", "database", "storage", "durable_object", "daemon"],
212
- VERSION: "1.1.0"
307
+ VERSION: "1.2.0"
213
308
  };
214
309
  var index_default = {
215
310
  generateKeypair,
216
311
  generateIdentity,
312
+ generateQuantumKeypair,
313
+ generateQuantumResistantIdentity,
217
314
  createDID,
218
315
  parseDID,
219
316
  deriveWallet,
220
317
  signPayload,
318
+ signPayloadHybrid,
221
319
  verifySignature,
320
+ verifySignatureHybrid,
222
321
  generateJWKS,
223
322
  CONSTANTS
224
323
  };
@@ -230,7 +329,11 @@ var index_default = {
230
329
  generateIdentity,
231
330
  generateJWKS,
232
331
  generateKeypair,
332
+ generateQuantumKeypair,
333
+ generateQuantumResistantIdentity,
233
334
  parseDID,
234
335
  signPayload,
235
- verifySignature
336
+ signPayloadHybrid,
337
+ verifySignature,
338
+ verifySignatureHybrid
236
339
  });
package/dist/index.mjs CHANGED
@@ -3,6 +3,7 @@ import * as ed25519 from "@noble/ed25519";
3
3
  import * as secp256k1 from "@noble/secp256k1";
4
4
  import { sha256 } from "@noble/hashes/sha256";
5
5
  import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
6
+ import { ml_dsa65 } from "@noble/post-quantum/ml-dsa";
6
7
  var HEX_64_RE = /^[0-9a-f]{64}$/i;
7
8
  var NAME_RE = /^[\w.-]{1,128}$/;
8
9
  var MAX_DID_LENGTH = 512;
@@ -161,21 +162,115 @@ function generateJWKS(publicKeys) {
161
162
  }))
162
163
  };
163
164
  }
165
+ function generateQuantumKeypair(seed) {
166
+ let seedBytes;
167
+ if (seed) {
168
+ if (typeof seed !== "string" || !/^[0-9a-f]{64}$/i.test(seed)) {
169
+ throw new TypeError("seed must be a 64-character hex string (32 bytes)");
170
+ }
171
+ seedBytes = hexToBytes(seed);
172
+ } else {
173
+ seedBytes = new Uint8Array(32);
174
+ globalThis.crypto.getRandomValues(seedBytes);
175
+ }
176
+ const { secretKey, publicKey } = ml_dsa65.keygen(seedBytes);
177
+ return {
178
+ secretKey: bytesToHex(secretKey),
179
+ publicKey: bytesToHex(publicKey),
180
+ algorithm: "ML-DSA-65"
181
+ };
182
+ }
183
+ async function generateQuantumResistantIdentity(type, name) {
184
+ validateType(type);
185
+ validateName(name);
186
+ const { identity, privateKey: classicalPrivateKey } = await generateIdentity(type, name);
187
+ const quantumKeypair = generateQuantumKeypair();
188
+ const qFingerprint = bytesToHex(sha256(hexToBytes(quantumKeypair.publicKey.slice(0, 64)))).slice(0, 32);
189
+ const quantumDid = `did:epochcore:pq:${type}:${name}:${qFingerprint}`;
190
+ return {
191
+ hybrid: {
192
+ classical: identity,
193
+ quantumPublicKey: quantumKeypair.publicKey,
194
+ quantumDid
195
+ },
196
+ classicalPrivateKey,
197
+ quantumSecretKey: quantumKeypair.secretKey
198
+ };
199
+ }
200
+ async function signPayloadHybrid(payload, classicalPrivateKey, quantumSecretKey, quantumPublicKey) {
201
+ if (typeof payload !== "string" || payload.length === 0) {
202
+ throw new TypeError("payload must be a non-empty string");
203
+ }
204
+ const payloadBytes = new TextEncoder().encode(payload);
205
+ if (payloadBytes.byteLength > MAX_PAYLOAD_BYTES) {
206
+ throw new RangeError(`payload exceeds maximum size of ${MAX_PAYLOAD_BYTES} bytes`);
207
+ }
208
+ validateHex64(classicalPrivateKey, "classicalPrivateKey");
209
+ if (typeof quantumSecretKey !== "string" || quantumSecretKey.length === 0) {
210
+ throw new TypeError("quantumSecretKey must be a non-empty hex string");
211
+ }
212
+ if (typeof quantumPublicKey !== "string" || quantumPublicKey.length === 0) {
213
+ throw new TypeError("quantumPublicKey must be a non-empty hex string");
214
+ }
215
+ const classicalSig = await ed25519.signAsync(payloadBytes, hexToBytes(classicalPrivateKey));
216
+ const classicalPub = await ed25519.getPublicKeyAsync(hexToBytes(classicalPrivateKey));
217
+ const quantumSig = ml_dsa65.sign(hexToBytes(quantumSecretKey), payloadBytes);
218
+ return {
219
+ payload,
220
+ classicalSignature: bytesToHex(classicalSig),
221
+ quantumSignature: bytesToHex(quantumSig),
222
+ classicalPublicKey: bytesToHex(classicalPub),
223
+ quantumPublicKey,
224
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
225
+ };
226
+ }
227
+ async function verifySignatureHybrid(payload, classicalSignature, quantumSignature, classicalPublicKey, quantumPublicKey) {
228
+ if (typeof payload !== "string" || payload.length === 0) {
229
+ throw new TypeError("payload must be a non-empty string");
230
+ }
231
+ const payloadBytes = new TextEncoder().encode(payload);
232
+ if (typeof classicalSignature !== "string" || !/^[0-9a-f]{128}$/i.test(classicalSignature)) {
233
+ throw new TypeError("classicalSignature must be a 128-character hex string");
234
+ }
235
+ validateHex64(classicalPublicKey, "classicalPublicKey");
236
+ const classicalValid = await ed25519.verifyAsync(
237
+ hexToBytes(classicalSignature),
238
+ payloadBytes,
239
+ hexToBytes(classicalPublicKey)
240
+ );
241
+ if (typeof quantumSignature !== "string" || quantumSignature.length === 0) {
242
+ throw new TypeError("quantumSignature must be a non-empty hex string");
243
+ }
244
+ if (typeof quantumPublicKey !== "string" || quantumPublicKey.length === 0) {
245
+ throw new TypeError("quantumPublicKey must be a non-empty hex string");
246
+ }
247
+ const quantumValid = ml_dsa65.verify(
248
+ hexToBytes(quantumPublicKey),
249
+ payloadBytes,
250
+ hexToBytes(quantumSignature)
251
+ );
252
+ return classicalValid && quantumValid;
253
+ }
164
254
  var CONSTANTS = {
165
255
  DID_PREFIX: "did:epochcore",
166
256
  SIGNING_ALGORITHM: "Ed25519",
257
+ PQ_SIGNING_ALGORITHM: "ML-DSA-65",
167
258
  WALLET_ALGORITHM: "secp256k1",
168
259
  SUPPORTED_TYPES: ["worker", "database", "storage", "durable_object", "daemon"],
169
- VERSION: "1.1.0"
260
+ VERSION: "1.2.0"
170
261
  };
171
262
  var index_default = {
172
263
  generateKeypair,
173
264
  generateIdentity,
265
+ generateQuantumKeypair,
266
+ generateQuantumResistantIdentity,
174
267
  createDID,
175
268
  parseDID,
176
269
  deriveWallet,
177
270
  signPayload,
271
+ signPayloadHybrid,
178
272
  verifySignature,
273
+ verifySignatureHybrid,
179
274
  generateJWKS,
180
275
  CONSTANTS
181
276
  };
@@ -187,7 +282,11 @@ export {
187
282
  generateIdentity,
188
283
  generateJWKS,
189
284
  generateKeypair,
285
+ generateQuantumKeypair,
286
+ generateQuantumResistantIdentity,
190
287
  parseDID,
191
288
  signPayload,
192
- verifySignature
289
+ signPayloadHybrid,
290
+ verifySignature,
291
+ verifySignatureHybrid
193
292
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@epochcore/identity-sdk",
3
- "version": "1.1.0",
4
- "description": "World's First Universal Infrastructure Identity SDK - Ed25519 cryptographic identities for workers, databases, storage, and daemons",
3
+ "version": "1.2.0",
4
+ "description": "World's First Universal Infrastructure Identity SDK - Ed25519 + ML-DSA-65 (post-quantum) cryptographic identities for workers, databases, storage, and daemons",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -13,7 +13,7 @@
13
13
  }
14
14
  },
15
15
  "scripts": {
16
- "build": "tsup src/index.ts --format cjs,esm --dts --clean --external @noble/ed25519 --external @noble/secp256k1 --external @noble/hashes",
16
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean --external @noble/ed25519 --external @noble/secp256k1 --external @noble/hashes --external @noble/post-quantum",
17
17
  "test": "vitest run",
18
18
  "prepublishOnly": "npm run build"
19
19
  },
@@ -23,6 +23,9 @@
23
23
  "infrastructure",
24
24
  "ed25519",
25
25
  "secp256k1",
26
+ "ml-dsa",
27
+ "dilithium",
28
+ "post-quantum",
26
29
  "web3",
27
30
  "cloudflare-workers",
28
31
  "quantum",
@@ -38,7 +41,8 @@
38
41
  "dependencies": {
39
42
  "@noble/ed25519": "^2.0.0",
40
43
  "@noble/secp256k1": "^2.0.0",
41
- "@noble/hashes": "^1.3.0"
44
+ "@noble/hashes": "^1.3.0",
45
+ "@noble/post-quantum": "^0.2.0"
42
46
  },
43
47
  "devDependencies": {
44
48
  "tsup": "^8.0.0",