@smartledger/keys 3.1.1 → 4.0.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/README.md +46 -13
- package/dist/cjs/sdk.d.ts +25 -4
- package/dist/cjs/sdk.d.ts.map +1 -1
- package/dist/cjs/sdk.js +40 -20
- package/dist/cjs/sdk.js.map +1 -1
- package/dist/cjs/types.d.ts +13 -0
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/sdk.d.ts +25 -4
- package/dist/esm/sdk.d.ts.map +1 -1
- package/dist/esm/sdk.js +39 -19
- package/dist/esm/sdk.js.map +1 -1
- package/dist/esm/types.d.ts +13 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/types.js.map +1 -1
- package/dist/lumen-keys.js +56 -24
- package/dist/lumen-keys.min.js +3 -3
- package/dist/lumen-keys.min.js.map +3 -3
- package/package.json +5 -3
package/dist/lumen-keys.js
CHANGED
|
@@ -7848,14 +7848,19 @@ zoo`.split("\n"));
|
|
|
7848
7848
|
publicKey
|
|
7849
7849
|
};
|
|
7850
7850
|
}
|
|
7851
|
-
async sign(privateKey, message) {
|
|
7851
|
+
async sign(privateKey, message, options = {}) {
|
|
7852
|
+
if (options.context !== void 0 && !(options.context instanceof Uint8Array && options.context.length === 0)) {
|
|
7853
|
+
throw new Error("BsvEcdsaSuite: ECDSA has no context string; bind the context into the message instead");
|
|
7854
|
+
}
|
|
7852
7855
|
try {
|
|
7853
7856
|
return sign(message, privateKey, { prehash: false });
|
|
7854
7857
|
} catch (error) {
|
|
7855
7858
|
throw new Error(`BsvEcdsaSuite signing failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
7856
7859
|
}
|
|
7857
7860
|
}
|
|
7858
|
-
async verify(publicKey, message, signature) {
|
|
7861
|
+
async verify(publicKey, message, signature, options = {}) {
|
|
7862
|
+
if (options.context !== void 0 && !(options.context instanceof Uint8Array && options.context.length === 0))
|
|
7863
|
+
return false;
|
|
7859
7864
|
try {
|
|
7860
7865
|
return verify(signature, message, publicKey, { prehash: false }) === true;
|
|
7861
7866
|
} catch (error) {
|
|
@@ -7920,6 +7925,16 @@ zoo`.split("\n"));
|
|
|
7920
7925
|
}
|
|
7921
7926
|
return ml_dsa87_lib;
|
|
7922
7927
|
}
|
|
7928
|
+
function contextOption(options) {
|
|
7929
|
+
const context = options.context;
|
|
7930
|
+
if (context === void 0)
|
|
7931
|
+
return void 0;
|
|
7932
|
+
if (!(context instanceof Uint8Array))
|
|
7933
|
+
throw new Error("context must be a Uint8Array");
|
|
7934
|
+
if (context.length > 255)
|
|
7935
|
+
throw new Error("context must be at most 255 bytes");
|
|
7936
|
+
return context.length === 0 ? void 0 : { context };
|
|
7937
|
+
}
|
|
7923
7938
|
var ML_DSA_SIZES = {
|
|
7924
7939
|
"ml-dsa-44": { publicKey: 1312, privateKey: 2560, signature: 2420 },
|
|
7925
7940
|
"ml-dsa-65": { publicKey: 1952, privateKey: 4032, signature: 3309 },
|
|
@@ -7944,21 +7959,21 @@ zoo`.split("\n"));
|
|
|
7944
7959
|
throw new Error(`${this.suiteId} key generation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
7945
7960
|
}
|
|
7946
7961
|
}
|
|
7947
|
-
async sign(privateKey, message) {
|
|
7962
|
+
async sign(privateKey, message, options = {}) {
|
|
7948
7963
|
try {
|
|
7949
7964
|
const lib = await this.getLib();
|
|
7950
|
-
return lib.sign(message, privateKey);
|
|
7965
|
+
return lib.sign(message, privateKey, contextOption(options));
|
|
7951
7966
|
} catch (error) {
|
|
7952
7967
|
throw new Error(`${this.suiteId} signing failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
7953
7968
|
}
|
|
7954
7969
|
}
|
|
7955
|
-
async verify(publicKey, message, signature) {
|
|
7970
|
+
async verify(publicKey, message, signature, options = {}) {
|
|
7956
7971
|
try {
|
|
7957
7972
|
const lib = await this.getLib();
|
|
7958
7973
|
if (publicKey.length !== this.sizes.publicKey || signature.length !== this.sizes.signature) {
|
|
7959
7974
|
return false;
|
|
7960
7975
|
}
|
|
7961
|
-
return lib.verify(signature, message, publicKey) === true;
|
|
7976
|
+
return lib.verify(signature, message, publicKey, contextOption(options)) === true;
|
|
7962
7977
|
} catch (error) {
|
|
7963
7978
|
return false;
|
|
7964
7979
|
}
|
|
@@ -8429,6 +8444,7 @@ zoo`.split("\n"));
|
|
|
8429
8444
|
};
|
|
8430
8445
|
|
|
8431
8446
|
// src/sdk.ts
|
|
8447
|
+
var DEFAULT_SIGNING_CONTEXT = "@smartledger/keys/4";
|
|
8432
8448
|
var COUNTER_SUFFIX = /^pk-[^:-]+-(\d+)$/;
|
|
8433
8449
|
var MAX_KEY_ID_ATTEMPTS = 8;
|
|
8434
8450
|
function assertAgentId(agentId) {
|
|
@@ -8453,6 +8469,12 @@ zoo`.split("\n"));
|
|
|
8453
8469
|
this.getOrCreateInFlight = /* @__PURE__ */ new Map();
|
|
8454
8470
|
this.keyRegistry = config.keyRegistry;
|
|
8455
8471
|
this.suiteRegistry = config.suiteRegistry;
|
|
8472
|
+
const context = config.signingContext ?? DEFAULT_SIGNING_CONTEXT;
|
|
8473
|
+
const bytes = typeof context === "string" ? new TextEncoder().encode(context) : Uint8Array.from(context);
|
|
8474
|
+
if (bytes.length < 1 || bytes.length > 255) {
|
|
8475
|
+
throw new Error("signingContext must be 1 to 255 bytes");
|
|
8476
|
+
}
|
|
8477
|
+
this.signingContext = bytes;
|
|
8456
8478
|
}
|
|
8457
8479
|
/**
|
|
8458
8480
|
* Create a new key for an agent.
|
|
@@ -8518,9 +8540,29 @@ Consider using one of these suites or remove the derivationContext option.` : `N
|
|
|
8518
8540
|
);
|
|
8519
8541
|
}
|
|
8520
8542
|
const suite = this.suiteRegistry.getSuite(result.meta.suiteId);
|
|
8521
|
-
const
|
|
8522
|
-
|
|
8523
|
-
|
|
8543
|
+
const { input, options } = await this.signingInput(result.meta.suiteId, message, "v4");
|
|
8544
|
+
return await suite.sign(result.keypair.privateKey, input, options);
|
|
8545
|
+
}
|
|
8546
|
+
/**
|
|
8547
|
+
* What a key of `suiteId` signs for `message` under a scheme.
|
|
8548
|
+
*
|
|
8549
|
+
* v4: ML-DSA signs the message itself in FIPS 204 pure mode with this SDK's
|
|
8550
|
+
* context string, so a standard verifier needs only the message and the
|
|
8551
|
+
* context, and the signature is not limited by an outside digest. ECDSA
|
|
8552
|
+
* signs SHA-256(message): ECDSA signs a digest by definition and has no
|
|
8553
|
+
* context, so callers who need domain separation for it put the purpose in
|
|
8554
|
+
* the message.
|
|
8555
|
+
*
|
|
8556
|
+
* v3-digest: what 3.x signed — SHA3-256(message) for ML-DSA, empty context.
|
|
8557
|
+
*/
|
|
8558
|
+
async signingInput(suiteId, message, scheme) {
|
|
8559
|
+
if (scheme !== "v4" && scheme !== "v3-digest") {
|
|
8560
|
+
throw new Error(`Unknown signature scheme: ${String(scheme)}`);
|
|
8561
|
+
}
|
|
8562
|
+
if (suiteId.startsWith("ml-dsa")) {
|
|
8563
|
+
return scheme === "v4" ? { input: message, options: { context: this.signingContext } } : { input: await hashBytes(message, "sha3-256") };
|
|
8564
|
+
}
|
|
8565
|
+
return { input: await hashBytes(message, "sha256") };
|
|
8524
8566
|
}
|
|
8525
8567
|
/**
|
|
8526
8568
|
* Verify a signature.
|
|
@@ -8538,15 +8580,14 @@ Consider using one of these suites or remove the derivationContext option.` : `N
|
|
|
8538
8580
|
if (!statusAllows(result.meta, options.keyStatus ?? "any")) {
|
|
8539
8581
|
return false;
|
|
8540
8582
|
}
|
|
8541
|
-
return this.verifyAgainst(result.meta, result.publicKey, message, signature);
|
|
8583
|
+
return this.verifyAgainst(result.meta, result.publicKey, message, signature, options.scheme ?? "v4");
|
|
8542
8584
|
}
|
|
8543
8585
|
/** The cryptographic check alone. Anything but a strict `true` is a failure. */
|
|
8544
|
-
async verifyAgainst(meta, publicKey, message, signature) {
|
|
8586
|
+
async verifyAgainst(meta, publicKey, message, signature, scheme = "v4") {
|
|
8545
8587
|
try {
|
|
8546
8588
|
const suite = this.suiteRegistry.getSuite(meta.suiteId);
|
|
8547
|
-
const
|
|
8548
|
-
|
|
8549
|
-
return await suite.verify(publicKey, messageHash, signature) === true;
|
|
8589
|
+
const { input, options } = await this.signingInput(meta.suiteId, message, scheme);
|
|
8590
|
+
return await suite.verify(publicKey, input, signature, options) === true;
|
|
8550
8591
|
} catch {
|
|
8551
8592
|
return false;
|
|
8552
8593
|
}
|
|
@@ -8790,7 +8831,7 @@ Consider using one of these suites or remove the derivationContext option.` : `N
|
|
|
8790
8831
|
fail("Signature must be a Uint8Array");
|
|
8791
8832
|
continue;
|
|
8792
8833
|
}
|
|
8793
|
-
const valid = await this.verifyAgainst(key.meta, key.publicKey, message, entry.signature);
|
|
8834
|
+
const valid = await this.verifyAgainst(key.meta, key.publicKey, message, entry.signature, options.scheme ?? "v4");
|
|
8794
8835
|
if (valid) {
|
|
8795
8836
|
results.push({ suiteId, keyId, valid: true });
|
|
8796
8837
|
} else {
|
|
@@ -8948,15 +8989,6 @@ Consider using one of these suites or remove the derivationContext option.` : `N
|
|
|
8948
8989
|
options
|
|
8949
8990
|
);
|
|
8950
8991
|
}
|
|
8951
|
-
/**
|
|
8952
|
-
* Helper: Get hash algorithm for a suite.
|
|
8953
|
-
*/
|
|
8954
|
-
getHashAlgorithm(suiteId) {
|
|
8955
|
-
if (suiteId.startsWith("ml-dsa")) {
|
|
8956
|
-
return "sha3-256";
|
|
8957
|
-
}
|
|
8958
|
-
return "sha256";
|
|
8959
|
-
}
|
|
8960
8992
|
/**
|
|
8961
8993
|
* Helper: register a key under the agent's next free key ID.
|
|
8962
8994
|
*
|