@motebit/crypto 0.8.0 → 1.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/LICENSE +198 -18
- package/NOTICE +19 -0
- package/README.md +11 -3
- package/dist/artifacts.d.ts +431 -32
- package/dist/artifacts.d.ts.map +1 -1
- package/dist/credential-anchor.d.ts +76 -2
- package/dist/credential-anchor.d.ts.map +1 -1
- package/dist/credentials.d.ts +26 -1
- package/dist/credentials.d.ts.map +1 -1
- package/dist/hardware-attestation.d.ts +268 -0
- package/dist/hardware-attestation.d.ts.map +1 -0
- package/dist/index.d.ts +56 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3597 -153
- package/dist/signing.d.ts +52 -17
- package/dist/signing.d.ts.map +1 -1
- package/dist/suite-dispatch.d.ts +103 -0
- package/dist/suite-dispatch.d.ts.map +1 -0
- package/dist/suite-dispatch.js +3233 -0
- package/package.json +20 -5
- package/dist/artifacts.js +0 -506
- package/dist/artifacts.js.map +0 -1
- package/dist/credential-anchor.js +0 -159
- package/dist/credential-anchor.js.map +0 -1
- package/dist/credentials.js +0 -209
- package/dist/credentials.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/signing.js +0 -282
- package/dist/signing.js.map +0 -1
package/dist/signing.d.ts
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* Protocol signing primitives — Ed25519, encoding, canonical JSON, signed tokens.
|
|
3
3
|
*
|
|
4
4
|
* These are the cryptographic building blocks that any protocol participant
|
|
5
|
-
* needs to produce valid Motebit artifacts. Moved from BSL @motebit/
|
|
6
|
-
* to
|
|
5
|
+
* needs to produce valid Motebit artifacts. Moved from BSL @motebit/encryption
|
|
6
|
+
* to the permissive floor in @motebit/crypto (Apache-2.0) so the protocol's
|
|
7
|
+
* signing format is open.
|
|
7
8
|
*
|
|
8
9
|
* Zero monorepo dependencies — only @noble/ed25519 for cryptography.
|
|
9
10
|
*/
|
|
@@ -20,7 +21,20 @@ export interface SignedTokenPayload {
|
|
|
20
21
|
jti: string;
|
|
21
22
|
/** Audience claim — binds token to a specific endpoint/operation. Prevents cross-endpoint replay. */
|
|
22
23
|
aud: string;
|
|
24
|
+
/**
|
|
25
|
+
* Cryptosuite identifier. Always `"motebit-jwt-ed25519-v1"` for this
|
|
26
|
+
* token shape today. Present in the signed payload so verifiers
|
|
27
|
+
* dispatch primitive verification through `verifyBySuite` rather
|
|
28
|
+
* than assuming Ed25519. Missing or unknown values are rejected
|
|
29
|
+
* fail-closed — no legacy-no-suite path.
|
|
30
|
+
*/
|
|
31
|
+
suite: "motebit-jwt-ed25519-v1";
|
|
23
32
|
}
|
|
33
|
+
/** The one suite this token shape uses. Exported as a const so the
|
|
34
|
+
* signer emits exactly this value and the verifier checks for exactly
|
|
35
|
+
* this value — no string drift risk.
|
|
36
|
+
*/
|
|
37
|
+
export declare const SIGNED_TOKEN_SUITE: "motebit-jwt-ed25519-v1";
|
|
24
38
|
/**
|
|
25
39
|
* Deterministic JSON serialization with sorted keys (recursive).
|
|
26
40
|
* Produces identical output regardless of insertion order.
|
|
@@ -53,30 +67,51 @@ export declare function didKeyToPublicKey(did: string): Uint8Array;
|
|
|
53
67
|
export declare function publicKeyToDidKey(publicKey: Uint8Array): string;
|
|
54
68
|
export declare function hexPublicKeyToDidKey(hexPublicKey: string): string;
|
|
55
69
|
export declare function hash(data: Uint8Array): Promise<string>;
|
|
56
|
-
/** SHA-256 returning raw bytes (used by credential signing). */
|
|
57
|
-
export declare function sha256(data: Uint8Array): Promise<Uint8Array>;
|
|
58
|
-
export declare function generateKeypair(): Promise<KeyPair>;
|
|
59
70
|
/**
|
|
60
|
-
*
|
|
71
|
+
* Canonical-bytes hash. Convenience wrapper over `canonicalJson` + SHA-256
|
|
72
|
+
* for diagnostic and audit use: lets a producer and a verifier deterministically
|
|
73
|
+
* agree on (or disagree about) the exact bytes a signature was computed over,
|
|
74
|
+
* without re-implementing the canonicalization recipe at the call site.
|
|
61
75
|
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Verify an Ed25519 signature.
|
|
76
|
+
* Returns the hex SHA-256 of the UTF-8 bytes of `canonicalJson(obj)`. Stable
|
|
77
|
+
* across processes, machines, and Node versions — same input ⇒ same output,
|
|
78
|
+
* always. The only requirement on `obj` is that it be a JSON-serializable
|
|
79
|
+
* value (no functions, no symbols, no cycles).
|
|
68
80
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
81
|
+
* Primary use case: when a signed-artifact verification fails, both ends of
|
|
82
|
+
* the pipeline can log `canonicalSha256(body)` and the producer can confirm
|
|
83
|
+
* whether the bytes the verifier reproduced match the bytes the producer
|
|
84
|
+
* signed. A hash mismatch localizes the bug to the wire path; a hash match
|
|
85
|
+
* localizes it to the signature primitive (which is far less likely).
|
|
71
86
|
*/
|
|
72
|
-
export declare function
|
|
87
|
+
export declare function canonicalSha256(obj: unknown): Promise<string>;
|
|
88
|
+
/** SHA-256 returning raw bytes (used by credential signing). */
|
|
89
|
+
export declare function sha256(data: Uint8Array): Promise<Uint8Array>;
|
|
90
|
+
export { ed25519Sign, ed25519Verify, generateEd25519Keypair, getPublicKeyBySuite, signBySuite, verifyBySuite, } from "./suite-dispatch.js";
|
|
91
|
+
export declare function generateKeypair(): Promise<KeyPair>;
|
|
73
92
|
/**
|
|
74
93
|
* Create a signed token: base64url(payload) + "." + base64url(signature).
|
|
75
94
|
* Default expiry: 5 minutes from now.
|
|
95
|
+
*
|
|
96
|
+
* The payload includes a fixed `suite` field (`SIGNED_TOKEN_SUITE`) so
|
|
97
|
+
* the verifier can dispatch primitive verification explicitly rather
|
|
98
|
+
* than implicitly assuming Ed25519. Callers MUST supply every other
|
|
99
|
+
* required payload field; this function does not fill defaults for
|
|
100
|
+
* `mid` / `did` / `iat` / `exp` / `jti` / `aud`.
|
|
76
101
|
*/
|
|
77
|
-
export declare function createSignedToken(payload: SignedTokenPayload, privateKey: Uint8Array): Promise<string>;
|
|
102
|
+
export declare function createSignedToken(payload: Omit<SignedTokenPayload, "suite">, privateKey: Uint8Array): Promise<string>;
|
|
78
103
|
/**
|
|
79
|
-
* Verify a signed token. Returns the parsed payload if valid and not
|
|
104
|
+
* Verify a signed token. Returns the parsed payload if valid and not
|
|
105
|
+
* expired, null otherwise.
|
|
106
|
+
*
|
|
107
|
+
* Rejects fail-closed on:
|
|
108
|
+
* - malformed token string (no dot separator, invalid base64url),
|
|
109
|
+
* - missing `suite` field,
|
|
110
|
+
* - `suite` value other than `SIGNED_TOKEN_SUITE`,
|
|
111
|
+
* - signature mismatch,
|
|
112
|
+
* - expired token,
|
|
113
|
+
* - missing `jti` (replay defense),
|
|
114
|
+
* - missing `aud` (cross-endpoint replay defense).
|
|
80
115
|
*/
|
|
81
116
|
export declare function verifySignedToken(token: string, publicKey: Uint8Array): Promise<SignedTokenPayload | null>;
|
|
82
117
|
/**
|
package/dist/signing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../src/signing.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../src/signing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,UAAU,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,wFAAwF;IACxF,GAAG,EAAE,MAAM,CAAC;IACZ,qGAAqG;IACrG,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,KAAK,EAAE,wBAAwB,CAAC;CACjC;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAG,wBAAiC,CAAC;AAIpE;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAclD;AAID,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAIpD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAMlD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAMpD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAQrD;AAMD,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAczD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAoBvD;AAID;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAezD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAS/D;AAED,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEjE;AAID,wBAAsB,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAM5D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnE;AAED,gEAAgE;AAChE,wBAAsB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAGlE;AAaD,OAAO,EACL,WAAW,EACX,aAAa,EACb,sBAAsB,EACtB,mBAAmB,EACnB,WAAW,EACX,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAExD;AAID;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,CAAC,EAC1C,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAoCpC;AAID;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAQxD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAehF"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cryptosuite dispatch — the single entry point for signature primitive
|
|
3
|
+
* verification in @motebit/crypto.
|
|
4
|
+
*
|
|
5
|
+
* Every `verify*` function that checks a signed motebit artifact MUST
|
|
6
|
+
* route through `verifyBySuite`. Direct calls to `ed.verifyAsync`,
|
|
7
|
+
* `ed.signAsync`, or any other primitive outside this file are a
|
|
8
|
+
* drift-gate violation — see `scripts/check-suite-dispatch.ts`.
|
|
9
|
+
*
|
|
10
|
+
* Rationale: the suite value on a wire artifact names a complete
|
|
11
|
+
* verification recipe (algorithm + canonicalization + encoding). The
|
|
12
|
+
* dispatcher's job is to map `suite` → primitive. Encoding of the
|
|
13
|
+
* signature and public key stays at the artifact layer (every artifact
|
|
14
|
+
* already has its own encoding convention — see `spec/<artifact>-v1.md`
|
|
15
|
+
* `#### Wire format (foundation law)` subsections); the dispatcher
|
|
16
|
+
* receives already-decoded bytes and returns already-produced bytes.
|
|
17
|
+
* This keeps the Ed25519 switch arm honest: it does one thing, and the
|
|
18
|
+
* PQ switch arms that follow in 2026+ will do the same one thing for
|
|
19
|
+
* ML-DSA / SLH-DSA.
|
|
20
|
+
*
|
|
21
|
+
* Fail-closed throughout:
|
|
22
|
+
* - unknown `SuiteId` → `verifyBySuite` returns `false`, `signBySuite` throws.
|
|
23
|
+
* - unsupported algorithm in the switch (PQ placeholder) → throws with
|
|
24
|
+
* a clear message so the call site doesn't silently succeed.
|
|
25
|
+
* - primitive-level exception → `verifyBySuite` returns `false`.
|
|
26
|
+
*
|
|
27
|
+
* No legacy-no-suite path. A caller that reaches this function without
|
|
28
|
+
* a valid `SuiteId` has already lost; the function enforces that
|
|
29
|
+
* contract at the boundary.
|
|
30
|
+
*/
|
|
31
|
+
import type { SuiteId } from "@motebit/protocol";
|
|
32
|
+
/**
|
|
33
|
+
* Verify an already-decoded signature over `canonicalBytes` using the
|
|
34
|
+
* primitive named by `suite`. The caller is responsible for:
|
|
35
|
+
* 1. canonicalization (the bytes are already the signing input per
|
|
36
|
+
* the suite's canonicalization rule);
|
|
37
|
+
* 2. signature and public-key decoding (hex → Uint8Array, base64url
|
|
38
|
+
* → Uint8Array, multibase → Uint8Array per the suite's
|
|
39
|
+
* `signatureEncoding` / `publicKeyEncoding`).
|
|
40
|
+
*
|
|
41
|
+
* Returns `false` on unknown or unsupported suite, on primitive-level
|
|
42
|
+
* exception, and on signature mismatch. Never throws in the Ed25519
|
|
43
|
+
* path. Throws only on PQ suites (placeholder until implementation
|
|
44
|
+
* lands), because a misconfigured dispatcher there would silently
|
|
45
|
+
* pass every verification.
|
|
46
|
+
*/
|
|
47
|
+
export declare function verifyBySuite(suite: SuiteId, canonicalBytes: Uint8Array, signatureBytes: Uint8Array, publicKeyBytes: Uint8Array): Promise<boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* Produce a signature over `canonicalBytes` using the primitive named
|
|
50
|
+
* by `suite`. Mirrors `verifyBySuite`: caller provides already-
|
|
51
|
+
* canonicalized bytes; caller encodes the returned `Uint8Array` per
|
|
52
|
+
* the suite's `signatureEncoding` at the artifact boundary.
|
|
53
|
+
*
|
|
54
|
+
* Throws on unknown or unsupported suite (fail-closed). Signers that
|
|
55
|
+
* catch and swallow this exception would ship unsigned artifacts,
|
|
56
|
+
* which is a worse failure mode than a loud throw.
|
|
57
|
+
*/
|
|
58
|
+
export declare function signBySuite(suite: SuiteId, canonicalBytes: Uint8Array, privateKeyBytes: Uint8Array): Promise<Uint8Array>;
|
|
59
|
+
/**
|
|
60
|
+
* Lowest-level Ed25519 primitives. These are the functions callers
|
|
61
|
+
* should use when they genuinely need the primitive — for example,
|
|
62
|
+
* generating a keypair at identity bootstrap, or computing a
|
|
63
|
+
* succession-chain signature where the caller has already dispatched
|
|
64
|
+
* by suite. Exported from this file so the drift gate's scan rule is
|
|
65
|
+
* simple: "`ed.*` lives only in `suite-dispatch.ts`."
|
|
66
|
+
*/
|
|
67
|
+
export declare function ed25519Sign(message: Uint8Array, privateKey: Uint8Array): Promise<Uint8Array>;
|
|
68
|
+
export declare function ed25519Verify(signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): Promise<boolean>;
|
|
69
|
+
export declare function generateEd25519Keypair(): Promise<{
|
|
70
|
+
publicKey: Uint8Array;
|
|
71
|
+
privateKey: Uint8Array;
|
|
72
|
+
}>;
|
|
73
|
+
/**
|
|
74
|
+
* Derive the matching public key from a private key, dispatched by suite.
|
|
75
|
+
*
|
|
76
|
+
* For Ed25519 suites this is deterministic seed expansion (hash the seed,
|
|
77
|
+
* derive the curve point). Callers that have a private key in hand and
|
|
78
|
+
* need the public key — sovereign delegation paths, identity bootstrap
|
|
79
|
+
* after a seed import, recovery flows — go through here so the noble
|
|
80
|
+
* call doesn't escape the dispatcher.
|
|
81
|
+
*
|
|
82
|
+
* Throws on unknown or unsupported suite (fail-closed). PQ arms will
|
|
83
|
+
* land alongside their `verifyBySuite` / `signBySuite` counterparts.
|
|
84
|
+
*/
|
|
85
|
+
export declare function getPublicKeyBySuite(privateKey: Uint8Array, suite: SuiteId): Promise<Uint8Array>;
|
|
86
|
+
/**
|
|
87
|
+
* Verify a P-256 ECDSA-SHA256 signature.
|
|
88
|
+
*
|
|
89
|
+
* - `publicKeyCompressedHex` — P-256 public key in compressed-point
|
|
90
|
+
* hex encoding (33 bytes, `02`/`03` prefix). Uncompressed keys
|
|
91
|
+
* (65 bytes, `04` prefix) also accepted — noble handles both.
|
|
92
|
+
* - `messageBytes` — the bytes that were signed. noble internally
|
|
93
|
+
* SHA-256 hashes before verification, so callers pass the
|
|
94
|
+
* un-pre-hashed payload.
|
|
95
|
+
* - `signatureDerBytes` — DER-encoded ECDSA signature as emitted by
|
|
96
|
+
* Apple SE / Security.framework.
|
|
97
|
+
*
|
|
98
|
+
* Returns `false` on any failure (bad key, bad DER, bad signature,
|
|
99
|
+
* mismatch). Never throws — matches the `verifyBySuite` contract so
|
|
100
|
+
* callers don't need a try/catch.
|
|
101
|
+
*/
|
|
102
|
+
export declare function verifyP256EcdsaSha256(publicKeyCompressedHex: string, messageBytes: Uint8Array, signatureDerBytes: Uint8Array): boolean;
|
|
103
|
+
//# sourceMappingURL=suite-dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suite-dispatch.d.ts","sourceRoot":"","sources":["../src/suite-dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAkBH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AASjD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,OAAO,EACd,cAAc,EAAE,UAAU,EAC1B,cAAc,EAAE,UAAU,EAC1B,cAAc,EAAE,UAAU,GACzB,OAAO,CAAC,OAAO,CAAC,CAgBlB;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,OAAO,EACd,cAAc,EAAE,UAAU,EAC1B,eAAe,EAAE,UAAU,GAC1B,OAAO,CAAC,UAAU,CAAC,CASrB;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,UAAU,EACnB,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,UAAU,CAAC,CAErB;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,OAAO,CAAC,CAMlB;AAED,wBAAsB,sBAAsB,IAAI,OAAO,CAAC;IACtD,SAAS,EAAE,UAAU,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC,CAGD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,UAAU,CAAC,CASrB;AAeD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,sBAAsB,EAAE,MAAM,EAC9B,YAAY,EAAE,UAAU,EACxB,iBAAiB,EAAE,UAAU,GAC5B,OAAO,CAQT"}
|