raz-encrypt 0.3.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/dist/core.d.ts +4 -2
- package/dist/core.js +2 -1
- package/dist/core.js.map +1 -1
- package/dist/crypto/hybrid.d.ts +91 -17
- package/dist/crypto/hybrid.js +164 -31
- package/dist/crypto/hybrid.js.map +1 -1
- package/dist/crypto/ratchet.d.ts +68 -0
- package/dist/crypto/ratchet.js +89 -0
- package/dist/crypto/ratchet.js.map +1 -0
- package/package.json +1 -1
package/dist/core.d.ts
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
* included, fs-backed versions of the same logic — this module is the
|
|
11
11
|
* un-wired core they're built from, not a separate implementation.
|
|
12
12
|
*/
|
|
13
|
-
export { decryptFromCore as decryptFrom, encryptForCore as encryptFor, establishSessionInitiatorCore as establishSessionInitiator, establishSessionResponderCore as establishSessionResponder, signCore as sign, UntrustedPartyError, verifyCore as verify, } from "./crypto/hybrid.js";
|
|
14
|
-
export type { Certificate, EncryptedBox, InitiatorSessionResult, LogDeps, SessionKeys, SignOptions, TrustDeps, TrustStatus, VerifyDeps, VerifyFailureReason, VerifyResult, } from "./crypto/hybrid.js";
|
|
13
|
+
export { createResponderHandshakeCore as createResponderHandshake, decryptFromCore as decryptFrom, encryptForCore as encryptFor, establishSessionInitiatorCore as establishSessionInitiator, establishSessionResponderCore as establishSessionResponder, HandshakeVerificationError, signCore as sign, UntrustedPartyError, verifyCore as verify, } from "./crypto/hybrid.js";
|
|
14
|
+
export type { Certificate, EncryptedBox, HandshakeSignature, InitiatorHandshakeMessage, InitiatorSessionResult, LogDeps, ResponderHandshakeInit, ResponderHandshakeMessage, ResponderHandshakeSecrets, ResponderSessionResult, SessionKeys, SignOptions, TrustDeps, TrustStatus, VerifyDeps, VerifyFailureReason, VerifyResult, } from "./crypto/hybrid.js";
|
|
15
15
|
export { generateClassicalKeypair, classicalSharedSecret, classicalSign, classicalVerify } from "./crypto/classical.js";
|
|
16
16
|
export type { ClassicalKeypair } from "./crypto/classical.js";
|
|
17
17
|
export { generatePqcKemKeypair, generatePqcSignKeypair, pqcDecapsulate, pqcEncapsulate, pqcSign, pqcVerify, } from "./crypto/pqc.js";
|
|
@@ -20,4 +20,6 @@ export { canonicalize, hashDocument } from "./canonicalJson.js";
|
|
|
20
20
|
export { fingerprint } from "./fingerprint.js";
|
|
21
21
|
export { decryptFrame, encryptFrame, FrameDecryptionError } from "./crypto/frameCipher.js";
|
|
22
22
|
export type { EncryptedFrame } from "./crypto/frameCipher.js";
|
|
23
|
+
export { CHAIN_INFO_INITIATOR_TO_RESPONDER, CHAIN_INFO_RESPONDER_TO_INITIATOR, ML_KEM_STEP_CADENCE, performEcdhStep, performKemStep, ratchetChainKey, seedChainKey, } from "./crypto/ratchet.js";
|
|
24
|
+
export type { AsymmetricStepResult, ChainStep } from "./crypto/ratchet.js";
|
|
23
25
|
export type { Identity, PublicCard } from "./identity.js";
|
package/dist/core.js
CHANGED
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
* included, fs-backed versions of the same logic — this module is the
|
|
11
11
|
* un-wired core they're built from, not a separate implementation.
|
|
12
12
|
*/
|
|
13
|
-
export { decryptFromCore as decryptFrom, encryptForCore as encryptFor, establishSessionInitiatorCore as establishSessionInitiator, establishSessionResponderCore as establishSessionResponder, signCore as sign, UntrustedPartyError, verifyCore as verify, } from "./crypto/hybrid.js";
|
|
13
|
+
export { createResponderHandshakeCore as createResponderHandshake, decryptFromCore as decryptFrom, encryptForCore as encryptFor, establishSessionInitiatorCore as establishSessionInitiator, establishSessionResponderCore as establishSessionResponder, HandshakeVerificationError, signCore as sign, UntrustedPartyError, verifyCore as verify, } from "./crypto/hybrid.js";
|
|
14
14
|
export { generateClassicalKeypair, classicalSharedSecret, classicalSign, classicalVerify } from "./crypto/classical.js";
|
|
15
15
|
export { generatePqcKemKeypair, generatePqcSignKeypair, pqcDecapsulate, pqcEncapsulate, pqcSign, pqcVerify, } from "./crypto/pqc.js";
|
|
16
16
|
export { canonicalize, hashDocument } from "./canonicalJson.js";
|
|
17
17
|
export { fingerprint } from "./fingerprint.js";
|
|
18
18
|
export { decryptFrame, encryptFrame, FrameDecryptionError } from "./crypto/frameCipher.js";
|
|
19
|
+
export { CHAIN_INFO_INITIATOR_TO_RESPONDER, CHAIN_INFO_RESPONDER_TO_INITIATOR, ML_KEM_STEP_CADENCE, performEcdhStep, performKemStep, ratchetChainKey, seedChainKey, } from "./crypto/ratchet.js";
|
|
19
20
|
//# sourceMappingURL=core.js.map
|
package/dist/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EACL,eAAe,IAAI,WAAW,EAC9B,cAAc,IAAI,UAAU,EAC5B,6BAA6B,IAAI,yBAAyB,EAC1D,6BAA6B,IAAI,yBAAyB,EAC1D,QAAQ,IAAI,IAAI,EAChB,mBAAmB,EACnB,UAAU,IAAI,MAAM,GACrB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EACL,4BAA4B,IAAI,wBAAwB,EACxD,eAAe,IAAI,WAAW,EAC9B,cAAc,IAAI,UAAU,EAC5B,6BAA6B,IAAI,yBAAyB,EAC1D,6BAA6B,IAAI,yBAAyB,EAC1D,0BAA0B,EAC1B,QAAQ,IAAI,IAAI,EAChB,mBAAmB,EACnB,UAAU,IAAI,MAAM,GACrB,MAAM,oBAAoB,CAAC;AAqB5B,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxH,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,cAAc,EACd,cAAc,EACd,OAAO,EACP,SAAS,GACV,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG3F,OAAO,EACL,iCAAiC,EACjC,iCAAiC,EACjC,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,eAAe,EACf,YAAY,GACb,MAAM,qBAAqB,CAAC"}
|
package/dist/crypto/hybrid.d.ts
CHANGED
|
@@ -87,31 +87,105 @@ export declare function encryptForCore(identity: Identity, counterpart: PublicCa
|
|
|
87
87
|
*/
|
|
88
88
|
export declare function decryptFromCore<T = unknown>(identity: Identity, counterpart: PublicCard, box: EncryptedBox, deps: TrustDeps): Promise<T>;
|
|
89
89
|
export interface SessionKeys {
|
|
90
|
-
/** AES-256-GCM key for frames sent by the initiator
|
|
90
|
+
/** AES-256-GCM key for frames sent by the initiator, decrypted by the responder. */
|
|
91
91
|
initiatorToResponder: Uint8Array;
|
|
92
|
-
/** AES-256-GCM key for frames sent by the responder
|
|
92
|
+
/** AES-256-GCM key for frames sent by the responder, decrypted by the initiator. */
|
|
93
93
|
responderToInitiator: Uint8Array;
|
|
94
94
|
}
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
/** The dual classical+PQ signature over a handshake message's own signed ephemeral payload (see `handshakeSignedMessage`). */
|
|
96
|
+
export interface HandshakeSignature {
|
|
97
|
+
classicalSignature: string;
|
|
98
|
+
pqcSignature: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The responder's half of the handshake: one fresh ECDH-P384 public key,
|
|
102
|
+
* one fresh ML-KEM-1024 public key, and a per-handshake nonce, dual-signed
|
|
103
|
+
* with the responder's long-term classical+PQ signing keys.
|
|
104
|
+
*/
|
|
105
|
+
export interface ResponderHandshakeMessage {
|
|
106
|
+
ephemeralClassicalPublicKey: string;
|
|
107
|
+
ephemeralKemPublicKey: string;
|
|
108
|
+
nonce: string;
|
|
109
|
+
signature: HandshakeSignature;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The initiator's reply: its own fresh ECDH-P384 public key and nonce
|
|
113
|
+
* (dual-signed), plus the ML-KEM ciphertext encapsulated toward the
|
|
114
|
+
* responder's ephemeral KEM public key (never the responder's long-term
|
|
115
|
+
* one).
|
|
116
|
+
*/
|
|
117
|
+
export interface InitiatorHandshakeMessage {
|
|
118
|
+
ephemeralClassicalPublicKey: string;
|
|
119
|
+
nonce: string;
|
|
120
|
+
signature: HandshakeSignature;
|
|
97
121
|
kemCipherText: string;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The responder's ephemeral secrets plus everything needed to reconstruct
|
|
125
|
+
* its own signed message for the transcript hash later. Returned to the
|
|
126
|
+
* caller only to be threaded straight into `establishSessionResponderCore`
|
|
127
|
+
* for THIS handshake attempt — never persisted, logged, or attached to
|
|
128
|
+
* Identity, and discarded (left for GC) once that call returns.
|
|
129
|
+
*/
|
|
130
|
+
export interface ResponderHandshakeSecrets {
|
|
131
|
+
ephemeralClassicalSecretKey: Uint8Array;
|
|
132
|
+
ephemeralKemSecretKey: Uint8Array;
|
|
133
|
+
message: ResponderHandshakeMessage;
|
|
134
|
+
}
|
|
135
|
+
export interface ResponderHandshakeInit {
|
|
136
|
+
message: ResponderHandshakeMessage;
|
|
137
|
+
ephemeral: ResponderHandshakeSecrets;
|
|
138
|
+
}
|
|
139
|
+
export interface InitiatorSessionResult {
|
|
140
|
+
/** Send this to the responder to complete the handshake. */
|
|
141
|
+
message: InitiatorHandshakeMessage;
|
|
98
142
|
keys: SessionKeys;
|
|
143
|
+
/** HKDF output #3 — proves both sides derived the same combined secret before any chat/file-transfer traffic is trusted. Using it (e.g. as a MAC key over the transcript) is the caller's concern. */
|
|
144
|
+
confirmationKey: Uint8Array;
|
|
145
|
+
/** HKDF output #4 (additive, issue #29) — seeds a two-party ratchet (see ./ratchet.ts) built on top of this handshake. Not a replacement for `keys`/`confirmationKey`, and never used to encrypt a frame directly. */
|
|
146
|
+
rootKey: Uint8Array;
|
|
99
147
|
}
|
|
148
|
+
export interface ResponderSessionResult {
|
|
149
|
+
keys: SessionKeys;
|
|
150
|
+
confirmationKey: Uint8Array;
|
|
151
|
+
/** See InitiatorSessionResult.rootKey. */
|
|
152
|
+
rootKey: Uint8Array;
|
|
153
|
+
}
|
|
154
|
+
export declare class HandshakeVerificationError extends Error {
|
|
155
|
+
constructor(message: string);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* First step of the handshake, run by the connection's responder: generates
|
|
159
|
+
* one fresh, single-use ECDH-P384 keypair and one fresh, single-use
|
|
160
|
+
* ML-KEM-1024 keypair, a per-handshake nonce, and dual-signs all three with
|
|
161
|
+
* the responder's long-term classical+PQ signing keys. `message` is sent to
|
|
162
|
+
* the initiator (it can ride alongside the responder's PublicCard); `ephemeral`
|
|
163
|
+
* must be held in memory only and passed straight into
|
|
164
|
+
* `establishSessionResponderCore` once the initiator's reply arrives, then
|
|
165
|
+
* discarded.
|
|
166
|
+
*/
|
|
167
|
+
export declare function createResponderHandshakeCore(identity: Identity): ResponderHandshakeInit;
|
|
100
168
|
/**
|
|
101
|
-
* Establishes a session as the connection's initiator
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* toward
|
|
106
|
-
*
|
|
107
|
-
*
|
|
169
|
+
* Establishes a session as the connection's initiator, given the
|
|
170
|
+
* responder's `ResponderHandshakeMessage`. Verifies the responder's dual
|
|
171
|
+
* signature (throws `HandshakeVerificationError` on failure), generates its
|
|
172
|
+
* own fresh, single-use ECDH-P384 keypair and nonce, dual-signs them,
|
|
173
|
+
* encapsulates toward the responder's ephemeral KEM public key, and derives
|
|
174
|
+
* the Session Keys plus a key-confirmation key from the combined ephemeral
|
|
175
|
+
* ECDH + KEM + long-term ECDH secret, salted by a hash of the full
|
|
176
|
+
* handshake transcript. The returned `message` is sent to the responder to
|
|
177
|
+
* complete the handshake. No trust dependency: establishing a session never
|
|
178
|
+
* checks anyone's trust status, same as signCore.
|
|
108
179
|
*/
|
|
109
|
-
export declare function establishSessionInitiatorCore(identity: Identity, counterpart: PublicCard): InitiatorSessionResult;
|
|
180
|
+
export declare function establishSessionInitiatorCore(identity: Identity, counterpart: PublicCard, responderMessage: ResponderHandshakeMessage): InitiatorSessionResult;
|
|
110
181
|
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
182
|
+
* Completes the handshake as the connection's responder, given the
|
|
183
|
+
* `ephemeral` secrets returned by `createResponderHandshakeCore` and the
|
|
184
|
+
* initiator's `InitiatorHandshakeMessage`. Verifies the initiator's dual
|
|
185
|
+
* signature (throws `HandshakeVerificationError` on failure), decapsulates
|
|
186
|
+
* the KEM ciphertext with the ephemeral KEM secret key, computes the
|
|
187
|
+
* ephemeral ECDH secret, and derives the same Session Keys and
|
|
188
|
+
* confirmation key the initiator derived.
|
|
115
189
|
*/
|
|
116
|
-
export declare function establishSessionResponderCore(identity: Identity, counterpart: PublicCard,
|
|
190
|
+
export declare function establishSessionResponderCore(identity: Identity, counterpart: PublicCard, ephemeral: ResponderHandshakeSecrets, initiatorMessage: InitiatorHandshakeMessage): ResponderSessionResult;
|
|
117
191
|
export {};
|
package/dist/crypto/hybrid.js
CHANGED
|
@@ -3,8 +3,8 @@ import { hkdf } from "@noble/hashes/hkdf.js";
|
|
|
3
3
|
import { sha384 } from "@noble/hashes/sha2.js";
|
|
4
4
|
import { bytesToHex, concatBytes, hexToBytes, randomBytes, utf8ToBytes } from "@noble/hashes/utils.js";
|
|
5
5
|
import { canonicalize, hashDocument } from "../canonicalJson.js";
|
|
6
|
-
import { classicalSharedSecret, classicalSign, classicalVerify } from "./classical.js";
|
|
7
|
-
import { pqcDecapsulate, pqcEncapsulate, pqcSign, pqcVerify } from "./pqc.js";
|
|
6
|
+
import { classicalSharedSecret, classicalSign, classicalVerify, generateClassicalKeypair } from "./classical.js";
|
|
7
|
+
import { generatePqcKemKeypair, pqcDecapsulate, pqcEncapsulate, pqcSign, pqcVerify } from "./pqc.js";
|
|
8
8
|
// No import of ../store.js or ../trust.js here (only their LogEntry TYPE,
|
|
9
9
|
// which is erased at compile time) — this file must stay resolvable by a
|
|
10
10
|
// browser bundler on its own. The node:fs-backed default wiring for
|
|
@@ -139,42 +139,175 @@ export async function decryptFromCore(identity, counterpart, box, deps) {
|
|
|
139
139
|
//
|
|
140
140
|
// encryptForCore/decryptFromCore above do a full ECDH + ML-KEM encapsulation
|
|
141
141
|
// PER CALL — fine for a one-off document, prohibitively expensive if called
|
|
142
|
-
// once per 16 KiB chunk of a large file transfer. The functions below run
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
142
|
+
// once per 16 KiB chunk of a large file transfer. The functions below run a
|
|
143
|
+
// hybrid exchange ONCE per connection and hand back a pair of directional
|
|
144
|
+
// keys the caller reuses (via a separate per-frame cipher, not implemented
|
|
145
|
+
// here) for as many messages as the connection carries.
|
|
146
|
+
//
|
|
147
|
+
// This handshake is ephemeral and authenticated (see docs/adr/0006, which
|
|
148
|
+
// supersedes ADR 0004's single-encapsulation design): each side generates a
|
|
149
|
+
// fresh, single-use ECDH-P384 keypair per session attempt (the responder
|
|
150
|
+
// also a fresh, single-use ML-KEM-1024 keypair), signs its own ephemeral
|
|
151
|
+
// public key(s) plus a per-handshake nonce with its long-term classical and
|
|
152
|
+
// PQ signing keys (the same dual-signature mechanism signCore/verifyCore use
|
|
153
|
+
// for documents), and the counterpart verifies both signatures before
|
|
154
|
+
// trusting the signed ephemeral key(s). The combined secret folds together
|
|
155
|
+
// the fresh ephemeral ECDH secret, the KEM-encapsulated secret, AND the
|
|
156
|
+
// existing long-term (static) ECDH secret (defense-in-depth; forward
|
|
157
|
+
// secrecy itself rests entirely on the ephemeral secrets being discarded).
|
|
158
|
+
// None of the ephemeral secret keys are ever attached to Identity,
|
|
159
|
+
// persisted, or logged — they live only in the return value of
|
|
160
|
+
// createResponderHandshakeCore and the stack of establishSessionInitiatorCore,
|
|
161
|
+
// for the lifetime of one handshake attempt.
|
|
162
|
+
//
|
|
163
|
+
// Wire shape: the responder generates its ephemeral keys first and sends
|
|
164
|
+
// ResponderHandshakeMessage (this can ride alongside the responder's
|
|
165
|
+
// PublicCard, since nothing in it depends on anything from the initiator);
|
|
166
|
+
// the initiator replies with InitiatorHandshakeMessage, which is the only
|
|
167
|
+
// message carrying the KEM ciphertext (the initiator is the one who
|
|
168
|
+
// encapsulates, same initiator/responder asymmetry ADR 0004 already
|
|
169
|
+
// established); the responder completes the handshake from that reply.
|
|
170
|
+
const SESSION_INFO_INITIATOR_TO_RESPONDER = utf8ToBytes("raz-encrypt-session-v2|initiator-to-responder");
|
|
171
|
+
const SESSION_INFO_RESPONDER_TO_INITIATOR = utf8ToBytes("raz-encrypt-session-v2|responder-to-initiator");
|
|
172
|
+
const SESSION_INFO_KEY_CONFIRMATION = utf8ToBytes("raz-encrypt-session-v2|key-confirmation");
|
|
173
|
+
// A fourth, additional HKDF output (issue #29/raz-encrypt #29) from the exact
|
|
174
|
+
// same combined input key material and transcript salt as the three outputs
|
|
175
|
+
// above — NOT a repurposing of any of them. This is the seed for a two-party
|
|
176
|
+
// ratchet (see ./ratchet.ts) built on top of the handshake, never itself used
|
|
177
|
+
// to encrypt a frame directly.
|
|
178
|
+
const SESSION_INFO_ROOT_KEY = utf8ToBytes("raz-encrypt-session-v2|root-key");
|
|
179
|
+
export class HandshakeVerificationError extends Error {
|
|
180
|
+
constructor(message) {
|
|
181
|
+
super(message);
|
|
182
|
+
this.name = "HandshakeVerificationError";
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/** Reconstructs the counterpart-facing PublicCard shape from an Identity, without importing identity.js (which pulls in node:fs) — keeps this module browser-safe. */
|
|
186
|
+
function publicCardOf(identity) {
|
|
150
187
|
return {
|
|
151
|
-
|
|
152
|
-
|
|
188
|
+
alias: identity.alias,
|
|
189
|
+
classicalPublicKey: bytesToHex(identity.classical.publicKey),
|
|
190
|
+
pqcSignPublicKey: bytesToHex(identity.pqcSign.publicKey),
|
|
191
|
+
pqcKemPublicKey: bytesToHex(identity.pqcKem.publicKey),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/** The exact bytes a handshake signature is computed over — mirrors `signedMessage`'s canonicalize-then-sign-directly shape, applied to ephemeral handshake material instead of a document. */
|
|
195
|
+
function handshakeSignedMessage(payload) {
|
|
196
|
+
return utf8ToBytes(canonicalize(payload));
|
|
197
|
+
}
|
|
198
|
+
function signHandshakePayload(identity, payload) {
|
|
199
|
+
const message = handshakeSignedMessage(payload);
|
|
200
|
+
return {
|
|
201
|
+
classicalSignature: bytesToHex(classicalSign(message, identity.classical.secretKey)),
|
|
202
|
+
pqcSignature: bytesToHex(pqcSign(message, identity.pqcSign.secretKey)),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/** Throws HandshakeVerificationError unless BOTH the classical and PQ signatures check out — mirrors verifyCore's all-or-nothing dual-signature requirement. */
|
|
206
|
+
function verifyHandshakeSignature(signer, payload, signature) {
|
|
207
|
+
const message = handshakeSignedMessage(payload);
|
|
208
|
+
const classicalOk = classicalVerify(hexToBytes(signature.classicalSignature), message, hexToBytes(signer.classicalPublicKey));
|
|
209
|
+
if (!classicalOk)
|
|
210
|
+
throw new HandshakeVerificationError(`Handshake rejected: classical signature from "${signer.alias}" did not verify.`);
|
|
211
|
+
const pqcOk = pqcVerify(hexToBytes(signature.pqcSignature), message, hexToBytes(signer.pqcSignPublicKey));
|
|
212
|
+
if (!pqcOk)
|
|
213
|
+
throw new HandshakeVerificationError(`Handshake rejected: PQC signature from "${signer.alias}" did not verify.`);
|
|
214
|
+
}
|
|
215
|
+
function handshakeTranscriptSalt(initiatorCard, responderCard, responderMessage, initiatorEphemeral) {
|
|
216
|
+
return sha384(utf8ToBytes(canonicalize({ initiatorCard, responderCard, responderMessage, initiatorEphemeral })));
|
|
217
|
+
}
|
|
218
|
+
function deriveSessionSecrets(ephemeralEcdhSecret, kemSecret, staticEcdhSecret, transcriptSalt) {
|
|
219
|
+
const ikm = concatBytes(ephemeralEcdhSecret, kemSecret, staticEcdhSecret);
|
|
220
|
+
return {
|
|
221
|
+
keys: {
|
|
222
|
+
initiatorToResponder: hkdf(sha384, ikm, transcriptSalt, SESSION_INFO_INITIATOR_TO_RESPONDER, 32),
|
|
223
|
+
responderToInitiator: hkdf(sha384, ikm, transcriptSalt, SESSION_INFO_RESPONDER_TO_INITIATOR, 32),
|
|
224
|
+
},
|
|
225
|
+
confirmationKey: hkdf(sha384, ikm, transcriptSalt, SESSION_INFO_KEY_CONFIRMATION, 32),
|
|
226
|
+
rootKey: hkdf(sha384, ikm, transcriptSalt, SESSION_INFO_ROOT_KEY, 32),
|
|
153
227
|
};
|
|
154
228
|
}
|
|
155
229
|
/**
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* the
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
230
|
+
* First step of the handshake, run by the connection's responder: generates
|
|
231
|
+
* one fresh, single-use ECDH-P384 keypair and one fresh, single-use
|
|
232
|
+
* ML-KEM-1024 keypair, a per-handshake nonce, and dual-signs all three with
|
|
233
|
+
* the responder's long-term classical+PQ signing keys. `message` is sent to
|
|
234
|
+
* the initiator (it can ride alongside the responder's PublicCard); `ephemeral`
|
|
235
|
+
* must be held in memory only and passed straight into
|
|
236
|
+
* `establishSessionResponderCore` once the initiator's reply arrives, then
|
|
237
|
+
* discarded.
|
|
163
238
|
*/
|
|
164
|
-
export function
|
|
165
|
-
const
|
|
166
|
-
const
|
|
167
|
-
|
|
239
|
+
export function createResponderHandshakeCore(identity) {
|
|
240
|
+
const ephemeralClassical = generateClassicalKeypair();
|
|
241
|
+
const ephemeralKem = generatePqcKemKeypair();
|
|
242
|
+
const nonce = bytesToHex(randomBytes(32));
|
|
243
|
+
const payload = {
|
|
244
|
+
ephemeralClassicalPublicKey: bytesToHex(ephemeralClassical.publicKey),
|
|
245
|
+
ephemeralKemPublicKey: bytesToHex(ephemeralKem.publicKey),
|
|
246
|
+
nonce,
|
|
247
|
+
};
|
|
248
|
+
const signature = signHandshakePayload(identity, payload);
|
|
249
|
+
const message = { ...payload, signature };
|
|
250
|
+
return {
|
|
251
|
+
message,
|
|
252
|
+
ephemeral: {
|
|
253
|
+
ephemeralClassicalSecretKey: ephemeralClassical.secretKey,
|
|
254
|
+
ephemeralKemSecretKey: ephemeralKem.secretKey,
|
|
255
|
+
message,
|
|
256
|
+
},
|
|
257
|
+
};
|
|
168
258
|
}
|
|
169
259
|
/**
|
|
170
|
-
* Establishes a session as the connection's
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
260
|
+
* Establishes a session as the connection's initiator, given the
|
|
261
|
+
* responder's `ResponderHandshakeMessage`. Verifies the responder's dual
|
|
262
|
+
* signature (throws `HandshakeVerificationError` on failure), generates its
|
|
263
|
+
* own fresh, single-use ECDH-P384 keypair and nonce, dual-signs them,
|
|
264
|
+
* encapsulates toward the responder's ephemeral KEM public key, and derives
|
|
265
|
+
* the Session Keys plus a key-confirmation key from the combined ephemeral
|
|
266
|
+
* ECDH + KEM + long-term ECDH secret, salted by a hash of the full
|
|
267
|
+
* handshake transcript. The returned `message` is sent to the responder to
|
|
268
|
+
* complete the handshake. No trust dependency: establishing a session never
|
|
269
|
+
* checks anyone's trust status, same as signCore.
|
|
174
270
|
*/
|
|
175
|
-
export function
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
271
|
+
export function establishSessionInitiatorCore(identity, counterpart, responderMessage) {
|
|
272
|
+
verifyHandshakeSignature(counterpart, {
|
|
273
|
+
ephemeralClassicalPublicKey: responderMessage.ephemeralClassicalPublicKey,
|
|
274
|
+
ephemeralKemPublicKey: responderMessage.ephemeralKemPublicKey,
|
|
275
|
+
nonce: responderMessage.nonce,
|
|
276
|
+
}, responderMessage.signature);
|
|
277
|
+
const ephemeralClassical = generateClassicalKeypair();
|
|
278
|
+
const nonce = bytesToHex(randomBytes(32));
|
|
279
|
+
const payload = { ephemeralClassicalPublicKey: bytesToHex(ephemeralClassical.publicKey), nonce };
|
|
280
|
+
const signature = signHandshakePayload(identity, payload);
|
|
281
|
+
const ephemeralEcdhSecret = classicalSharedSecret(ephemeralClassical.secretKey, hexToBytes(responderMessage.ephemeralClassicalPublicKey));
|
|
282
|
+
const { cipherText, sharedSecret: kemSecret } = pqcEncapsulate(hexToBytes(responderMessage.ephemeralKemPublicKey));
|
|
283
|
+
const staticEcdhSecret = classicalSharedSecret(identity.classical.secretKey, hexToBytes(counterpart.classicalPublicKey));
|
|
284
|
+
const transcriptSalt = handshakeTranscriptSalt(publicCardOf(identity), counterpart, responderMessage, payload);
|
|
285
|
+
const { keys, confirmationKey, rootKey } = deriveSessionSecrets(ephemeralEcdhSecret, kemSecret, staticEcdhSecret, transcriptSalt);
|
|
286
|
+
return {
|
|
287
|
+
message: { ...payload, signature, kemCipherText: bytesToHex(cipherText) },
|
|
288
|
+
keys,
|
|
289
|
+
confirmationKey,
|
|
290
|
+
rootKey,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Completes the handshake as the connection's responder, given the
|
|
295
|
+
* `ephemeral` secrets returned by `createResponderHandshakeCore` and the
|
|
296
|
+
* initiator's `InitiatorHandshakeMessage`. Verifies the initiator's dual
|
|
297
|
+
* signature (throws `HandshakeVerificationError` on failure), decapsulates
|
|
298
|
+
* the KEM ciphertext with the ephemeral KEM secret key, computes the
|
|
299
|
+
* ephemeral ECDH secret, and derives the same Session Keys and
|
|
300
|
+
* confirmation key the initiator derived.
|
|
301
|
+
*/
|
|
302
|
+
export function establishSessionResponderCore(identity, counterpart, ephemeral, initiatorMessage) {
|
|
303
|
+
verifyHandshakeSignature(counterpart, { ephemeralClassicalPublicKey: initiatorMessage.ephemeralClassicalPublicKey, nonce: initiatorMessage.nonce }, initiatorMessage.signature);
|
|
304
|
+
const ephemeralEcdhSecret = classicalSharedSecret(ephemeral.ephemeralClassicalSecretKey, hexToBytes(initiatorMessage.ephemeralClassicalPublicKey));
|
|
305
|
+
const kemSecret = pqcDecapsulate(hexToBytes(initiatorMessage.kemCipherText), ephemeral.ephemeralKemSecretKey);
|
|
306
|
+
const staticEcdhSecret = classicalSharedSecret(identity.classical.secretKey, hexToBytes(counterpart.classicalPublicKey));
|
|
307
|
+
const transcriptSalt = handshakeTranscriptSalt(counterpart, publicCardOf(identity), ephemeral.message, {
|
|
308
|
+
ephemeralClassicalPublicKey: initiatorMessage.ephemeralClassicalPublicKey,
|
|
309
|
+
nonce: initiatorMessage.nonce,
|
|
310
|
+
});
|
|
311
|
+
return deriveSessionSecrets(ephemeralEcdhSecret, kemSecret, staticEcdhSecret, transcriptSalt);
|
|
179
312
|
}
|
|
180
313
|
//# sourceMappingURL=hybrid.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hybrid.js","sourceRoot":"","sources":["../../src/crypto/hybrid.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hybrid.js","sourceRoot":"","sources":["../../src/crypto/hybrid.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { type ClassicalKeypair } from "./classical.js";
|
|
2
|
+
/** Domain-separation label for `seedChainKey`'s `direction` parameter — mirrors hybrid.ts's SESSION_INFO_* labels, applied to chain keys instead of Session Keys. */
|
|
3
|
+
export declare const CHAIN_INFO_INITIATOR_TO_RESPONDER: Uint8Array<ArrayBufferLike> & Uint8Array<ArrayBuffer>;
|
|
4
|
+
/** See CHAIN_INFO_INITIATOR_TO_RESPONDER. */
|
|
5
|
+
export declare const CHAIN_INFO_RESPONDER_TO_INITIATOR: Uint8Array<ArrayBufferLike> & Uint8Array<ArrayBuffer>;
|
|
6
|
+
/**
|
|
7
|
+
* How many control-type messages (chat/file-lifecycle; file-chunk/binary
|
|
8
|
+
* traffic is never counted), summed across BOTH directions combined, trigger
|
|
9
|
+
* one ML-KEM-1024 asymmetric step (see `performKemStep`). Named and exported
|
|
10
|
+
* so the recovery-speed-vs-overhead trade-off is visible and adjustable in
|
|
11
|
+
* one place, rather than a magic number buried in `secureConnection.ts`'s
|
|
12
|
+
* (ticket #30's) triggering logic — which is also where the actual counting
|
|
13
|
+
* happens; this constant is consumed there, not here.
|
|
14
|
+
*/
|
|
15
|
+
export declare const ML_KEM_STEP_CADENCE = 20;
|
|
16
|
+
/**
|
|
17
|
+
* Seeds a per-direction chain key from the handshake's `rootKey` output (see
|
|
18
|
+
* hybrid.ts's InitiatorSessionResult/ResponderSessionResult). Pass one of
|
|
19
|
+
* CHAIN_INFO_INITIATOR_TO_RESPONDER / CHAIN_INFO_RESPONDER_TO_INITIATOR as
|
|
20
|
+
* `direction` — the two directions always seed distinct chain keys from the
|
|
21
|
+
* same root key, mirroring how a Session's two directional keys are split
|
|
22
|
+
* from one combined secret.
|
|
23
|
+
*/
|
|
24
|
+
export declare function seedChainKey(rootKey: Uint8Array, direction: Uint8Array): Uint8Array;
|
|
25
|
+
/** The result of advancing a chain key by one message: the single-use key for THIS message, and the chain key's new value for the next one. */
|
|
26
|
+
export interface ChainStep {
|
|
27
|
+
/** Single-use — encrypt/decrypt exactly one frame with this, then discard it. Never reused. */
|
|
28
|
+
messageKey: Uint8Array;
|
|
29
|
+
/** Replaces the chain key passed into `ratchetChainKey`. The old chain key must not be kept. */
|
|
30
|
+
nextChainKey: Uint8Array;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Derives a single-use message key from `chainKey` AND advances the chain to
|
|
34
|
+
* its next value, in the same operation — so by the time this call returns,
|
|
35
|
+
* the OLD chain key is gone (the caller must not retain it) and a fresh
|
|
36
|
+
* `nextChainKey` stands in its place. Both outputs are one-way functions of
|
|
37
|
+
* `chainKey` (HKDF-SHA384 with distinct, fixed info labels): holding
|
|
38
|
+
* `nextChainKey` alone never lets you recover `chainKey` or `messageKey`
|
|
39
|
+
* (forward secrecy at the symmetric-chain level — see
|
|
40
|
+
* test/ratchet.test.ts's forward-secrecy suite).
|
|
41
|
+
*/
|
|
42
|
+
export declare function ratchetChainKey(chainKey: Uint8Array): ChainStep;
|
|
43
|
+
/** The result of an asymmetric step (ECDH or ML-KEM): a new root key, and a freshly re-seeded SENDING chain key for the side that performed the step. The other direction's chain is untouched until it performs its own step (Double-Ratchet-style asymmetry). */
|
|
44
|
+
export interface AsymmetricStepResult {
|
|
45
|
+
rootKey: Uint8Array;
|
|
46
|
+
sendingChainKey: Uint8Array;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The ECDH-P384 asymmetric step: mixes a fresh ephemeral ECDH shared secret
|
|
50
|
+
* into the current root key (producing a new root key) and re-seeds the
|
|
51
|
+
* stepping side's own sending chain key from it. `ephemeral` is a freshly
|
|
52
|
+
* generated keypair (reuse `generateClassicalKeypair` from ./classical.js —
|
|
53
|
+
* this function does not generate keys itself); `counterpartEphemeralPublicKey`
|
|
54
|
+
* is the counterpart's most recently received ephemeral public key.
|
|
55
|
+
*
|
|
56
|
+
* Deciding WHEN to call this ("a reply after receiving") is out of scope —
|
|
57
|
+
* that is ticket #30's `secureConnection.ts` connection-level state.
|
|
58
|
+
*/
|
|
59
|
+
export declare function performEcdhStep(rootKey: Uint8Array, ephemeral: ClassicalKeypair, counterpartEphemeralPublicKey: Uint8Array, sendingDirection: Uint8Array): AsymmetricStepResult;
|
|
60
|
+
/**
|
|
61
|
+
* The ML-KEM-1024 asymmetric step: mixes an ML-KEM-encapsulated (sender) or
|
|
62
|
+
* decapsulated (receiver) shared secret — `kemSecret`, from
|
|
63
|
+
* `pqcEncapsulate`/`pqcDecapsulate` in ./pqc.js, which this function does not
|
|
64
|
+
* call itself — into the current root key, and re-seeds the stepping side's
|
|
65
|
+
* sending chain key from the result. Cadence (how often this fires) is
|
|
66
|
+
* `ML_KEM_STEP_CADENCE`, counted and triggered by ticket #30, not here.
|
|
67
|
+
*/
|
|
68
|
+
export declare function performKemStep(rootKey: Uint8Array, kemSecret: Uint8Array, sendingDirection: Uint8Array): AsymmetricStepResult;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { hkdf } from "@noble/hashes/hkdf.js";
|
|
2
|
+
import { sha384 } from "@noble/hashes/sha2.js";
|
|
3
|
+
import { concatBytes, utf8ToBytes } from "@noble/hashes/utils.js";
|
|
4
|
+
import { classicalSharedSecret } from "./classical.js";
|
|
5
|
+
// The two-party ratchet (issue #17/#29): built ON TOP OF the handshake in
|
|
6
|
+
// ./hybrid.ts, seeded from its additional `rootKey` output. See docs/adr for
|
|
7
|
+
// the full design and its deliberate, explicit contrast with Signal's Double
|
|
8
|
+
// Ratchet (no skipped-message-key cache, no out-of-order handling, no
|
|
9
|
+
// group/multi-device fan-out — this stays two-party-only and in-order-only,
|
|
10
|
+
// matching this project's always-ordered, always-1:1 transport).
|
|
11
|
+
//
|
|
12
|
+
// Everything here is a PURE function: no "when do I step" logic, no
|
|
13
|
+
// connection-level state, no wire format. The caller (`secureConnection.ts`'s
|
|
14
|
+
// Envelope layer, a later, currently-blocked ticket) drives all of that.
|
|
15
|
+
const CHAIN_INFO_PREFIX = utf8ToBytes("raz-encrypt-ratchet-v1|chain|");
|
|
16
|
+
const MESSAGE_KEY_INFO = utf8ToBytes("raz-encrypt-ratchet-v1|message-key");
|
|
17
|
+
const CHAIN_ADVANCE_INFO = utf8ToBytes("raz-encrypt-ratchet-v1|chain-advance");
|
|
18
|
+
const ROOT_KEY_ECDH_STEP_INFO = utf8ToBytes("raz-encrypt-ratchet-v1|root-key|ecdh-step");
|
|
19
|
+
const ROOT_KEY_KEM_STEP_INFO = utf8ToBytes("raz-encrypt-ratchet-v1|root-key|kem-step");
|
|
20
|
+
/** Domain-separation label for `seedChainKey`'s `direction` parameter — mirrors hybrid.ts's SESSION_INFO_* labels, applied to chain keys instead of Session Keys. */
|
|
21
|
+
export const CHAIN_INFO_INITIATOR_TO_RESPONDER = concatBytes(CHAIN_INFO_PREFIX, utf8ToBytes("initiator-to-responder"));
|
|
22
|
+
/** See CHAIN_INFO_INITIATOR_TO_RESPONDER. */
|
|
23
|
+
export const CHAIN_INFO_RESPONDER_TO_INITIATOR = concatBytes(CHAIN_INFO_PREFIX, utf8ToBytes("responder-to-initiator"));
|
|
24
|
+
/**
|
|
25
|
+
* How many control-type messages (chat/file-lifecycle; file-chunk/binary
|
|
26
|
+
* traffic is never counted), summed across BOTH directions combined, trigger
|
|
27
|
+
* one ML-KEM-1024 asymmetric step (see `performKemStep`). Named and exported
|
|
28
|
+
* so the recovery-speed-vs-overhead trade-off is visible and adjustable in
|
|
29
|
+
* one place, rather than a magic number buried in `secureConnection.ts`'s
|
|
30
|
+
* (ticket #30's) triggering logic — which is also where the actual counting
|
|
31
|
+
* happens; this constant is consumed there, not here.
|
|
32
|
+
*/
|
|
33
|
+
export const ML_KEM_STEP_CADENCE = 20;
|
|
34
|
+
/**
|
|
35
|
+
* Seeds a per-direction chain key from the handshake's `rootKey` output (see
|
|
36
|
+
* hybrid.ts's InitiatorSessionResult/ResponderSessionResult). Pass one of
|
|
37
|
+
* CHAIN_INFO_INITIATOR_TO_RESPONDER / CHAIN_INFO_RESPONDER_TO_INITIATOR as
|
|
38
|
+
* `direction` — the two directions always seed distinct chain keys from the
|
|
39
|
+
* same root key, mirroring how a Session's two directional keys are split
|
|
40
|
+
* from one combined secret.
|
|
41
|
+
*/
|
|
42
|
+
export function seedChainKey(rootKey, direction) {
|
|
43
|
+
return hkdf(sha384, rootKey, undefined, direction, 32);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Derives a single-use message key from `chainKey` AND advances the chain to
|
|
47
|
+
* its next value, in the same operation — so by the time this call returns,
|
|
48
|
+
* the OLD chain key is gone (the caller must not retain it) and a fresh
|
|
49
|
+
* `nextChainKey` stands in its place. Both outputs are one-way functions of
|
|
50
|
+
* `chainKey` (HKDF-SHA384 with distinct, fixed info labels): holding
|
|
51
|
+
* `nextChainKey` alone never lets you recover `chainKey` or `messageKey`
|
|
52
|
+
* (forward secrecy at the symmetric-chain level — see
|
|
53
|
+
* test/ratchet.test.ts's forward-secrecy suite).
|
|
54
|
+
*/
|
|
55
|
+
export function ratchetChainKey(chainKey) {
|
|
56
|
+
return {
|
|
57
|
+
messageKey: hkdf(sha384, chainKey, undefined, MESSAGE_KEY_INFO, 32),
|
|
58
|
+
nextChainKey: hkdf(sha384, chainKey, undefined, CHAIN_ADVANCE_INFO, 32),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The ECDH-P384 asymmetric step: mixes a fresh ephemeral ECDH shared secret
|
|
63
|
+
* into the current root key (producing a new root key) and re-seeds the
|
|
64
|
+
* stepping side's own sending chain key from it. `ephemeral` is a freshly
|
|
65
|
+
* generated keypair (reuse `generateClassicalKeypair` from ./classical.js —
|
|
66
|
+
* this function does not generate keys itself); `counterpartEphemeralPublicKey`
|
|
67
|
+
* is the counterpart's most recently received ephemeral public key.
|
|
68
|
+
*
|
|
69
|
+
* Deciding WHEN to call this ("a reply after receiving") is out of scope —
|
|
70
|
+
* that is ticket #30's `secureConnection.ts` connection-level state.
|
|
71
|
+
*/
|
|
72
|
+
export function performEcdhStep(rootKey, ephemeral, counterpartEphemeralPublicKey, sendingDirection) {
|
|
73
|
+
const sharedSecret = classicalSharedSecret(ephemeral.secretKey, counterpartEphemeralPublicKey);
|
|
74
|
+
const newRootKey = hkdf(sha384, concatBytes(rootKey, sharedSecret), undefined, ROOT_KEY_ECDH_STEP_INFO, 32);
|
|
75
|
+
return { rootKey: newRootKey, sendingChainKey: seedChainKey(newRootKey, sendingDirection) };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The ML-KEM-1024 asymmetric step: mixes an ML-KEM-encapsulated (sender) or
|
|
79
|
+
* decapsulated (receiver) shared secret — `kemSecret`, from
|
|
80
|
+
* `pqcEncapsulate`/`pqcDecapsulate` in ./pqc.js, which this function does not
|
|
81
|
+
* call itself — into the current root key, and re-seeds the stepping side's
|
|
82
|
+
* sending chain key from the result. Cadence (how often this fires) is
|
|
83
|
+
* `ML_KEM_STEP_CADENCE`, counted and triggered by ticket #30, not here.
|
|
84
|
+
*/
|
|
85
|
+
export function performKemStep(rootKey, kemSecret, sendingDirection) {
|
|
86
|
+
const newRootKey = hkdf(sha384, concatBytes(rootKey, kemSecret), undefined, ROOT_KEY_KEM_STEP_INFO, 32);
|
|
87
|
+
return { rootKey: newRootKey, sendingChainKey: seedChainKey(newRootKey, sendingDirection) };
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=ratchet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ratchet.js","sourceRoot":"","sources":["../../src/crypto/ratchet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAyB,MAAM,gBAAgB,CAAC;AAE9E,0EAA0E;AAC1E,6EAA6E;AAC7E,6EAA6E;AAC7E,sEAAsE;AACtE,4EAA4E;AAC5E,iEAAiE;AACjE,EAAE;AACF,oEAAoE;AACpE,8EAA8E;AAC9E,yEAAyE;AAEzE,MAAM,iBAAiB,GAAG,WAAW,CAAC,+BAA+B,CAAC,CAAC;AACvE,MAAM,gBAAgB,GAAG,WAAW,CAAC,oCAAoC,CAAC,CAAC;AAC3E,MAAM,kBAAkB,GAAG,WAAW,CAAC,sCAAsC,CAAC,CAAC;AAC/E,MAAM,uBAAuB,GAAG,WAAW,CAAC,2CAA2C,CAAC,CAAC;AACzF,MAAM,sBAAsB,GAAG,WAAW,CAAC,0CAA0C,CAAC,CAAC;AAEvF,qKAAqK;AACrK,MAAM,CAAC,MAAM,iCAAiC,GAAG,WAAW,CAAC,iBAAiB,EAAE,WAAW,CAAC,wBAAwB,CAAC,CAAC,CAAC;AACvH,6CAA6C;AAC7C,MAAM,CAAC,MAAM,iCAAiC,GAAG,WAAW,CAAC,iBAAiB,EAAE,WAAW,CAAC,wBAAwB,CAAC,CAAC,CAAC;AAEvH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAEtC;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,OAAmB,EAAE,SAAqB;IACrE,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AACzD,CAAC;AAUD;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,QAAoB;IAClD,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,EAAE,CAAC;QACnE,YAAY,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,EAAE,CAAC;KACxE,CAAC;AACJ,CAAC;AAQD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAmB,EACnB,SAA2B,EAC3B,6BAAyC,EACzC,gBAA4B;IAE5B,MAAM,YAAY,GAAG,qBAAqB,CAAC,SAAS,CAAC,SAAS,EAAE,6BAA6B,CAAC,CAAC;IAC/F,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,SAAS,EAAE,uBAAuB,EAAE,EAAE,CAAC,CAAC;IAC5G,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,CAAC,UAAU,EAAE,gBAAgB,CAAC,EAAE,CAAC;AAC9F,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,OAAmB,EAAE,SAAqB,EAAE,gBAA4B;IACrG,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,SAAS,EAAE,sBAAsB,EAAE,EAAE,CAAC,CAAC;IACxG,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,CAAC,UAAU,EAAE,gBAAgB,CAAC,EAAE,CAAC;AAC9F,CAAC"}
|
package/package.json
CHANGED