qclair-quantshield
v1.0.24
Published
π‘οΈ Post-quantum encryption for web apps. Initialize once, protect ALL requests automatically. Works with React, Vue, Svelte, Vanilla JS. Zero code changes needed - transparent HTTP encryption with ML-KEM + AES-GCM.
Maintainers
Readme
π‘οΈ QuantShield JS SDK
Post-quantum encryption toolkit for web applications with transparent HTTP interception
QuantShield provides end-to-end encryption for web applications using post-quantum cryptography. It transparently intercepts HTTP requests (fetch, XMLHttpRequest, Axios) and encrypts them before sending to a QuantShield proxy server.
οΏ½ Prerequisites
QuantShield Proxy Server Required: This SDK requires a QuantShield proxy server to handle encryption/decryption. The proxy server:
- Deploys alongside your backend API server
- Handles ML-KEM-1024 key exchange
- Decrypts incoming requests and forwards to your API
- Encrypts API responses before returning to client
Note: The proxy server is typically deployed at
https://quantshield-proxy.yourcompany.comor during development athttp://localhost:7000
β¨ Features
- π Post-Quantum Security: ML-KEM-1024 (Module-Lattice-Based Key Encapsulation Mechanism)
- οΏ½ AES-GCM-256 Encryption: Symmetric encryption for request/response data
- οΏ½π Zero-Code Integration: Drop-in replacement for existing HTTP clients
- π Universal Support: Works in browsers (Chrome, Firefox, Safari, Edge)
- β‘ WebAssembly Performance: Go-compiled crypto functions for speed
- π― Domain Filtering: Only encrypts requests to specified domains
- π Automatic Decryption: Seamlessly decrypts responses
- π Session Persistence: Keys survive page navigation (sessionStorage)
- β° Auto-Refresh: Optional automatic key rotation
π Quick Start
Installation
npm install qclair-quantshieldβ οΈ One-Time Setup Required
Add 3 lines to your bundler config:
Vite/React/Vue/Svelte - Add to vite.config.js:
export default {
server: { fs: { allow: ['.', '../node_modules/qclair-quantshield/wasm'] } },
assetsInclude: ['**/*.wasm.gz']
}Next.js - Add to next.config.js:
module.exports = {
webpack: (config) => {
config.experiments = { asyncWebAssembly: true };
return config;
}
}That's it! Restart your dev server.
Usage
import QuantShield from 'qclair-quantshield';
// One-step initialization with automatic protection
await QuantShield.initialize('https://your-quantshield-proxy.com', {
autoProtect: true, // Automatically apply patches (default)
allowedDomains: ['api.example.com', 'secure.api.com']
});
// That's it! All fetch/XHR/Axios requests are now encrypted
const response = await fetch('https://api.example.com/data');
console.log(await response.json()); // Automatically decryptedManual Setup (Advanced)
import QuantShield from 'qclair-quantshield';
// Step 1: Initialize WASM module
await QuantShield.init();
// Step 2: Perform ML-KEM handshake with your QuantShield proxy server
await QuantShield.initializeHandshake('https://your-quantshield-proxy.com');
// Step 3: Apply HTTP patches
const proxyUrl = 'https://your-quantshield-proxy.com/decrypt-and-forward';
const allowedDomains = ['api.example.com'];
QuantShield.applyPatchFetch(proxyUrl, allowedDomains);
QuantShield.applyPatchXHR(proxyUrl, allowedDomains);
// Now make requests as usual
const response = await fetch('https://api.example.com/users');π¦ Module System Support
QuantShield is an ES Module (ESM) package. It works with modern JavaScript build tools.
β ES Modules (Recommended)
import QuantShield from 'qclair-quantshield';
await QuantShield.initialize('https://your-quantshield-proxy.com', {
autoProtect: true,
allowedDomains: ['api.example.com']
});β TypeScript Support
import QuantShield from 'qclair-quantshield';
// Full type definitions included - no @types package needed!
await QuantShield.initialize('https://your-quantshield-proxy.com', {
autoProtect: true,
allowedDomains: ['api.example.com']
});π― Build Tool Compatibility
| Build Tool | Support | Notes | |------------|---------|-------| | Vite | β Full | Zero config needed | | Webpack 5 | β Full | Zero config needed | | Rollup | β Full | Zero config needed | | esbuild | β Full | Zero config needed | | Create React App | β Full | Zero config needed | | Next.js | β Full | Use in client components | | Parcel | β Full | Zero config needed |
Note: This package is browser-only (not for Node.js servers). Use it in frontend applications only.
π Framework Integration
React (Recommended Pattern)
import React, { useEffect, useState } from 'react';
import QuantShield from 'qclair-quantshield';
function App() {
const [isReady, setIsReady] = useState(false);
useEffect(() => {
async function initSecurity() {
try {
await QuantShield.initialize('https://your-quantshield-proxy.com', {
autoProtect: true,
allowedDomains: ['api.example.com']
});
// Optional: Enable automatic key rotation every 10 minutes
QuantShield.enableAutoRefresh(10);
setIsReady(true);
} catch (error) {
console.error('QuantShield initialization failed:', error);
setIsReady(true); // Allow app to load even if encryption fails
}
}
initSecurity();
// Cleanup on unmount
return () => {
QuantShield.disableAutoRefresh();
};
}, []);
if (!isReady) {
return <div>Loading security layer...</div>;
}
return <div>Your App Content</div>;
}Vue.js
import { onMounted } from 'vue';
import QuantShield from 'qclair-quantshield';
export default {
setup() {
onMounted(async () => {
await QuantShield.initialize('https://your-quantshield-proxy.com', {
autoProtect: true,
allowedDomains: ['api.example.com']
});
});
}
};Next.js (Client Component)
'use client'; // Mark as client component
import { useEffect, useState } from 'react';
import QuantShield from 'qclair-quantshield';
export default function RootLayout({ children }) {
const [ready, setReady] = useState(false);
useEffect(() => {
QuantShield.initialize('https://your-quantshield-proxy.com', {
autoProtect: true,
allowedDomains: ['api.example.com']
}).then(() => setReady(true));
}, []);
return <html><body>{children}</body></html>;
}
```javascript
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import QuantShield from 'qclair-quantshield';
async function startApp() {
// Initialize QuantShield before creating Vue app
await QuantShield.init();
await QuantShield.initializeHandshake();
QuantShield.applyPatchFetch();
QuantShield.applyPatchXHR();
const app = createApp(App);
app.mount('#app');
}
startApp();<!-- Any component - requests automatically encrypted -->
<template>
<div>{{ userData }}</div>
</template>
<script>
export default {
async mounted() {
// Automatically encrypted request
const response = await fetch('/api/user/data');
this.userData = await response.json();
}
}
</script>Svelte / SvelteKit
// src/routes/+layout.js
import QuantShield from 'qclair-quantshield';
export async function load() {
// Initialize before any page loads
await QuantShield.init();
await QuantShield.initializeHandshake();
QuantShield.applyPatchFetch();
QuantShield.applyPatchXHR();
return { quantshieldReady: true };
}<!-- Any Svelte component -->
<script>
import { onMount } from 'svelte';
let users = [];
onMount(async () => {
// Automatically encrypted request
const response = await fetch('/api/users');
users = await response.json();
});
</script>
{#each users as user}
<div>{user.name}</div>
{/each}Vanilla JavaScript
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Secure App</title>
</head>
<body>
<div id="app"></div>
<script type="module">
import QuantShield from 'qclair-quantshield';
// Initialize immediately
async function init() {
await QuantShield.init();
await QuantShield.initializeHandshake();
QuantShield.applyPatchFetch();
QuantShield.applyPatchXHR();
console.log('π‘οΈ All requests now encrypted');
// Load your app after QuantShield is ready
loadApp();
}
function loadApp() {
// All these requests are automatically encrypted
fetch('/api/data').then(res => res.json());
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/users');
xhr.send();
}
init();
</script>
</body>
</html>οΏ½οΈ Global Protection Scope
Once initialized, QuantShield automatically protects ALL HTTP traffic in your application:
| Request Type | Automatically Protected | Example |
|--------------|------------------------|---------|
| fetch() | β
Yes | fetch('/api/data') |
| XMLHttpRequest | β
Yes | xhr.open('GET', '/api') |
| Axios | β
Yes | axios.get('/api') |
| jQuery AJAX | β
Yes | $.get('/api') |
| Third-party libraries | β
Yes | Any library using fetch/XHR |
π― Key Benefits
- οΏ½π§ Zero Code Changes: No need to modify existing API calls
- π Global Coverage: Protects requests from ANY component or library
- π¦ Framework Agnostic: Works with React, Vue, Svelte, Vanilla JS
- π Initialize Once: Set up in your main app file and forget about it
- π Transparent Encryption: Developers use normal fetch/XHR syntax
β‘ Third-Party Library Support
QuantShield automatically encrypts requests from popular libraries:
// All of these are automatically encrypted after QuantShield.init()
// Axios
import axios from 'axios';
const response = await axios.get('/api/users'); // β
Encrypted
// jQuery
import $ from 'jquery';
$.get('/api/data', (data) => console.log(data)); // β
Encrypted
// Superagent
import superagent from 'superagent';
const res = await superagent.get('/api/posts'); // β
Encrypted
// Any custom HTTP library using fetch/XHR under the hoodπ§ Configuration
Custom Server and Domains
// Custom QuantShield server
await QuantShield.initializeHandshake('https://your-server.com');
// Specify which domains to encrypt
QuantShield.applyPatchFetch('https://your-proxy.com/decrypt-and-forward');
QuantShield.applyPatchXHR(
'https://your-proxy.com/decrypt-and-forward',
['api.example.com', 'secure.mysite.com'] // Only these domains
);Environment-Based Configuration
// Production vs Development setup
const config = {
production: {
serverUrl: 'https://quantshield-proxy.yourcompany.com',
proxyUrl: 'https://quantshield-proxy.yourcompany.com/decrypt-and-forward',
allowedDomains: ['api.yourcompany.com', 'secure.yourcompany.com']
},
development: {
serverUrl: 'http://localhost:7000', // Local QuantShield proxy during development
proxyUrl: 'http://localhost:7000/decrypt-and-forward',
allowedDomains: ['localhost:3001', 'dev.api.com']
}
};
const env = process.env.NODE_ENV || 'development';
const { serverUrl, proxyUrl, allowedDomains } = config[env];
await QuantShield.initializeHandshake(serverUrl);
QuantShield.applyPatchFetch(proxyUrl);
QuantShield.applyPatchXHR(proxyUrl, allowedDomains);Conditional Initialization
// Only enable in production or when explicitly enabled
async function initQuantShieldIfNeeded() {
if (process.env.NODE_ENV === 'production' || process.env.ENABLE_QUANTSHIELD) {
try {
await QuantShield.init();
await QuantShield.initializeHandshake();
QuantShield.applyPatchFetch();
QuantShield.applyPatchXHR();
console.log('π‘οΈ QuantShield enabled');
return true;
} catch (error) {
console.warn('β οΈ QuantShield failed to initialize:', error);
return false;
}
} else {
console.log('π QuantShield disabled in development');
return false;
}
}Environment Detection
// Works in both browser and Node.js
if (typeof window !== 'undefined') {
// Browser environment
console.log('Running in browser');
} else {
// Node.js environment
console.log('Running in Node.js');
}
await QuantShield.init(); // Works in both environmentsπ API Reference
Core Methods
QuantShield.initialize(serverUrl, options?)
Recommended: All-in-one initialization method.
await QuantShield.initialize(serverUrl: string, options?: {
autoProtect?: boolean; // Auto-apply patches (default: true)
allowedDomains?: string[]; // Domains to intercept (default: [])
}): Promise<boolean>Example:
await QuantShield.initialize('https://your-quantshield-proxy.com', {
autoProtect: true,
allowedDomains: ['api.example.com', 'secure.api.com']
});QuantShield.init()
Initialize the WebAssembly crypto module.
await QuantShield.init(): Promise<boolean>QuantShield.initializeHandshake(serverUrl, forceNew?)
Perform ML-KEM-1024 key exchange with the QuantShield server.
await QuantShield.initializeHandshake(
serverUrl: string,
forceNew?: boolean // Force new handshake even if session exists
): Promise<HandshakeResult>Returns:
{
success: boolean;
uid: string; // Session unique identifier
cached: boolean; // Whether session was restored from cache
}QuantShield.applyPatchFetch(proxyUrl, allowedDomains?)
Patch the global fetch() function for automatic encryption.
QuantShield.applyPatchFetch(
'http://localhost:7000/decrypt-and-forward',
['api.example.com'] // Optional: filter by domain
): voidQuantShield.applyPatchXHR(proxyUrl, allowedDomains?)
Patch XMLHttpRequest (also intercepts Axios requests) for automatic encryption.
QuantShield.applyPatchXHR(
'http://localhost:7000/decrypt-and-forward',
['api.example.com', 'secure.api.com']
): voidKey Rotation Methods
QuantShield.enableAutoRefresh(intervalMinutes?)
New in v1.0.12: Enable automatic key rotation.
QuantShield.enableAutoRefresh(10); // Refresh every 10 minutes (default)Features:
- Automatically performs new handshake at specified interval
- Generates new UID + encryption key
- Non-blocking (doesn't interrupt ongoing requests)
- Prevents concurrent refreshes
QuantShield.disableAutoRefresh()
Disable automatic key rotation.
QuantShield.disableAutoRefresh();Session Management (Internal)
These methods are used internally by the SDK. Most users won't need them.
hasValidSession()
Check if a valid session exists (has UID + encryption key).
clearSession()
Clear current session from sessionStorage.
getUID()
Get current session UID.
getStatus()
Get initialization status object.
π Security Architecture
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β Client App βββββΆβ QuantShield SDK βββββΆβ QuantShield β
β β β (This Package) β β Proxy Server β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β² β
β βΌ
βββββββββββββββ βββββββββββββββββββ
β ML-KEM β β Target API β
β Handshake β β Server β
βββββββββββββββ βββββββββββββββββββ- Handshake: Client and server exchange keys using post-quantum ML-KEM
- Request: Client encrypts HTTP request with AES-GCM using derived key
- Proxy: QuantShield server decrypts and forwards to target API
- Response: Server encrypts API response and sends back to client
- Decryption: Client automatically decrypts response
π― Browser Compatibility
- β Chrome 57+ (WebAssembly support)
- β Firefox 52+ (WebAssembly support)
- β Safari 11+ (WebAssembly support)
- β Edge 16+ (WebAssembly support)
π Package Structure
qclair-quantshield/
βββ src/
β βββ index.js # Main entry point
β βββ QuantShield.js # Core SDK implementation
β βββ wasm_exec.js # Go WASM runtime bridge
β βββ index.d.ts # TypeScript definitions
βββ wasm/
β βββ crypto.wasm.gz # Compressed WASM binary
βββ package.json
βββ README.mdποΈ Production Build Support
β WASM Files Are Handled Automatically
Modern bundlers (Vite, Webpack 5, Rollup) automatically detect and include the WASM file in your production build:
# React/Vite build process:
npm run build
# β
WASM file is automatically:
# 1. Detected in node_modules/qclair-quantshield/wasm/
# 2. Copied to build/dist output
# 3. Loaded at runtime via import.meta.url
# 4. Cached by browser for performanceπ― Build Tool Compatibility
| Build Tool | WASM Support | Configuration | |------------|--------------|---------------| | Vite | β Automatic | None needed | | Webpack 5 | β Automatic | None needed | | Create React App | β Automatic | None needed | | Next.js 13+ | β Automatic | None needed (asyncWebAssembly enabled by default) | | Rollup | β Automatic | None needed |
Deployment Platforms
Works out-of-the-box on all major platforms:
- β Vercel - Zero config
- β Netlify - Zero config
- β Cloudflare Pages - Zero config
- β AWS Amplify - Zero config
- β GitHub Pages - Zero config
π Verify WASM in Production
# After building, check WASM is included:
find build -name "*.wasm*" # Create React App
find dist -name "*.wasm*" # Vite
# Test production build locally:
npx serve -s build # CRA
npm run preview # Viteβ Frequently Asked Questions
Q: Do I need to modify my existing API calls?
A: No! QuantShield works transparently. After initialization, all your existing fetch() and XMLHttpRequest calls are automatically encrypted without any code changes.
Q: Does it work with Axios, jQuery, and other HTTP libraries?
A: Yes! QuantShield patches the underlying fetch and XMLHttpRequest APIs, so any library that uses these (including Axios, jQuery, Superagent, etc.) is automatically protected.
Q: Where should I initialize QuantShield in my app?
A: Initialize once in your main app file:
- React:
App.jsor_app.js(Next.js) - Vue:
main.js - Svelte:
+layout.jsorapp.html - Vanilla JS:
index.htmlor main entry file
Q: Will it slow down my application?
A: Minimal impact. The WebAssembly crypto functions are highly optimized. The main overhead is the initial handshake (happens once) and AES-GCM encryption (very fast).
Q: Does it work with SSR (Server-Side Rendering)?
A: Yes for client-side requests. QuantShield initializes on the client side and protects browser-initiated requests. Server-side requests during SSR are not affected.
Q: Can I use it with React Native?
A: Yes! There's a separate package for React Native. Use qclair-quantshield-react-native-android for React Native apps.
Q: Does it work with CommonJS projects?
A: No. This package is ESM-only. Modern projects (React, Vue, Next.js, Vite) all support ESM by default. If you're on an older setup, consider migrating to ESM or using the CDN version.
Q: What Node.js version is required?
A: Node.js 16+ is required for WebAssembly and ES modules support. Most modern projects already use Node 16+.
Q: Does it work with older bundlers like Webpack 4?
A: For older bundlers, use dynamic imports. Modern bundlers (Webpack 5, Vite, Rollup, esbuild) have full support.
Q: What happens if QuantShield fails to initialize?
A: Your app continues to work normally with unencrypted HTTP requests. Always wrap initialization in try/catch blocks for production apps.
οΏ½ React Native Support
This package is for web browsers only. For React Native apps, use the dedicated package:
npm install qclair-quantshield-react-native-androidWhy separate packages?
- React Native doesn't support WebAssembly like browsers do
- Different networking APIs (no
XMLHttpRequestorfetchin the same way) - Native bridge required for ML-KEM crypto operations
β οΈ Important Notes
- Initialize Early: Call
QuantShield.init()before making any HTTP requests - Initialize Once: Multiple initializations can cause conflicts
- Global Effect: Once initialized, ALL requests in your app are protected
- Async Nature: Always
awaitthe initialization functions - Error Handling: Wrap initialization in try/catch for production apps
- Domain Filtering: Only requests to specified domains are encrypted (configurable)
π Troubleshooting
Error: "WebAssembly.instantiate(): expected magic word 00 61 73 6d, found 3c 21 64 6f"
What it means: The WASM file is returning HTML (a 404 error page) instead of the actual WebAssembly binary.
Common causes:
- Bundler not configured to serve files from
node_modules - WASM file not being copied to build output
- Incorrect path resolution
Quick fixes by bundler:
Vite (Most Common)
Add to your vite.config.ts or vite.config.js:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
// Allow serving files from node_modules
server: {
fs: {
allow: ['.', '../node_modules/qclair-quantshield/wasm']
}
},
// Treat WASM files as assets
assetsInclude: ['**/*.wasm', '**/*.wasm.gz'],
// Don't pre-bundle QuantShield
optimizeDeps: {
exclude: ['qclair-quantshield']
}
})Webpack 5
Add to your webpack.config.js:
module.exports = {
experiments: {
asyncWebAssembly: true,
topLevelAwait: true
},
module: {
rules: [
{
test: /\.wasm$/,
type: 'asset/resource'
}
]
}
}Create React App (CRA)
Install react-app-rewired:
npm install --save-dev react-app-rewiredCreate config-overrides.js:
module.exports = function override(config) {
config.experiments = {
asyncWebAssembly: true,
topLevelAwait: true
};
return config;
};Update package.json:
{
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build"
}
}Next.js
Add to next.config.js:
module.exports = {
webpack: (config) => {
config.experiments = {
asyncWebAssembly: true,
layers: true
};
return config;
}
}Error: "Failed to fetch" or Network Error
Cause: CORS issues or incorrect server URL
Fix:
- Ensure your QuantShield proxy server is running
- Check the server URL in
initialize()is correct - For local development, use
http://localhost:7000(not127.0.0.1) - Check browser console for detailed error messages
WASM File Not Found in Production Build
Symptoms: Works in development but fails in production
Fix: Verify WASM file is in build output:
# For Vite
ls -la dist/assets/*.wasm*
# For CRA
ls -la build/static/**/*.wasm*If missing, ensure assetsInclude is configured in your bundler.
Initialization Takes Too Long
Cause: Large WASM file or slow network
Fix:
- The WASM file is already gzipped (~800KB)
- Enable HTTP/2 on your server for faster loading
- Consider preloading the WASM file:
// Preload WASM before user interaction
const preloadLink = document.createElement('link');
preloadLink.rel = 'preload';
preloadLink.href = '/path/to/crypto.wasm.gz';
preloadLink.as = 'fetch';
preloadLink.crossOrigin = 'anonymous';
document.head.appendChild(preloadLink);"Go is not defined" Error
Cause: wasm_exec.js not loaded
Fix: This should be automatic. If you see this error:
- Check that
src/wasm_exec.jsexists in the package - Ensure you're importing from
qclair-quantshield(not a custom path) - Clear your bundler cache:
rm -rf node_modules/.viteorrm -rf node_modules/.cache
Need More Help?
Diagnostic Tool: Use our diagnostic script to identify the issue:
import QuantShield from 'qclair-quantshield';
// Add detailed logging
console.log('Starting QuantShield initialization...');
try {
await QuantShield.initialize('https://your-server.com', {
autoProtect: true,
allowedDomains: ['api.example.com']
});
console.log('β
QuantShield initialized successfully');
} catch (error) {
console.error('β QuantShield initialization failed:', error);
console.error('Error details:', {
message: error.message,
stack: error.stack
});
}Get Support:
- Check the WASM-FIX-GUIDE.md for detailed solutions
- Open an issue on GitHub with:
- Your bundler name and version
- Full error message
- Your config file
- Output of
npm list qclair-quantshield
π€ Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
π License
MIT License - see LICENSE file for details.
π Links
Made with β€οΈ by Qclair
