@calimero-network/mero-js 22.5.0 → 22.6.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.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +144 -19
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/index.mjs +144 -19
- package/dist/index.mjs.map +4 -4
- package/dist/namespace-op/namespace-op.d.ts +5 -1
- package/dist/namespace-op/namespace-op.js +5 -1
- package/dist/relay/relay-client.d.ts +18 -1
- package/dist/relay/relay-client.js +18 -3
- package/dist/signer/index.d.ts +2 -0
- package/dist/signer/index.js +3 -0
- package/dist/signer/signer.d.ts +92 -0
- package/dist/signer/signer.js +147 -0
- package/dist/warrant/creation-warrant.d.ts +17 -3
- package/dist/warrant/creation-warrant.js +6 -5
- package/dist/warrant/governance-warrant.d.ts +17 -3
- package/dist/warrant/governance-warrant.js +6 -5
- package/dist/warrant/warrant.d.ts +20 -1
- package/dist/warrant/warrant.js +19 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export * from "./cloud/index.js";
|
|
|
19
19
|
export * from "./sealed/index.js";
|
|
20
20
|
export * from "./relay/index.js";
|
|
21
21
|
export { signWarrant, intentHash, signCreationWarrant, parseCreationWarrant, creationInitHash, signGovernanceWarrant, parseGovernanceWarrant, governanceOpHash, memberAddedOp, memberRemovedOp, memberLeftOp, memberRoleSetOp, groupCreatedOp, groupReparentedOp, groupDeletedOp, } from "./warrant/index.js";
|
|
22
|
+
export { signerFromSecret, signerFromCryptoKey } from "./signer/index.js";
|
|
23
|
+
export type { Signer } from "./signer/index.js";
|
|
22
24
|
export { generateAccountRoot, accountRootFromPhrase, accountRootFromSecret, signAccountLink, signAccountLogin, } from "./account/index.js";
|
|
23
25
|
export type { AccountRoot, RecoverableAccountRoot, AccountLinkInput, AccountLoginInput, } from "./account/index.js";
|
|
24
26
|
export { signDeviceCert, mintDeviceId, deviceCertPayload, accountForRoot, } from "./device-cert/index.js";
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,9 @@ export * from "./sealed/index.js";
|
|
|
28
28
|
export * from "./relay/index.js";
|
|
29
29
|
// Warrant signing — mint the author's consent for a relay to run one intent
|
|
30
30
|
export { signWarrant, intentHash, signCreationWarrant, parseCreationWarrant, creationInitHash, signGovernanceWarrant, parseGovernanceWarrant, governanceOpHash, memberAddedOp, memberRemovedOp, memberLeftOp, memberRoleSetOp, groupCreatedOp, groupReparentedOp, groupDeletedOp, } from "./warrant/index.js";
|
|
31
|
+
// Who signs — a key's capability, separated from its material, so a
|
|
32
|
+
// non-extractable key can be used wherever a hex secret could.
|
|
33
|
+
export { signerFromSecret, signerFromCryptoKey } from "./signer/index.js";
|
|
31
34
|
// Account roots — mint one with a recovery phrase, or prove you hold one
|
|
32
35
|
export { generateAccountRoot, accountRootFromPhrase, accountRootFromSecret, signAccountLink, signAccountLogin, } from "./account/index.js";
|
|
33
36
|
export { signDeviceCert, mintDeviceId, deviceCertPayload, accountForRoot, } from "./device-cert/index.js";
|
package/dist/index.mjs
CHANGED
|
@@ -6449,6 +6449,117 @@ var LocalStorageTokenStore = class {
|
|
|
6449
6449
|
}
|
|
6450
6450
|
};
|
|
6451
6451
|
|
|
6452
|
+
// src/signer/signer.ts
|
|
6453
|
+
var PKCS8_ED25519_PREFIX2 = new Uint8Array([
|
|
6454
|
+
48,
|
|
6455
|
+
46,
|
|
6456
|
+
2,
|
|
6457
|
+
1,
|
|
6458
|
+
0,
|
|
6459
|
+
48,
|
|
6460
|
+
5,
|
|
6461
|
+
6,
|
|
6462
|
+
3,
|
|
6463
|
+
43,
|
|
6464
|
+
101,
|
|
6465
|
+
112,
|
|
6466
|
+
4,
|
|
6467
|
+
34,
|
|
6468
|
+
4,
|
|
6469
|
+
32
|
|
6470
|
+
]);
|
|
6471
|
+
function unsupported(cause) {
|
|
6472
|
+
const detail = cause instanceof Error ? `: ${cause.message}` : "";
|
|
6473
|
+
return new Error(
|
|
6474
|
+
"this runtime has no WebCrypto Ed25519, so nothing can be signed here. Node 18.4+, Safari 17+, Firefox 129+ and Chrome 137+ have it" + detail
|
|
6475
|
+
);
|
|
6476
|
+
}
|
|
6477
|
+
async function signerFromSecret(secret, label2 = "secret") {
|
|
6478
|
+
const seed = fromHex(secret, label2, 32);
|
|
6479
|
+
const pkcs8 = concat(PKCS8_ED25519_PREFIX2, seed);
|
|
6480
|
+
let privateKey;
|
|
6481
|
+
let publicKey;
|
|
6482
|
+
try {
|
|
6483
|
+
const exportable = await crypto.subtle.importKey(
|
|
6484
|
+
"pkcs8",
|
|
6485
|
+
pkcs8,
|
|
6486
|
+
{ name: "Ed25519" },
|
|
6487
|
+
true,
|
|
6488
|
+
["sign"]
|
|
6489
|
+
);
|
|
6490
|
+
const jwk = await crypto.subtle.exportKey("jwk", exportable);
|
|
6491
|
+
publicKey = hex(
|
|
6492
|
+
Uint8Array.from(
|
|
6493
|
+
atob(jwk.x.replace(/-/g, "+").replace(/_/g, "/")),
|
|
6494
|
+
(c) => c.charCodeAt(0)
|
|
6495
|
+
)
|
|
6496
|
+
);
|
|
6497
|
+
privateKey = await crypto.subtle.importKey(
|
|
6498
|
+
"pkcs8",
|
|
6499
|
+
pkcs8,
|
|
6500
|
+
{ name: "Ed25519" },
|
|
6501
|
+
false,
|
|
6502
|
+
["sign"]
|
|
6503
|
+
);
|
|
6504
|
+
} catch (cause) {
|
|
6505
|
+
throw unsupported(cause);
|
|
6506
|
+
}
|
|
6507
|
+
return fromKeyAndPublic(privateKey, publicKey);
|
|
6508
|
+
}
|
|
6509
|
+
async function signerFromCryptoKey(privateKey, publicKey) {
|
|
6510
|
+
if (privateKey.type !== "private") {
|
|
6511
|
+
throw new Error(
|
|
6512
|
+
`signerFromCryptoKey needs the private half of the pair, got a ${privateKey.type} key`
|
|
6513
|
+
);
|
|
6514
|
+
}
|
|
6515
|
+
if (!privateKey.usages.includes("sign")) {
|
|
6516
|
+
throw new Error(
|
|
6517
|
+
"this CryptoKey cannot sign: generate it with usages ['sign', 'verify']"
|
|
6518
|
+
);
|
|
6519
|
+
}
|
|
6520
|
+
let publicHex;
|
|
6521
|
+
if (typeof publicKey === "string") {
|
|
6522
|
+
fromHex(publicKey, "publicKey", 32);
|
|
6523
|
+
publicHex = publicKey.trim().toLowerCase();
|
|
6524
|
+
} else {
|
|
6525
|
+
try {
|
|
6526
|
+
publicHex = hex(
|
|
6527
|
+
new Uint8Array(await crypto.subtle.exportKey("raw", publicKey))
|
|
6528
|
+
);
|
|
6529
|
+
} catch (cause) {
|
|
6530
|
+
const detail = cause instanceof Error ? `: ${cause.message}` : "";
|
|
6531
|
+
throw new Error(
|
|
6532
|
+
"could not read the public half of this key pair; pass the public key as 64 hex instead" + detail
|
|
6533
|
+
);
|
|
6534
|
+
}
|
|
6535
|
+
}
|
|
6536
|
+
return fromKeyAndPublic(privateKey, publicHex);
|
|
6537
|
+
}
|
|
6538
|
+
function fromKeyAndPublic(privateKey, publicKey) {
|
|
6539
|
+
return {
|
|
6540
|
+
publicKey,
|
|
6541
|
+
async sign(payload) {
|
|
6542
|
+
try {
|
|
6543
|
+
return new Uint8Array(
|
|
6544
|
+
await crypto.subtle.sign({ name: "Ed25519" }, privateKey, payload)
|
|
6545
|
+
);
|
|
6546
|
+
} catch (cause) {
|
|
6547
|
+
throw unsupported(cause);
|
|
6548
|
+
}
|
|
6549
|
+
}
|
|
6550
|
+
};
|
|
6551
|
+
}
|
|
6552
|
+
async function resolveSigner(secret, signer, label2) {
|
|
6553
|
+
if (signer && secret !== void 0) {
|
|
6554
|
+
throw new Error(
|
|
6555
|
+
`pass either ${label2} or signer, not both \u2014 they may name different keys`
|
|
6556
|
+
);
|
|
6557
|
+
}
|
|
6558
|
+
if (signer) return signer;
|
|
6559
|
+
if (secret !== void 0) return signerFromSecret(secret, label2);
|
|
6560
|
+
throw new Error(`${label2} or signer is required`);
|
|
6561
|
+
}
|
|
6562
|
+
|
|
6452
6563
|
// src/warrant/warrant.ts
|
|
6453
6564
|
var SIGN_DOMAIN2 = new TextEncoder().encode("calimero.warrant.v2");
|
|
6454
6565
|
var INTENT_DOMAIN = new TextEncoder().encode("calimero.warrant.intent.v1");
|
|
@@ -6469,8 +6580,8 @@ async function signWarrant(input) {
|
|
|
6469
6580
|
);
|
|
6470
6581
|
const accountHeads = citedHeads(input.accountHeads, "accountHeads");
|
|
6471
6582
|
const governanceFloor = citedHeads(input.governanceFloor, "governanceFloor");
|
|
6472
|
-
const
|
|
6473
|
-
const publicKey =
|
|
6583
|
+
const signer = await resolveSigner(input.deviceSecret, input.signer, "deviceSecret");
|
|
6584
|
+
const publicKey = fromHex(signer.publicKey, "signer.publicKey", 32);
|
|
6474
6585
|
const method = new TextEncoder().encode(input.method);
|
|
6475
6586
|
const commitment = await intentHash(input.method, input.argsJson);
|
|
6476
6587
|
const nonce2 = u64le(input.nonce);
|
|
@@ -6490,9 +6601,7 @@ async function signWarrant(input) {
|
|
|
6490
6601
|
nonce2,
|
|
6491
6602
|
notAfter
|
|
6492
6603
|
]);
|
|
6493
|
-
const signature =
|
|
6494
|
-
await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
|
|
6495
|
-
);
|
|
6604
|
+
const signature = checkedSignature(await signer.sign(preimage));
|
|
6496
6605
|
return hex(
|
|
6497
6606
|
concat(
|
|
6498
6607
|
context,
|
|
@@ -6513,6 +6622,13 @@ async function signWarrant(input) {
|
|
|
6513
6622
|
)
|
|
6514
6623
|
);
|
|
6515
6624
|
}
|
|
6625
|
+
function checkedSignature(signature) {
|
|
6626
|
+
if (!(signature instanceof Uint8Array) || signature.length !== 64) {
|
|
6627
|
+
const got = signature instanceof Uint8Array ? `${signature.length} bytes` : typeof signature;
|
|
6628
|
+
throw new Error(`signer returned ${got}, expected a 64-byte Ed25519 signature`);
|
|
6629
|
+
}
|
|
6630
|
+
return signature;
|
|
6631
|
+
}
|
|
6516
6632
|
function citedHeads(heads, label2) {
|
|
6517
6633
|
const list = heads ?? [];
|
|
6518
6634
|
if (list.length > MAX_CITED_HEADS) {
|
|
@@ -6562,8 +6678,8 @@ async function signCreationWarrant(input) {
|
|
|
6562
6678
|
const name = label(input.name, "name");
|
|
6563
6679
|
const accountHeads = citedHeads(input.accountHeads, "accountHeads");
|
|
6564
6680
|
const governanceFloor = citedHeads(input.governanceFloor, "governanceFloor");
|
|
6565
|
-
const
|
|
6566
|
-
const deviceKey =
|
|
6681
|
+
const signer = await resolveSigner(input.deviceSecret, input.signer, "deviceSecret");
|
|
6682
|
+
const deviceKey = fromHex(signer.publicKey, "signer.publicKey", 32);
|
|
6567
6683
|
const initHash = await creationInitHash(input.initArgs);
|
|
6568
6684
|
const preimage = await creationWarrantPreimage({
|
|
6569
6685
|
group,
|
|
@@ -6580,9 +6696,7 @@ async function signCreationWarrant(input) {
|
|
|
6580
6696
|
nonce: input.nonce,
|
|
6581
6697
|
notAfter: input.notAfter
|
|
6582
6698
|
});
|
|
6583
|
-
const signature =
|
|
6584
|
-
await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
|
|
6585
|
-
);
|
|
6699
|
+
const signature = checkedSignature(await signer.sign(preimage));
|
|
6586
6700
|
const warrant = hex(
|
|
6587
6701
|
concat(
|
|
6588
6702
|
group,
|
|
@@ -6711,8 +6825,8 @@ async function signGovernanceWarrant(input) {
|
|
|
6711
6825
|
const accountHeads = citedHeads(input.accountHeads, "accountHeads");
|
|
6712
6826
|
const governanceFloor = citedHeads(input.governanceFloor, "governanceFloor");
|
|
6713
6827
|
const kind = kindByte(input.op.kind);
|
|
6714
|
-
const
|
|
6715
|
-
const deviceKey =
|
|
6828
|
+
const signer = await resolveSigner(input.deviceSecret, input.signer, "deviceSecret");
|
|
6829
|
+
const deviceKey = fromHex(signer.publicKey, "signer.publicKey", 32);
|
|
6716
6830
|
const opHash = await governanceOpHash(input.op);
|
|
6717
6831
|
const preimage = await governanceWarrantPreimage({
|
|
6718
6832
|
scope,
|
|
@@ -6726,9 +6840,7 @@ async function signGovernanceWarrant(input) {
|
|
|
6726
6840
|
nonce: input.nonce,
|
|
6727
6841
|
notAfter: input.notAfter
|
|
6728
6842
|
});
|
|
6729
|
-
const signature =
|
|
6730
|
-
await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
|
|
6731
|
-
);
|
|
6843
|
+
const signature = checkedSignature(await signer.sign(preimage));
|
|
6732
6844
|
return hex(
|
|
6733
6845
|
concat(
|
|
6734
6846
|
scope,
|
|
@@ -6829,6 +6941,14 @@ var RelayClient = class {
|
|
|
6829
6941
|
this.fetchImpl = injected ? (input, init) => injected(input, init) : (input, init) => globalThis.fetch(input, init);
|
|
6830
6942
|
this.timeoutMs = config.timeoutMs ?? 1e4;
|
|
6831
6943
|
}
|
|
6944
|
+
/**
|
|
6945
|
+
* The author device's signer, built from `deviceSecret` when that is what was
|
|
6946
|
+
* configured. A {@link Signer} and never the secret, so no caller of a
|
|
6947
|
+
* `RelayClient` gains the ability to read key material.
|
|
6948
|
+
*/
|
|
6949
|
+
async authorSigner() {
|
|
6950
|
+
return resolveSigner(this.config.deviceSecret, this.config.signer, "deviceSecret");
|
|
6951
|
+
}
|
|
6832
6952
|
/**
|
|
6833
6953
|
* Ask the relay what it can do in `contextId`.
|
|
6834
6954
|
*
|
|
@@ -6850,6 +6970,7 @@ var RelayClient = class {
|
|
|
6850
6970
|
*/
|
|
6851
6971
|
async execute(contextId, method, argsJson = {}) {
|
|
6852
6972
|
const executor = this.executorAccount ?? (await this.describe(contextId)).executorAccount;
|
|
6973
|
+
const signer = await this.authorSigner();
|
|
6853
6974
|
const nonce2 = await this.config.nonces.next();
|
|
6854
6975
|
const ttl = this.config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
6855
6976
|
const warrant = await signWarrant({
|
|
@@ -6860,7 +6981,7 @@ var RelayClient = class {
|
|
|
6860
6981
|
argsJson,
|
|
6861
6982
|
nonce: nonce2,
|
|
6862
6983
|
notAfter: BigInt(Math.floor(Date.now() / 1e3)) + BigInt(ttl),
|
|
6863
|
-
|
|
6984
|
+
signer
|
|
6864
6985
|
});
|
|
6865
6986
|
const body = await this.json(
|
|
6866
6987
|
"POST",
|
|
@@ -6924,6 +7045,7 @@ var RelayClient = class {
|
|
|
6924
7045
|
}
|
|
6925
7046
|
const executor = this.checkedExecutor(described.executorAccount);
|
|
6926
7047
|
const initArgs = input.initArgs ?? {};
|
|
7048
|
+
const signer = await this.authorSigner();
|
|
6927
7049
|
const nonce2 = await this.config.nonces.next();
|
|
6928
7050
|
const ttl = this.config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
6929
7051
|
const { warrant } = await signCreationWarrant({
|
|
@@ -6937,7 +7059,7 @@ var RelayClient = class {
|
|
|
6937
7059
|
initArgs,
|
|
6938
7060
|
nonce: nonce2,
|
|
6939
7061
|
notAfter: BigInt(Math.floor(Date.now() / 1e3)) + BigInt(ttl),
|
|
6940
|
-
|
|
7062
|
+
signer
|
|
6941
7063
|
});
|
|
6942
7064
|
const body = await this.json(
|
|
6943
7065
|
"POST",
|
|
@@ -6987,6 +7109,7 @@ var RelayClient = class {
|
|
|
6987
7109
|
);
|
|
6988
7110
|
}
|
|
6989
7111
|
const executor = this.checkedExecutor(described.executorAccount);
|
|
7112
|
+
const signer = await this.authorSigner();
|
|
6990
7113
|
const nonce2 = await this.config.nonces.next();
|
|
6991
7114
|
const ttl = this.config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
6992
7115
|
const warrant = await signGovernanceWarrant({
|
|
@@ -6996,7 +7119,7 @@ var RelayClient = class {
|
|
|
6996
7119
|
executor,
|
|
6997
7120
|
nonce: nonce2,
|
|
6998
7121
|
notAfter: BigInt(Math.floor(Date.now() / 1e3)) + BigInt(ttl),
|
|
6999
|
-
|
|
7122
|
+
signer
|
|
7000
7123
|
});
|
|
7001
7124
|
const body = await this.json(
|
|
7002
7125
|
"POST",
|
|
@@ -8490,7 +8613,7 @@ function groupDeletedOp(rootGroupId) {
|
|
|
8490
8613
|
}
|
|
8491
8614
|
|
|
8492
8615
|
// src/namespace-op/namespace-op.ts
|
|
8493
|
-
var SIGNED_NAMESPACE_OP_SCHEMA_VERSION =
|
|
8616
|
+
var SIGNED_NAMESPACE_OP_SCHEMA_VERSION = 16;
|
|
8494
8617
|
var NAMESPACE_SIGN_DOMAIN = new TextEncoder().encode("calimero.namespace.v1");
|
|
8495
8618
|
var NAMESPACE_OP_ROOT = 0;
|
|
8496
8619
|
var ROOT_OP2 = {
|
|
@@ -8918,6 +9041,8 @@ export {
|
|
|
8918
9041
|
signRequest,
|
|
8919
9042
|
signRoutingChallenge,
|
|
8920
9043
|
signWarrant,
|
|
9044
|
+
signerFromCryptoKey,
|
|
9045
|
+
signerFromSecret,
|
|
8921
9046
|
transportKeyBinding,
|
|
8922
9047
|
trustSignedRelease,
|
|
8923
9048
|
trustedMeasurementsFromReleases,
|