quantum-resistant-rustykey 0.4.1 → 0.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/README.md CHANGED
@@ -1,68 +1,69 @@
1
- **Note**: 🚧 WORK IN PROGRESS...do not pnpm install 🚧
2
-
3
1
  # Quantum-Resistant RustyKey®
4
2
 
5
- A WebAssembly implementation of ML-KEM (Quantum-Resistant Signatures) for both Node.js and web environments. This is an improved version of the NIST winner's standard implementation, patched to withstand side-channel attacks.
6
-
7
- <!-- > **Note**: 🚧 WORK IN PROGRESS...do not install 🚧 -->
8
- <p align="center">
9
- <img src="./kyber.png"/>
10
- </p>
11
-
12
-
13
- ## About
14
- You use this quantum-resistant RustyKey® npm package mainly for secure key exchange, specifically as a Key Encapsulation Mechanism (KEM). It's designed to securely establish a shared secret between two parties, which is then used for encryption with a symmetric algorithm like AES. While Kyber can be used for encryption, its primary function is to encapsulate and transmit a session key, not the data itself.
15
-
16
- Here's a more detailed explanation:
17
- Key Exchange (KEM):
18
- - to facilitate the secure exchange of a shared secret key between two parties. This shared key is then used to encrypt and decrypt data using a separate, symmetric encryption algorithm.
19
- Not Direct Encryption:
20
- - doesn't directly encrypt the data itself. It's designed to securely encapsulate a session key, which is then used to encrypt the actual data using a symmetric encryption algorithm.
21
- Hybrid Approach:
22
- - often used in a hybrid approach, combining it with symmetric encryption algorithms like AES for stronger security. Used to securely exchange a session key, then used to encrypt the data using AES.
23
- Post-Quantum Security:
24
- - a post-quantum cryptosystem, meaning it is designed to be secure against attacks from quantum computers. This makes it a valuable tool for securing communication in the future when quantum computers become more powerful.
25
-
26
- In essence, RustyKey® quantum-resistant npm package creates a secure handshake, establishing a shared secret key that can then be used to encrypt and decrypt data with a more efficient symmetric encryption algorithm
27
-
28
- ## Web Assembly implementation
29
- ### Pros
30
- #### Highly secure
31
- Wasm operates within a sandboxed environment, isolating it from the host system. This prevents malicious code within the Wasm module from directly accessing sensitive data or compromising system resources. JavaScript, while also sandboxed, has a larger attack surface due to its dynamic nature and access to a wider range of APIs.
32
- #### Reduced Attack Surface
33
- Since Wasm modules have limited access to system resources and APIs, their attack surface is smaller than that of JavaScript. This makes it more difficult for attackers to exploit vulnerabilities.
34
- #### fast
35
- (mostly!) as Web Assembly (WASM) implementations of algorithms offer near-native performance due to WASM's low-level of bytecode, which itself is usually orders of magnitude faster than JavaScript for computationally intensive tasks.
36
- #### Controlled Imports
37
- Wasm modules have explicit import declarations, defining the exact functions they can access from the host environment (usually JavaScript). This allows for fine-grained control over the module's capabilities. In contrast, JavaScript has more implicit access to APIs, making it harder to restrict its behavior.
38
- #### Static Analysis
39
- Wasm's binary format allows for static analysis and code validation. This enables browsers to verify the module's structure and behavior before execution, reducing the risk of introducing vulnerabilities. JavaScript, being dynamically typed and interpreted, is more challenging to analyze statically.
40
- #### Compilation and Validation
41
- Wasm code is compiled into a low-level bytecode that is validated before execution. This process helps to identify and prevent many types of vulnerabilities that are common in JavaScript, such as buffer overflows.
42
-
43
- ### Cons
44
- #### Complex
45
- WASM is more complex to work with than JavaScript, and requires a build process to compile code into WASM modules and manual memory management, which is why this package exists...to make it easier for developers and end-users to incorporate the benefits of increased security and faster speed into their authentication, authorization and other encryption/decryption workflows.
46
-
47
- #### No Direct DOM Access
48
- WASM cannot directly manipulate the DOM. It relies on JavaScript to interact with the DOM, which adds complexity and can affect performance when frequent DOM interactions are needed.
49
- #### Garbage Collection
50
- WASM relies on JavaScript for garbage collection, which can be less efficient compared to languages with native garbage collection.
51
- #### Limited API Access
52
- WASM has limited access to browser and Node.js APIs compared to JavaScript, requiring JavaScript to act as a bridge for these interactions.
53
- #### Data Transfer Overhead
54
- Passing data between WASM and JavaScript can incur performance overhead due to serialization and deserialization.
55
-
56
- ### Algorithm source
57
- Based on a suite of "Cryptographic Suite for Algebraic Lattices" (CRYSTALS) based on hard problems over module lattices, designed to withstand attacks by large quantum computers, and selected among the winners of the [NIST post-quantum cryptography project](https://pq-crystals.org/index.shtml)
58
-
59
- | Package | Registry | Description |
60
- |---------|----------|-------------|
61
- | quantum-resistant-rustykey | [![npm](https://img.shields.io/npm/v/quantum-resistant-rustykey)](https://www.npmjs.com/package/quantum-resistant-rustykey) | 🚧 WORK IN PROGRESS 🚧 |
3
+ A WebAssembly implementation of ML-KEM for both Node.js and web environments.
4
+
5
+ ## Implementation status
6
+
7
+ - **ML-KEM-512**, **ML-KEM-768**, and **ML-KEM-1024** all use the same stack: [mlkem-native](https://github.com/pq-code-package/mlkem-native) (C) built with **Emscripten**, plus TypeScript adapted from Dmitry Chestnykh’s [mlkem-wasm](https://github.com/dchest/mlkem-wasm), vendored in this repo (no runtime npm dependency on `mlkem-wasm`).
8
+ - **PQClean** and **libsodium** are no longer part of this package’s build or runtime path.
9
+
10
+ ## Security assurance and verification
11
+
12
+ This project relies on upstream `mlkem-native` for arithmetic/security properties.
13
+ The three parameter sets (512/768/1024) use the same implementation family and differ only by compile-time parameter selection.
14
+
15
+ ### Upstream evidence
16
+
17
+ - `mlkem-native` security/formal-verification statements:
18
+ - [README.md](https://github.com/pq-code-package/mlkem-native/blob/main/README.md)
19
+ - [SOUNDNESS.md](https://github.com/pq-code-package/mlkem-native/blob/main/SOUNDNESS.md)
20
+ - [proofs/hol_light/README.md](https://github.com/pq-code-package/mlkem-native/blob/main/proofs/hol_light/README.md)
21
+ - [proofs/cbmc/README.md](https://github.com/pq-code-package/mlkem-native/blob/main/proofs/cbmc/README.md)
22
+ - Arithmetic implementation details in upstream source:
23
+ - Montgomery multiplication path in `mlk_fqmul()`:
24
+ - [mlkem/src/poly.c](https://github.com/pq-code-package/mlkem-native/blob/main/mlkem/src/poly.c)
25
+ - Barrett reduction path in `mlk_barrett_reduce()`:
26
+ - [mlkem/src/poly.c](https://github.com/pq-code-package/mlkem-native/blob/main/mlkem/src/poly.c)
27
+ - Generic Montgomery reduction helper:
28
+ - [mlkem/src/poly.h](https://github.com/pq-code-package/mlkem-native/blob/main/mlkem/src/poly.h)
29
+
30
+ ### What this means for 512/768/1024
31
+
32
+ - Constant-time claims and proofs are provided upstream by `mlkem-native` (see links above).
33
+ - This package builds the same source for all three variants by changing only `MLK_CONFIG_PARAMETER_SET` in `wasm/Makefile`.
34
+ - Variant sizes/parameters are defined upstream in `mlkem/mlkem_native.h`.
35
+
36
+ ### How users can independently verify
37
+
38
+ From the repository root:
39
+
40
+ ```bash
41
+ # 1) Confirm the three variant builds only change parameter set.
42
+ rg "MLK_CONFIG_PARAMETER_SET=512|MLK_CONFIG_PARAMETER_SET=768|MLK_CONFIG_PARAMETER_SET=1024" wasm/Makefile
43
+
44
+ # 2) Confirm Montgomery and Barrett reduction functions exist in upstream source.
45
+ rg "mlk_fqmul|Montgomery multiplication|mlk_barrett_reduce|Barrett reduction" vendor/mlkem-native/mlkem/src/poly.c
46
+ rg "mlk_montgomery_reduce" vendor/mlkem-native/mlkem/src/poly.h
47
+
48
+ # 3) Confirm upstream constant-time/security documentation is present.
49
+ rg "constant-time|secret-dependent|HOL-Light|CBMC" vendor/mlkem-native/README.md vendor/mlkem-native/SOUNDNESS.md
50
+
51
+ # 4) (Optional) Rebuild the vendored wasm/modules from source.
52
+ pnpm build:vendor
53
+ ```
54
+
55
+ Notes:
56
+ - The upstream project documents scope/assumptions in `SOUNDNESS.md`; review this when making compliance assertions.
57
+ - This package uses ML-KEM-1024 (not "1028").
58
+
59
+ ## Credits
60
+
61
+ - Core approach adapted from Dmitry Chestnykh's `mlkem-wasm`:
62
+ - https://github.com/dchest/mlkem-wasm
62
63
 
63
64
  ## Installation
64
65
 
65
- For Node.js, you can install quantum-resistant-rustykey via pnpm, npm or yarn:
66
+ Install via pnpm, npm or yarn:
66
67
 
67
68
  ```bash
68
69
  pnpm install quantum-resistant-rustykey
@@ -74,7 +75,7 @@ yarn add quantum-resistant-rustykey
74
75
 
75
76
  ## Usage
76
77
 
77
- ### Node.js Environment
78
+ ### Node.js example
78
79
 
79
80
  ```typescript
80
81
  import { loadMlKem1024, loadMlKem768, loadMlKem512 } from "quantum-resistant-rustykey";
@@ -93,13 +94,13 @@ async function main() {
93
94
 
94
95
  // Encrypt a message
95
96
  const message = "Hello, this is a secret message!";
96
- var encrypt = mlkem.encrypt(keypair.get('public_key'))
97
+ const encrypt = mlkem.encrypt(keypair.get('public_key'))
97
98
  const sharedSecret = encrypt.get('secret')
98
99
  const encryptedMessage = await mlkem.encryptMessage(message, sharedSecret)
99
100
  console.log("Encrypted message: ", encryptedMessage)
100
101
 
101
102
  // Decrypt the message
102
- var decryptedSharedSecret = mlkem.decrypt(encrypt.get('cyphertext'), keypair.get('private_key'))
103
+ const decryptedSharedSecret = mlkem.decrypt(encrypt.get('cyphertext'), keypair.get('private_key'))
103
104
  const decryptedMessage = await mlkem.decryptMessage(encryptedMessage, decryptedSharedSecret)
104
105
  console.log("Decrypted message: ", decryptedMessage)
105
106
  } catch (error) {
@@ -110,39 +111,45 @@ async function main() {
110
111
  main();
111
112
  ```
112
113
 
113
- ### Security Considerations for Web Usage
114
+ ### Frontend example (Vite / browser)
114
115
 
115
- When using ML-KEM in a web environment, consider the following security best practices:
116
+ ```typescript
117
+ import { loadMlKem768 } from "quantum-resistant-rustykey";
116
118
 
117
- 1. **Key Storage**:
118
- - Never store private keys in localStorage or sessionStorage
119
- - Use secure storage mechanisms like IndexedDB with encryption
120
- - Consider using the Web Crypto API for additional security
119
+ const output = document.querySelector("#output");
121
120
 
122
- 2. **Key Management**:
123
- - Generate new key pairs for each session when possible
124
- - Implement proper key rotation policies
125
- - Consider using a key management service for production applications
121
+ async function run() {
122
+ const kem = await loadMlKem768();
123
+ const kp = kem.keypair();
126
124
 
127
- 3. **Data Handling**:
128
- - Always encrypt sensitive data before transmission
129
- - Use HTTPS for all communications
130
- - Implement proper error handling to prevent information leakage
125
+ const enc = kem.encrypt(kp.get("public_key"));
126
+ const sharedSecretA = await enc.get("secret");
127
+ const sharedSecretB = await kem.decrypt(enc.get("cyphertext"), kp.get("private_key"));
131
128
 
132
- 4. **Performance**:
133
- - Consider using Web Workers for cryptographic operations
134
- - Implement proper loading states for long-running operations
135
- - Cache public keys when appropriate
129
+ const encrypted = await kem.encryptMessage("hello from browser", sharedSecretA);
130
+ const decrypted = await kem.decryptMessage(encrypted, sharedSecretB);
131
+
132
+ output.textContent = decrypted;
133
+ }
134
+
135
+ run().catch((err) => {
136
+ console.error(err);
137
+ output.textContent = "failed";
138
+ });
139
+ ```
140
+
141
+ Security note for web apps:
142
+ - never store private keys in `localStorage`/`sessionStorage`
143
+ - prefer HTTPS + short-lived keys
144
+ - use secure key storage strategy (e.g. IndexedDB + app-level protections)
136
145
 
137
146
  ## Building from Source
138
147
 
139
148
  ### Prerequisites
140
149
 
141
- - Node.js >= 24.1.0 (optimal)
142
- - Node.js >= 22 (current LTS)
143
- - pnpm (pnpm for faster cache, but npm also works fine)
144
- - Emscripten
145
- - CMake
150
+ - Node.js >= 22 (LTS)
151
+ - pnpm (or npm)
152
+ - Emscripten **or** Docker only needed if you run `pnpm build:vendor` to regenerate `src/vendor/mlkem*.js`
146
153
 
147
154
  ### Build Instructions
148
155
 
@@ -152,72 +159,55 @@ git clone https://github.com/antonymott/quantum-resistant-rustykey.git
152
159
  cd quantum-resistant-rustykey
153
160
  ```
154
161
 
155
- 2. Initialize submodules:
162
+ 2. Install dependencies:
156
163
  ```bash
157
- git submodule update --init --recursive
164
+ pnpm i
158
165
  ```
159
166
 
160
- 3. Install dependencies:
167
+ 3. (Optional) Clone [mlkem-native](https://github.com/pq-code-package/mlkem-native) if you will regenerate vendored bundles:
161
168
  ```bash
162
- pnpm i
169
+ git clone --depth 1 https://github.com/pq-code-package/mlkem-native.git vendor/mlkem-native
163
170
  ```
164
171
 
165
- 4. Build the WASM engine with Emscripten and CMake
166
-
167
- ### Environment Configuration
168
-
169
- The package supports two different environments:
172
+ 4. (Optional) Rebuild `src/vendor/mlkem*.js` after changing `wasm/` or `mlkem-src/` (requires `emcc` or Docker):
173
+ ```bash
174
+ pnpm build:vendor
175
+ ```
170
176
 
171
- - **Web Environment**: Set `sENVIRONMENT=web,worker` in CMakeLists.txt
172
- - **Node.js Environment**: Set `sENVIRONMENT=node,worker` in CMakeLists.txt
177
+ 5. Compile TypeScript to `dist/`:
173
178
 
174
179
  ```bash
175
- pnpm pre
176
-
177
- # Copy the WASM file to src directory
178
- cp install/kyber_crystals_wasm_engine.wasm ./src/
180
+ pnpm build
179
181
  ```
180
182
 
181
- The `sENVIRONMENT` option specifies which environments the WebAssembly module should be built for:
182
- - `web`: Enables running in web browsers
183
- - `worker`: Enables running in Web Workers
184
- - `node`: Enables running in Node.js
185
183
 
186
- For web applications, use `web,worker` to support both browser and Web Worker environments.
187
- For Node.js applications, use `node,worker` to support both Node.js and Worker Threads.
184
+ ## Testing
185
+
186
+ - Run `pnpm test` for ML-KEM-512 / 768 / 1024 round-trips.
187
+
188
+ ## Browser example (local)
188
189
 
189
- 5. Compile TypeScript files to JavaScript
190
+ A Vite app under `examples/browser-demo` links this package from the workspace. From the repo root:
190
191
 
191
192
  ```bash
192
193
  pnpm build
194
+ pnpm example:browser
193
195
  ```
194
196
 
195
-
196
- ## Testing
197
-
198
- - Tested to work with Node.js v23.6.0
199
- - For web testing, open `install/test.html` in a live server and check the console for encryption/decryption results of the three variants
197
+ See `examples/browser-demo/README.md` for details.
200
198
 
201
199
  ## Project Structure
202
200
 
203
- ```mermaid
204
- stateDiagram-v2
205
- [*] --> install
206
- install --> [*]
207
- install --> kyber_crystals_wasm_engine.js
208
- kyber_crystals_wasm_engine.js --> kyber_crystals_wasm_engine.wasm
209
- kyber_crystals_wasm_engine.wasm --> test.html
210
- test.html --> [*]
211
- ```
201
+ ML-KEM logic comes from **mlkem-native** (C), compiled with **Emscripten** under `wasm/`, wrapped by TypeScript derived from [mlkem-wasm](https://github.com/dchest/mlkem-wasm) in `mlkem-src/`, then bundled into `src/vendor/mlkem*.js`.
212
202
 
213
203
  ## Publishing
214
204
 
215
- The package is published from the `install` folder. To publish a new version:
205
+ The package is published from the npm package root (`dist/`). To publish a new version:
216
206
  1. make a new branch locally from main
217
207
  2. edit and test your changes
218
208
  3. pnpm changeset
219
- 4. build (will run CI/CD tests)
220
- 5. if it works, CI/CD will generate a pull request for admin to approve
209
+ 4. `pnpm lint && pnpm test && pnpm build`
210
+ 5. merge to main; CI publishes when the version changed
221
211
 
222
212
  ## Security Considerations
223
213