quantum-resistant-rustykey 0.0.2

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 ADDED
@@ -0,0 +1,265 @@
1
+ **Note**: 🚧 WORK IN PROGRESS...do not install 🚧
2
+
3
+ # Quantum-Resistant RustyKey
4
+
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
+
15
+ A WASM implementation 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)
16
+
17
+ | Package | Registry | Description |
18
+ |---------|----------|-------------|
19
+ | quantum-resistant-rustykey | [![npm](https://img.shields.io/npm/v/quantum-resistant-rustykey)](https://www.npmjs.com/package/quantum-resistant-rustykey) | 🚧 WORK IN PROGRESS 🚧 |
20
+
21
+ ## Installation
22
+
23
+ For Node.js, you can install quantum-resistant-rustykey via pnpm, npm or yarn:
24
+
25
+ ```bash
26
+ pnpm install quantum-resistant-rustykey
27
+ # or
28
+ npm install quantum-resistant-rustykey
29
+ # or
30
+ yarn add quantum-resistant-rustykey
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ### Node.js Environment
36
+
37
+ ```typescript
38
+ import { loadMlKem1024, loadMlKem768, loadMlKem512 } from "quantum-resistant-rustykey";
39
+
40
+ async function main() {
41
+ try {
42
+ // Load the desired ML-KEM variant
43
+ const mlkem = await loadMlKem1024(); // Options: loadMlKem1024, loadMlKem768, loadMlKem512
44
+
45
+ // Generate key pair
46
+ const keypair = mlkem.keypair();
47
+ const publicKey = mlkem.buffer_to_string(keypair.get('public_key'));
48
+ const privateKey = mlkem.buffer_to_string(keypair.get('private_key'));
49
+ console.log("Public Key:", publicKey);
50
+ console.log("Private Key:", privateKey);
51
+
52
+ // Encrypt a message
53
+ const message = "Hello, quantum-resistant world!";
54
+ const encrypt = mlkem.encrypt(keypair.get('public_key'));
55
+ const ciphertext = mlkem.buffer_to_string(encrypt.get('cyphertext'));
56
+ const secret = mlkem.buffer_to_string(encrypt.get('secret'));
57
+ console.log("Ciphertext:", ciphertext);
58
+ console.log("Secret:", secret);
59
+
60
+ // Decrypt the message
61
+ const decrypted = mlkem.decrypt(encrypt.get('cyphertext'), keypair.get('private_key'));
62
+ console.log("Decrypted:", mlkem.buffer_to_string(decrypted));
63
+ } catch (error) {
64
+ console.error("Error:", error);
65
+ }
66
+ }
67
+
68
+ main();
69
+ ```
70
+
71
+ ### Web Environment
72
+
73
+ ```typescript
74
+ import { loadMlKem1024, loadMlKem768, loadMlKem512 } from 'quantum-resistant-rustykey';
75
+
76
+ // Example usage in a web application
77
+ async function handleEncryption() {
78
+ try {
79
+ // Load the desired ML-KEM variant
80
+ const mlkem = await loadMlKem1024(); // Options: loadMlKem1024, loadMlKem768, loadMlKem512
81
+
82
+ // Generate key pair
83
+ const keypair = mlkem.keypair();
84
+ const publicKey = mlkem.buffer_to_string(keypair.get('public_key'));
85
+ const privateKey = mlkem.buffer_to_string(keypair.get('private_key'));
86
+
87
+ // Store keys securely (e.g., in IndexedDB or secure storage)
88
+ await storeKeys(publicKey, privateKey);
89
+
90
+ // Encrypt user data
91
+ const userData = {
92
+ username: "user123",
93
+ email: "user@example.com"
94
+ };
95
+
96
+ const encrypt = mlkem.encrypt(keypair.get('public_key'));
97
+ const ciphertext = mlkem.buffer_to_string(encrypt.get('cyphertext'));
98
+ const secret = mlkem.buffer_to_string(encrypt.get('secret'));
99
+
100
+ // Send encrypted data to server
101
+ await sendToServer(ciphertext, secret);
102
+ } catch (error) {
103
+ console.error("Encryption error:", error);
104
+ }
105
+ }
106
+
107
+ // Example secure storage implementation
108
+ async function storeKeys(publicKey: string, privateKey: string) {
109
+ // Implement secure storage (e.g., IndexedDB, Web Crypto API)
110
+ // This is just a placeholder - implement proper secure storage
111
+ localStorage.setItem('mlkem_publicKey', publicKey);
112
+ localStorage.setItem('mlkem_privateKey', privateKey);
113
+ }
114
+
115
+ // Example server communication
116
+ async function sendToServer(ciphertext: string, secret: string) {
117
+ // Implement server communication
118
+ // This is just a placeholder - implement proper API calls
119
+ const response = await fetch('/api/secure-data', {
120
+ method: 'POST',
121
+ headers: {
122
+ 'Content-Type': 'application/json',
123
+ },
124
+ body: JSON.stringify({ ciphertext, secret }),
125
+ });
126
+ return response.json();
127
+ }
128
+
129
+ // Initialize the application
130
+ document.addEventListener('DOMContentLoaded', () => {
131
+ const encryptButton = document.getElementById('encrypt-button');
132
+ if (encryptButton) {
133
+ encryptButton.addEventListener('click', handleEncryption);
134
+ }
135
+ });
136
+ ```
137
+
138
+ ### Security Considerations for Web Usage
139
+
140
+ When using ML-KEM in a web environment, consider the following security best practices:
141
+
142
+ 1. **Key Storage**:
143
+ - Never store private keys in localStorage or sessionStorage
144
+ - Use secure storage mechanisms like IndexedDB with encryption
145
+ - Consider using the Web Crypto API for additional security
146
+
147
+ 2. **Key Management**:
148
+ - Generate new key pairs for each session when possible
149
+ - Implement proper key rotation policies
150
+ - Consider using a key management service for production applications
151
+
152
+ 3. **Data Handling**:
153
+ - Always encrypt sensitive data before transmission
154
+ - Use HTTPS for all communications
155
+ - Implement proper error handling to prevent information leakage
156
+
157
+ 4. **Performance**:
158
+ - Consider using Web Workers for cryptographic operations
159
+ - Implement proper loading states for long-running operations
160
+ - Cache public keys when appropriate
161
+
162
+ ## Building from Source
163
+
164
+ ### Prerequisites
165
+
166
+ - Node.js >= 23.6.0 (optimal)
167
+ - Node.js >= 22 (current LTS)
168
+ - pnpm (pnpm for faster cache, but npm also works fine)
169
+ - Emscripten
170
+ - CMake
171
+
172
+ ### Build Instructions
173
+
174
+ 1. Clone the repository:
175
+ ```bash
176
+ git clone https://github.com/antonymott/quantum-resistant-rustykey.git
177
+ cd quantum-resistant-rustykey
178
+ ```
179
+
180
+ 2. Initialize submodules:
181
+ ```bash
182
+ git submodule update --init --recursive
183
+ ```
184
+
185
+ 3. Install dependencies:
186
+ ```bash
187
+ pnpm i
188
+ ```
189
+
190
+ 4. Build the WASM engine with Emscripten and CMake
191
+
192
+ ### Environment Configuration
193
+
194
+ The package supports two different environments:
195
+
196
+ - **Web Environment**: Set `sENVIRONMENT=web,worker` in CMakeLists.txt
197
+ - **Node.js Environment**: Set `sENVIRONMENT=node,worker` in CMakeLists.txt
198
+
199
+ ```bash
200
+ pnpm pre
201
+
202
+ # Copy the WASM file to src directory
203
+ cp install/kyber_crystals_wasm_engine.wasm ./src/
204
+ ```
205
+
206
+ The `sENVIRONMENT` option specifies which environments the WebAssembly module should be built for:
207
+ - `web`: Enables running in web browsers
208
+ - `worker`: Enables running in Web Workers
209
+ - `node`: Enables running in Node.js
210
+
211
+ For web applications, use `web,worker` to support both browser and Web Worker environments.
212
+ For Node.js applications, use `node,worker` to support both Node.js and Worker Threads.
213
+
214
+ 5. Compile TypeScript files to JavaScript
215
+
216
+ ```bash
217
+ pnpm build
218
+ ```
219
+
220
+
221
+ ## Testing
222
+
223
+ - Tested to work with Node.js v23.6.0
224
+ - For web testing, open `install/test.html` in a live server and check the console for encryption/decryption results of the three variants
225
+
226
+ ## Project Structure
227
+
228
+ ```mermaid
229
+ stateDiagram-v2
230
+ [*] --> install
231
+ install --> [*]
232
+ install --> kyber_crystals_wasm_engine.js
233
+ kyber_crystals_wasm_engine.js --> kyber_crystals_wasm_engine.wasm
234
+ kyber_crystals_wasm_engine.wasm --> test.html
235
+ test.html --> [*]
236
+ ```
237
+
238
+ ## Publishing
239
+
240
+ The package is published from the `install` folder. To publish a new version:
241
+ 1. make a new branch locally from main
242
+ 2. edit and test your changes
243
+ 3. pnpm changeset
244
+ 4. build (will run CI/CD tests)
245
+ 5. if it works, CI/CD will generate a pull request for admin to approve
246
+
247
+ ## Security Considerations
248
+
249
+ This implementation includes patches to withstand side-channel attacks. For more information about the security improvements, see: [RaspberryPi recovers secret keys from NIST winner implementation...within minutes](https://kannwischer.eu/papers/2024_kyberslash_preprint20240628.pdf)
250
+
251
+ ## Contributing
252
+
253
+ - Please make pull requests tested to work on Bun and previous Node.js versions
254
+ - Follow the existing code style and testing practices
255
+ - Include tests for new features
256
+ - Update documentation as needed
257
+
258
+ ## License
259
+
260
+ ISC
261
+
262
+ ## Acknowledgments
263
+
264
+ - Based on the NIST post-quantum cryptography project
265
+ - Inspired by the implementation approach of [sqlite-wasm](https://github.com/sqlite/sqlite-wasm)
@@ -0,0 +1,19 @@
1
+ interface KeyPair {
2
+ get(key: 'public_key' | 'private_key'): any;
3
+ }
4
+ interface EncryptResult {
5
+ get(key: 'cyphertext' | 'secret'): any;
6
+ }
7
+ interface IMlKem {
8
+ keypair(): KeyPair;
9
+ encrypt(public_key: any): EncryptResult;
10
+ decrypt(cyphertext: any, private_key: any): any;
11
+ buffer_to_string(buffer: any): string;
12
+ delete(): void;
13
+ }
14
+
15
+ declare function loadMlKem1024(): Promise<IMlKem>;
16
+ declare function loadMlKem768(): Promise<IMlKem>;
17
+ declare function loadMlKem512(): Promise<IMlKem>;
18
+
19
+ export { loadMlKem1024, loadMlKem512, loadMlKem768 };