@calimero-network/mero-js 22.5.1 → 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 +143 -18
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/index.mjs +143 -18
- package/dist/index.mjs.map +4 -4
- 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.cjs
CHANGED
|
@@ -124,6 +124,8 @@ __export(index_exports, {
|
|
|
124
124
|
signRequest: () => signRequest,
|
|
125
125
|
signRoutingChallenge: () => signRoutingChallenge,
|
|
126
126
|
signWarrant: () => signWarrant,
|
|
127
|
+
signerFromCryptoKey: () => signerFromCryptoKey,
|
|
128
|
+
signerFromSecret: () => signerFromSecret,
|
|
127
129
|
transportKeyBinding: () => transportKeyBinding,
|
|
128
130
|
trustSignedRelease: () => trustSignedRelease,
|
|
129
131
|
trustedMeasurementsFromReleases: () => trustedMeasurementsFromReleases,
|
|
@@ -6585,6 +6587,117 @@ var LocalStorageTokenStore = class {
|
|
|
6585
6587
|
}
|
|
6586
6588
|
};
|
|
6587
6589
|
|
|
6590
|
+
// src/signer/signer.ts
|
|
6591
|
+
var PKCS8_ED25519_PREFIX2 = new Uint8Array([
|
|
6592
|
+
48,
|
|
6593
|
+
46,
|
|
6594
|
+
2,
|
|
6595
|
+
1,
|
|
6596
|
+
0,
|
|
6597
|
+
48,
|
|
6598
|
+
5,
|
|
6599
|
+
6,
|
|
6600
|
+
3,
|
|
6601
|
+
43,
|
|
6602
|
+
101,
|
|
6603
|
+
112,
|
|
6604
|
+
4,
|
|
6605
|
+
34,
|
|
6606
|
+
4,
|
|
6607
|
+
32
|
|
6608
|
+
]);
|
|
6609
|
+
function unsupported(cause) {
|
|
6610
|
+
const detail = cause instanceof Error ? `: ${cause.message}` : "";
|
|
6611
|
+
return new Error(
|
|
6612
|
+
"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
|
|
6613
|
+
);
|
|
6614
|
+
}
|
|
6615
|
+
async function signerFromSecret(secret, label2 = "secret") {
|
|
6616
|
+
const seed = fromHex(secret, label2, 32);
|
|
6617
|
+
const pkcs8 = concat(PKCS8_ED25519_PREFIX2, seed);
|
|
6618
|
+
let privateKey;
|
|
6619
|
+
let publicKey;
|
|
6620
|
+
try {
|
|
6621
|
+
const exportable = await crypto.subtle.importKey(
|
|
6622
|
+
"pkcs8",
|
|
6623
|
+
pkcs8,
|
|
6624
|
+
{ name: "Ed25519" },
|
|
6625
|
+
true,
|
|
6626
|
+
["sign"]
|
|
6627
|
+
);
|
|
6628
|
+
const jwk = await crypto.subtle.exportKey("jwk", exportable);
|
|
6629
|
+
publicKey = hex(
|
|
6630
|
+
Uint8Array.from(
|
|
6631
|
+
atob(jwk.x.replace(/-/g, "+").replace(/_/g, "/")),
|
|
6632
|
+
(c) => c.charCodeAt(0)
|
|
6633
|
+
)
|
|
6634
|
+
);
|
|
6635
|
+
privateKey = await crypto.subtle.importKey(
|
|
6636
|
+
"pkcs8",
|
|
6637
|
+
pkcs8,
|
|
6638
|
+
{ name: "Ed25519" },
|
|
6639
|
+
false,
|
|
6640
|
+
["sign"]
|
|
6641
|
+
);
|
|
6642
|
+
} catch (cause) {
|
|
6643
|
+
throw unsupported(cause);
|
|
6644
|
+
}
|
|
6645
|
+
return fromKeyAndPublic(privateKey, publicKey);
|
|
6646
|
+
}
|
|
6647
|
+
async function signerFromCryptoKey(privateKey, publicKey) {
|
|
6648
|
+
if (privateKey.type !== "private") {
|
|
6649
|
+
throw new Error(
|
|
6650
|
+
`signerFromCryptoKey needs the private half of the pair, got a ${privateKey.type} key`
|
|
6651
|
+
);
|
|
6652
|
+
}
|
|
6653
|
+
if (!privateKey.usages.includes("sign")) {
|
|
6654
|
+
throw new Error(
|
|
6655
|
+
"this CryptoKey cannot sign: generate it with usages ['sign', 'verify']"
|
|
6656
|
+
);
|
|
6657
|
+
}
|
|
6658
|
+
let publicHex;
|
|
6659
|
+
if (typeof publicKey === "string") {
|
|
6660
|
+
fromHex(publicKey, "publicKey", 32);
|
|
6661
|
+
publicHex = publicKey.trim().toLowerCase();
|
|
6662
|
+
} else {
|
|
6663
|
+
try {
|
|
6664
|
+
publicHex = hex(
|
|
6665
|
+
new Uint8Array(await crypto.subtle.exportKey("raw", publicKey))
|
|
6666
|
+
);
|
|
6667
|
+
} catch (cause) {
|
|
6668
|
+
const detail = cause instanceof Error ? `: ${cause.message}` : "";
|
|
6669
|
+
throw new Error(
|
|
6670
|
+
"could not read the public half of this key pair; pass the public key as 64 hex instead" + detail
|
|
6671
|
+
);
|
|
6672
|
+
}
|
|
6673
|
+
}
|
|
6674
|
+
return fromKeyAndPublic(privateKey, publicHex);
|
|
6675
|
+
}
|
|
6676
|
+
function fromKeyAndPublic(privateKey, publicKey) {
|
|
6677
|
+
return {
|
|
6678
|
+
publicKey,
|
|
6679
|
+
async sign(payload) {
|
|
6680
|
+
try {
|
|
6681
|
+
return new Uint8Array(
|
|
6682
|
+
await crypto.subtle.sign({ name: "Ed25519" }, privateKey, payload)
|
|
6683
|
+
);
|
|
6684
|
+
} catch (cause) {
|
|
6685
|
+
throw unsupported(cause);
|
|
6686
|
+
}
|
|
6687
|
+
}
|
|
6688
|
+
};
|
|
6689
|
+
}
|
|
6690
|
+
async function resolveSigner(secret, signer, label2) {
|
|
6691
|
+
if (signer && secret !== void 0) {
|
|
6692
|
+
throw new Error(
|
|
6693
|
+
`pass either ${label2} or signer, not both \u2014 they may name different keys`
|
|
6694
|
+
);
|
|
6695
|
+
}
|
|
6696
|
+
if (signer) return signer;
|
|
6697
|
+
if (secret !== void 0) return signerFromSecret(secret, label2);
|
|
6698
|
+
throw new Error(`${label2} or signer is required`);
|
|
6699
|
+
}
|
|
6700
|
+
|
|
6588
6701
|
// src/warrant/warrant.ts
|
|
6589
6702
|
var SIGN_DOMAIN2 = new TextEncoder().encode("calimero.warrant.v2");
|
|
6590
6703
|
var INTENT_DOMAIN = new TextEncoder().encode("calimero.warrant.intent.v1");
|
|
@@ -6605,8 +6718,8 @@ async function signWarrant(input) {
|
|
|
6605
6718
|
);
|
|
6606
6719
|
const accountHeads = citedHeads(input.accountHeads, "accountHeads");
|
|
6607
6720
|
const governanceFloor = citedHeads(input.governanceFloor, "governanceFloor");
|
|
6608
|
-
const
|
|
6609
|
-
const publicKey =
|
|
6721
|
+
const signer = await resolveSigner(input.deviceSecret, input.signer, "deviceSecret");
|
|
6722
|
+
const publicKey = fromHex(signer.publicKey, "signer.publicKey", 32);
|
|
6610
6723
|
const method = new TextEncoder().encode(input.method);
|
|
6611
6724
|
const commitment = await intentHash(input.method, input.argsJson);
|
|
6612
6725
|
const nonce2 = u64le(input.nonce);
|
|
@@ -6626,9 +6739,7 @@ async function signWarrant(input) {
|
|
|
6626
6739
|
nonce2,
|
|
6627
6740
|
notAfter
|
|
6628
6741
|
]);
|
|
6629
|
-
const signature =
|
|
6630
|
-
await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
|
|
6631
|
-
);
|
|
6742
|
+
const signature = checkedSignature(await signer.sign(preimage));
|
|
6632
6743
|
return hex(
|
|
6633
6744
|
concat(
|
|
6634
6745
|
context,
|
|
@@ -6649,6 +6760,13 @@ async function signWarrant(input) {
|
|
|
6649
6760
|
)
|
|
6650
6761
|
);
|
|
6651
6762
|
}
|
|
6763
|
+
function checkedSignature(signature) {
|
|
6764
|
+
if (!(signature instanceof Uint8Array) || signature.length !== 64) {
|
|
6765
|
+
const got = signature instanceof Uint8Array ? `${signature.length} bytes` : typeof signature;
|
|
6766
|
+
throw new Error(`signer returned ${got}, expected a 64-byte Ed25519 signature`);
|
|
6767
|
+
}
|
|
6768
|
+
return signature;
|
|
6769
|
+
}
|
|
6652
6770
|
function citedHeads(heads, label2) {
|
|
6653
6771
|
const list = heads ?? [];
|
|
6654
6772
|
if (list.length > MAX_CITED_HEADS) {
|
|
@@ -6698,8 +6816,8 @@ async function signCreationWarrant(input) {
|
|
|
6698
6816
|
const name = label(input.name, "name");
|
|
6699
6817
|
const accountHeads = citedHeads(input.accountHeads, "accountHeads");
|
|
6700
6818
|
const governanceFloor = citedHeads(input.governanceFloor, "governanceFloor");
|
|
6701
|
-
const
|
|
6702
|
-
const deviceKey =
|
|
6819
|
+
const signer = await resolveSigner(input.deviceSecret, input.signer, "deviceSecret");
|
|
6820
|
+
const deviceKey = fromHex(signer.publicKey, "signer.publicKey", 32);
|
|
6703
6821
|
const initHash = await creationInitHash(input.initArgs);
|
|
6704
6822
|
const preimage = await creationWarrantPreimage({
|
|
6705
6823
|
group,
|
|
@@ -6716,9 +6834,7 @@ async function signCreationWarrant(input) {
|
|
|
6716
6834
|
nonce: input.nonce,
|
|
6717
6835
|
notAfter: input.notAfter
|
|
6718
6836
|
});
|
|
6719
|
-
const signature =
|
|
6720
|
-
await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
|
|
6721
|
-
);
|
|
6837
|
+
const signature = checkedSignature(await signer.sign(preimage));
|
|
6722
6838
|
const warrant = hex(
|
|
6723
6839
|
concat(
|
|
6724
6840
|
group,
|
|
@@ -6847,8 +6963,8 @@ async function signGovernanceWarrant(input) {
|
|
|
6847
6963
|
const accountHeads = citedHeads(input.accountHeads, "accountHeads");
|
|
6848
6964
|
const governanceFloor = citedHeads(input.governanceFloor, "governanceFloor");
|
|
6849
6965
|
const kind = kindByte(input.op.kind);
|
|
6850
|
-
const
|
|
6851
|
-
const deviceKey =
|
|
6966
|
+
const signer = await resolveSigner(input.deviceSecret, input.signer, "deviceSecret");
|
|
6967
|
+
const deviceKey = fromHex(signer.publicKey, "signer.publicKey", 32);
|
|
6852
6968
|
const opHash = await governanceOpHash(input.op);
|
|
6853
6969
|
const preimage = await governanceWarrantPreimage({
|
|
6854
6970
|
scope,
|
|
@@ -6862,9 +6978,7 @@ async function signGovernanceWarrant(input) {
|
|
|
6862
6978
|
nonce: input.nonce,
|
|
6863
6979
|
notAfter: input.notAfter
|
|
6864
6980
|
});
|
|
6865
|
-
const signature =
|
|
6866
|
-
await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
|
|
6867
|
-
);
|
|
6981
|
+
const signature = checkedSignature(await signer.sign(preimage));
|
|
6868
6982
|
return hex(
|
|
6869
6983
|
concat(
|
|
6870
6984
|
scope,
|
|
@@ -6965,6 +7079,14 @@ var RelayClient = class {
|
|
|
6965
7079
|
this.fetchImpl = injected ? (input, init) => injected(input, init) : (input, init) => globalThis.fetch(input, init);
|
|
6966
7080
|
this.timeoutMs = config.timeoutMs ?? 1e4;
|
|
6967
7081
|
}
|
|
7082
|
+
/**
|
|
7083
|
+
* The author device's signer, built from `deviceSecret` when that is what was
|
|
7084
|
+
* configured. A {@link Signer} and never the secret, so no caller of a
|
|
7085
|
+
* `RelayClient` gains the ability to read key material.
|
|
7086
|
+
*/
|
|
7087
|
+
async authorSigner() {
|
|
7088
|
+
return resolveSigner(this.config.deviceSecret, this.config.signer, "deviceSecret");
|
|
7089
|
+
}
|
|
6968
7090
|
/**
|
|
6969
7091
|
* Ask the relay what it can do in `contextId`.
|
|
6970
7092
|
*
|
|
@@ -6986,6 +7108,7 @@ var RelayClient = class {
|
|
|
6986
7108
|
*/
|
|
6987
7109
|
async execute(contextId, method, argsJson = {}) {
|
|
6988
7110
|
const executor = this.executorAccount ?? (await this.describe(contextId)).executorAccount;
|
|
7111
|
+
const signer = await this.authorSigner();
|
|
6989
7112
|
const nonce2 = await this.config.nonces.next();
|
|
6990
7113
|
const ttl = this.config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
6991
7114
|
const warrant = await signWarrant({
|
|
@@ -6996,7 +7119,7 @@ var RelayClient = class {
|
|
|
6996
7119
|
argsJson,
|
|
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",
|
|
@@ -7060,6 +7183,7 @@ var RelayClient = class {
|
|
|
7060
7183
|
}
|
|
7061
7184
|
const executor = this.checkedExecutor(described.executorAccount);
|
|
7062
7185
|
const initArgs = input.initArgs ?? {};
|
|
7186
|
+
const signer = await this.authorSigner();
|
|
7063
7187
|
const nonce2 = await this.config.nonces.next();
|
|
7064
7188
|
const ttl = this.config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
7065
7189
|
const { warrant } = await signCreationWarrant({
|
|
@@ -7073,7 +7197,7 @@ var RelayClient = class {
|
|
|
7073
7197
|
initArgs,
|
|
7074
7198
|
nonce: nonce2,
|
|
7075
7199
|
notAfter: BigInt(Math.floor(Date.now() / 1e3)) + BigInt(ttl),
|
|
7076
|
-
|
|
7200
|
+
signer
|
|
7077
7201
|
});
|
|
7078
7202
|
const body = await this.json(
|
|
7079
7203
|
"POST",
|
|
@@ -7123,6 +7247,7 @@ var RelayClient = class {
|
|
|
7123
7247
|
);
|
|
7124
7248
|
}
|
|
7125
7249
|
const executor = this.checkedExecutor(described.executorAccount);
|
|
7250
|
+
const signer = await this.authorSigner();
|
|
7126
7251
|
const nonce2 = await this.config.nonces.next();
|
|
7127
7252
|
const ttl = this.config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
7128
7253
|
const warrant = await signGovernanceWarrant({
|
|
@@ -7132,7 +7257,7 @@ var RelayClient = class {
|
|
|
7132
7257
|
executor,
|
|
7133
7258
|
nonce: nonce2,
|
|
7134
7259
|
notAfter: BigInt(Math.floor(Date.now() / 1e3)) + BigInt(ttl),
|
|
7135
|
-
|
|
7260
|
+
signer
|
|
7136
7261
|
});
|
|
7137
7262
|
const body = await this.json(
|
|
7138
7263
|
"POST",
|