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 +265 -0
- package/install/index.d.ts +19 -0
- package/install/index.js +1836 -0
- package/install/index.js.map +1 -0
- package/package.json +42 -0
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 | [](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 };
|