@calimero-network/mero-js 14.0.0 → 15.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.
- package/dist/crypto/internal.d.ts +30 -0
- package/dist/crypto/internal.js +93 -0
- package/dist/device-cert/device-cert.d.ts +68 -0
- package/dist/device-cert/device-cert.js +110 -0
- package/dist/device-cert/index.d.ts +2 -0
- package/dist/device-cert/index.js +2 -0
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +105 -116
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -2
- package/dist/index.mjs +105 -116
- package/dist/index.mjs.map +4 -4
- package/dist/warrant/warrant.d.ts +1 -0
- package/dist/warrant/warrant.js +1 -79
- package/package.json +1 -1
- package/dist/account/index.d.ts +0 -43
- package/dist/account/index.js +0 -139
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ export * from './auth-api/index.js';
|
|
|
5
5
|
export * from './admin-api/index.js';
|
|
6
6
|
export { parseAuthCallback, buildAuthLoginUrl } from './auth/index.js';
|
|
7
7
|
export type { AuthCallbackResult, AuthLoginOptions } from './auth/index.js';
|
|
8
|
-
export { toAccountHex, toAccountBase58, sameAccount, } from './account/index.js';
|
|
9
8
|
export { MemoryTokenStore, LocalStorageTokenStore } from './token-store/index.js';
|
|
10
9
|
export type { TokenStore } from './token-store/index.js';
|
|
11
10
|
export { RpcClient, RpcError } from './rpc/index.js';
|
|
@@ -17,6 +16,8 @@ export { EphemeralClient, jsonCodec } from './ephemeral/index.js';
|
|
|
17
16
|
export type { Codec, EphemeralEntry } from './ephemeral/index.js';
|
|
18
17
|
export * from './cloud/index.js';
|
|
19
18
|
export { signWarrant, intentHash } from './warrant/index.js';
|
|
19
|
+
export { signDeviceCert, mintDeviceId, deviceCertPayload, accountForRoot, } from './device-cert/index.js';
|
|
20
|
+
export type { DeviceCertInput } from './device-cert/index.js';
|
|
20
21
|
export type { WarrantInput } from './warrant/index.js';
|
|
21
22
|
export * from './capabilities.js';
|
|
22
23
|
export { DEFAULT_LOCAL_NODE_PORTS, localNodeUrl, nodeEndpoint, probeNodeHealth, discoverLocalNodes, } from './nodeDiscovery.js';
|
package/dist/index.js
CHANGED
|
@@ -10,8 +10,6 @@ export * from './auth-api/index.js';
|
|
|
10
10
|
export * from './admin-api/index.js';
|
|
11
11
|
// Auth utilities
|
|
12
12
|
export { parseAuthCallback, buildAuthLoginUrl } from './auth/index.js';
|
|
13
|
-
// Account id encoding (hex everywhere core spells one; an app may re-encode)
|
|
14
|
-
export { toAccountHex, toAccountBase58, sameAccount, } from './account/index.js';
|
|
15
13
|
// Token store
|
|
16
14
|
export { MemoryTokenStore, LocalStorageTokenStore } from './token-store/index.js';
|
|
17
15
|
// RPC client
|
|
@@ -24,6 +22,7 @@ export { EphemeralClient, jsonCodec } from './ephemeral/index.js';
|
|
|
24
22
|
export * from './cloud/index.js';
|
|
25
23
|
// Warrant signing — mint the author's consent for a relay to run one intent
|
|
26
24
|
export { signWarrant, intentHash } from './warrant/index.js';
|
|
25
|
+
export { signDeviceCert, mintDeviceId, deviceCertPayload, accountForRoot, } from './device-cert/index.js';
|
|
27
26
|
// Member capability bitmask constants & helpers
|
|
28
27
|
export * from './capabilities.js';
|
|
29
28
|
// Utilities
|
package/dist/index.mjs
CHANGED
|
@@ -2441,93 +2441,6 @@ function createMeroJs(config) {
|
|
|
2441
2441
|
return new MeroJs(config);
|
|
2442
2442
|
}
|
|
2443
2443
|
|
|
2444
|
-
// src/account/index.ts
|
|
2445
|
-
var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
2446
|
-
var HEX_ACCOUNT = /^[0-9a-f]{64}$/i;
|
|
2447
|
-
function encodeBase58(bytes) {
|
|
2448
|
-
if (bytes.length === 0) return "";
|
|
2449
|
-
const digits = [0];
|
|
2450
|
-
for (const byte of bytes) {
|
|
2451
|
-
let carry = byte;
|
|
2452
|
-
for (let i = 0; i < digits.length; i++) {
|
|
2453
|
-
carry += digits[i] << 8;
|
|
2454
|
-
digits[i] = carry % 58;
|
|
2455
|
-
carry = carry / 58 | 0;
|
|
2456
|
-
}
|
|
2457
|
-
while (carry > 0) {
|
|
2458
|
-
digits.push(carry % 58);
|
|
2459
|
-
carry = carry / 58 | 0;
|
|
2460
|
-
}
|
|
2461
|
-
}
|
|
2462
|
-
let out = "";
|
|
2463
|
-
for (const byte of bytes) {
|
|
2464
|
-
if (byte !== 0) break;
|
|
2465
|
-
out += BASE58_ALPHABET[0];
|
|
2466
|
-
}
|
|
2467
|
-
for (let i = digits.length - 1; i >= 0; i--) {
|
|
2468
|
-
out += BASE58_ALPHABET[digits[i]];
|
|
2469
|
-
}
|
|
2470
|
-
return out;
|
|
2471
|
-
}
|
|
2472
|
-
function decodeBase58(value) {
|
|
2473
|
-
if (value.length === 0) return null;
|
|
2474
|
-
const bytes = [0];
|
|
2475
|
-
for (const char of value) {
|
|
2476
|
-
const index = BASE58_ALPHABET.indexOf(char);
|
|
2477
|
-
if (index < 0) return null;
|
|
2478
|
-
let carry = index;
|
|
2479
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
2480
|
-
carry += bytes[i] * 58;
|
|
2481
|
-
bytes[i] = carry & 255;
|
|
2482
|
-
carry >>= 8;
|
|
2483
|
-
}
|
|
2484
|
-
while (carry > 0) {
|
|
2485
|
-
bytes.push(carry & 255);
|
|
2486
|
-
carry >>= 8;
|
|
2487
|
-
}
|
|
2488
|
-
}
|
|
2489
|
-
let leadingZeros = 0;
|
|
2490
|
-
for (const char of value) {
|
|
2491
|
-
if (char !== BASE58_ALPHABET[0]) break;
|
|
2492
|
-
leadingZeros++;
|
|
2493
|
-
}
|
|
2494
|
-
return Uint8Array.from([
|
|
2495
|
-
...new Array(leadingZeros).fill(0),
|
|
2496
|
-
...bytes.reverse()
|
|
2497
|
-
]);
|
|
2498
|
-
}
|
|
2499
|
-
function toHex(bytes) {
|
|
2500
|
-
let out = "";
|
|
2501
|
-
for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
|
|
2502
|
-
return out;
|
|
2503
|
-
}
|
|
2504
|
-
function fromHex(hex2) {
|
|
2505
|
-
const bytes = new Uint8Array(hex2.length / 2);
|
|
2506
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
2507
|
-
bytes[i] = parseInt(hex2.slice(i * 2, i * 2 + 2), 16);
|
|
2508
|
-
}
|
|
2509
|
-
return bytes;
|
|
2510
|
-
}
|
|
2511
|
-
function toAccountHex(id) {
|
|
2512
|
-
const trimmed = (id ?? "").trim();
|
|
2513
|
-
if (!trimmed) return "";
|
|
2514
|
-
if (HEX_ACCOUNT.test(trimmed)) return trimmed.toLowerCase();
|
|
2515
|
-
const decoded = decodeBase58(trimmed);
|
|
2516
|
-
if (!decoded || decoded.length !== 32) return trimmed;
|
|
2517
|
-
return toHex(decoded);
|
|
2518
|
-
}
|
|
2519
|
-
function toAccountBase58(id) {
|
|
2520
|
-
const trimmed = (id ?? "").trim();
|
|
2521
|
-
if (!trimmed) return "";
|
|
2522
|
-
if (!HEX_ACCOUNT.test(trimmed)) return trimmed;
|
|
2523
|
-
return encodeBase58(fromHex(trimmed));
|
|
2524
|
-
}
|
|
2525
|
-
function sameAccount(a, b) {
|
|
2526
|
-
const left = toAccountHex(a);
|
|
2527
|
-
const right = toAccountHex(b);
|
|
2528
|
-
return HEX_ACCOUNT.test(left) && left === right;
|
|
2529
|
-
}
|
|
2530
|
-
|
|
2531
2444
|
// src/token-store/index.ts
|
|
2532
2445
|
var MemoryTokenStore = class {
|
|
2533
2446
|
constructor() {
|
|
@@ -2609,9 +2522,7 @@ var CloudClient = class {
|
|
|
2609
2522
|
}
|
|
2610
2523
|
};
|
|
2611
2524
|
|
|
2612
|
-
// src/
|
|
2613
|
-
var SIGN_DOMAIN = new TextEncoder().encode("calimero.warrant.v1");
|
|
2614
|
-
var INTENT_DOMAIN = new TextEncoder().encode("calimero.warrant.intent.v1");
|
|
2525
|
+
// src/crypto/internal.ts
|
|
2615
2526
|
var PKCS8_ED25519_PREFIX = new Uint8Array([
|
|
2616
2527
|
48,
|
|
2617
2528
|
46,
|
|
@@ -2630,10 +2541,15 @@ var PKCS8_ED25519_PREFIX = new Uint8Array([
|
|
|
2630
2541
|
4,
|
|
2631
2542
|
32
|
|
2632
2543
|
]);
|
|
2544
|
+
function u32le(value) {
|
|
2545
|
+
const out = new Uint8Array(4);
|
|
2546
|
+
new DataView(out.buffer).setUint32(0, value, true);
|
|
2547
|
+
return out;
|
|
2548
|
+
}
|
|
2633
2549
|
function hex(bytes) {
|
|
2634
2550
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
2635
2551
|
}
|
|
2636
|
-
function
|
|
2552
|
+
function fromHex(value, label, expectedBytes) {
|
|
2637
2553
|
const clean = value.trim();
|
|
2638
2554
|
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {
|
|
2639
2555
|
throw new Error(
|
|
@@ -2669,12 +2585,8 @@ async function domainHash(domain, parts) {
|
|
|
2669
2585
|
await crypto.subtle.digest("SHA-256", concat(...chunks))
|
|
2670
2586
|
);
|
|
2671
2587
|
}
|
|
2672
|
-
async function intentHash(method, argsJson) {
|
|
2673
|
-
const args = new TextEncoder().encode(JSON.stringify(argsJson));
|
|
2674
|
-
return domainHash(INTENT_DOMAIN, [new TextEncoder().encode(method), args]);
|
|
2675
|
-
}
|
|
2676
2588
|
async function importSigningKey(secretHex) {
|
|
2677
|
-
const seed =
|
|
2589
|
+
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
2678
2590
|
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2679
2591
|
try {
|
|
2680
2592
|
return await crypto.subtle.importKey(
|
|
@@ -2691,10 +2603,35 @@ async function importSigningKey(secretHex) {
|
|
|
2691
2603
|
);
|
|
2692
2604
|
}
|
|
2693
2605
|
}
|
|
2606
|
+
async function derivePublicKey(secretHex) {
|
|
2607
|
+
const seed = fromHex(secretHex, "deviceSecret", 32);
|
|
2608
|
+
const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
|
|
2609
|
+
const key = await crypto.subtle.importKey(
|
|
2610
|
+
"pkcs8",
|
|
2611
|
+
pkcs8,
|
|
2612
|
+
{ name: "Ed25519" },
|
|
2613
|
+
true,
|
|
2614
|
+
["sign"]
|
|
2615
|
+
);
|
|
2616
|
+
const jwk = await crypto.subtle.exportKey("jwk", key);
|
|
2617
|
+
const raw = jwk.x;
|
|
2618
|
+
return Uint8Array.from(
|
|
2619
|
+
atob(raw.replace(/-/g, "+").replace(/_/g, "/")),
|
|
2620
|
+
(c) => c.charCodeAt(0)
|
|
2621
|
+
);
|
|
2622
|
+
}
|
|
2623
|
+
|
|
2624
|
+
// src/warrant/warrant.ts
|
|
2625
|
+
var SIGN_DOMAIN = new TextEncoder().encode("calimero.warrant.v1");
|
|
2626
|
+
var INTENT_DOMAIN = new TextEncoder().encode("calimero.warrant.intent.v1");
|
|
2627
|
+
async function intentHash(method, argsJson) {
|
|
2628
|
+
const args = new TextEncoder().encode(JSON.stringify(argsJson));
|
|
2629
|
+
return domainHash(INTENT_DOMAIN, [new TextEncoder().encode(method), args]);
|
|
2630
|
+
}
|
|
2694
2631
|
async function signWarrant(input) {
|
|
2695
|
-
const context =
|
|
2696
|
-
const authorAccount =
|
|
2697
|
-
const executor =
|
|
2632
|
+
const context = fromHex(input.context, "context", 32);
|
|
2633
|
+
const authorAccount = fromHex(input.authorAccount, "authorAccount", 32);
|
|
2634
|
+
const executor = fromHex(input.executor, "executor", 32);
|
|
2698
2635
|
const key = await importSigningKey(input.deviceSecret);
|
|
2699
2636
|
const publicKey = await derivePublicKey(input.deviceSecret);
|
|
2700
2637
|
const commitment = await intentHash(input.method, input.argsJson);
|
|
@@ -2725,21 +2662,72 @@ async function signWarrant(input) {
|
|
|
2725
2662
|
)
|
|
2726
2663
|
);
|
|
2727
2664
|
}
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2665
|
+
|
|
2666
|
+
// src/device-cert/device-cert.ts
|
|
2667
|
+
var CERT_DOMAIN = new TextEncoder().encode("calimero.device.cert.v1");
|
|
2668
|
+
var ACCOUNT_ID_DOMAIN = new TextEncoder().encode("calimero.account.genesis.v1");
|
|
2669
|
+
var DEVICE_ID_DOMAIN = new TextEncoder().encode("calimero.device.id.v1");
|
|
2670
|
+
var ACCOUNT_GENESIS_VERSION = 1;
|
|
2671
|
+
async function mintDeviceId(account, nonce) {
|
|
2672
|
+
if (nonce.length !== 16) {
|
|
2673
|
+
throw new Error(`nonce must be 16 bytes, got ${nonce.length}`);
|
|
2674
|
+
}
|
|
2675
|
+
const accountBytes = fromHex(account, "account", 32);
|
|
2676
|
+
return hex(await domainHash(DEVICE_ID_DOMAIN, [accountBytes, nonce]));
|
|
2677
|
+
}
|
|
2678
|
+
async function deviceCertPayload(input) {
|
|
2679
|
+
return domainHash(CERT_DOMAIN, [
|
|
2680
|
+
fromHex(input.account, "account", 32),
|
|
2681
|
+
fromHex(input.device, "device", 32),
|
|
2682
|
+
fromHex(input.signPublicKey, "signPublicKey", 32),
|
|
2683
|
+
fromHex(input.kemPublicKey, "kemPublicKey", 32),
|
|
2684
|
+
u32le(input.keyEpoch),
|
|
2685
|
+
u32le(input.deviceEpoch)
|
|
2686
|
+
]);
|
|
2687
|
+
}
|
|
2688
|
+
async function signDeviceCert(input) {
|
|
2689
|
+
const rootPublicKey = await derivePublicKey(input.rootSecret);
|
|
2690
|
+
const account = hex(
|
|
2691
|
+
await domainHash(ACCOUNT_ID_DOMAIN, [
|
|
2692
|
+
concat(new Uint8Array([ACCOUNT_GENESIS_VERSION]), rootPublicKey)
|
|
2693
|
+
])
|
|
2737
2694
|
);
|
|
2738
|
-
const
|
|
2739
|
-
const
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2695
|
+
const keyEpoch = 0;
|
|
2696
|
+
const payload = await deviceCertPayload({
|
|
2697
|
+
account,
|
|
2698
|
+
device: input.device,
|
|
2699
|
+
signPublicKey: input.signPublicKey,
|
|
2700
|
+
kemPublicKey: input.kemPublicKey,
|
|
2701
|
+
keyEpoch,
|
|
2702
|
+
deviceEpoch: input.deviceEpoch
|
|
2703
|
+
});
|
|
2704
|
+
const key = await importSigningKey(input.rootSecret);
|
|
2705
|
+
const signature = new Uint8Array(
|
|
2706
|
+
await crypto.subtle.sign("Ed25519", key, payload)
|
|
2707
|
+
);
|
|
2708
|
+
const credential = concat(
|
|
2709
|
+
// AccountGenesis
|
|
2710
|
+
new Uint8Array([ACCOUNT_GENESIS_VERSION]),
|
|
2711
|
+
rootPublicKey,
|
|
2712
|
+
// chain: Vec<RootKeyHandoff>, empty
|
|
2713
|
+
u32le(0),
|
|
2714
|
+
// DeviceCert
|
|
2715
|
+
fromHex(account, "account", 32),
|
|
2716
|
+
fromHex(input.device, "device", 32),
|
|
2717
|
+
fromHex(input.signPublicKey, "signPublicKey", 32),
|
|
2718
|
+
fromHex(input.kemPublicKey, "kemPublicKey", 32),
|
|
2719
|
+
u32le(keyEpoch),
|
|
2720
|
+
u32le(input.deviceEpoch),
|
|
2721
|
+
signature
|
|
2722
|
+
);
|
|
2723
|
+
return hex(credential);
|
|
2724
|
+
}
|
|
2725
|
+
async function accountForRoot(rootSecret) {
|
|
2726
|
+
const rootPublicKey = await derivePublicKey(rootSecret);
|
|
2727
|
+
return hex(
|
|
2728
|
+
await domainHash(ACCOUNT_ID_DOMAIN, [
|
|
2729
|
+
concat(new Uint8Array([ACCOUNT_GENESIS_VERSION]), rootPublicKey)
|
|
2730
|
+
])
|
|
2743
2731
|
);
|
|
2744
2732
|
}
|
|
2745
2733
|
|
|
@@ -2835,6 +2823,7 @@ export {
|
|
|
2835
2823
|
SseClient,
|
|
2836
2824
|
WebHttpClient,
|
|
2837
2825
|
WsClient,
|
|
2826
|
+
accountForRoot,
|
|
2838
2827
|
buildAuthLoginUrl,
|
|
2839
2828
|
combineSignals,
|
|
2840
2829
|
compareSemver,
|
|
@@ -2853,18 +2842,18 @@ export {
|
|
|
2853
2842
|
createRetryableMethod,
|
|
2854
2843
|
createTimeoutSignal,
|
|
2855
2844
|
createUniversalHttpClient,
|
|
2845
|
+
deviceCertPayload,
|
|
2856
2846
|
discoverLocalNodes,
|
|
2857
2847
|
hasCap,
|
|
2858
2848
|
intentHash,
|
|
2859
2849
|
jsonCodec,
|
|
2860
2850
|
localNodeUrl,
|
|
2851
|
+
mintDeviceId,
|
|
2861
2852
|
nodeEndpoint,
|
|
2862
2853
|
parseAuthCallback,
|
|
2863
2854
|
probeNodeHealth,
|
|
2864
|
-
|
|
2855
|
+
signDeviceCert,
|
|
2865
2856
|
signWarrant,
|
|
2866
|
-
toAccountBase58,
|
|
2867
|
-
toAccountHex,
|
|
2868
2857
|
withCap,
|
|
2869
2858
|
withRetry,
|
|
2870
2859
|
withoutCap
|