Kyber Chat WEB v1
Kyber Chat WEB v1
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>PQC Notary Web v1.0</title>
<script src="https://cdn.jsdelivr.net/npm/@pq-crystals/dilithium@0.2.0/dist/dilithium.js"></script>
<script src="https://cdn.jsdelivr.net/npm/crypto-js@4.1.1/crypto-js.js"></script>
<style>
body { font-family: system-ui; max-width: 600px; margin: 2rem auto; padding: 1rem; background: #f9f9fb; }
h1 { text-align: center; }
.box { border: 2px dashed #ccc; padding: 2rem; text-align: center; margin: 1rem 0; border-radius: 8px; }
.box.dragover { border-color: #007acc; background: #e6f7ff; }
button { background: #007acc; color: white; border: none; padding: 0.8rem 1.2rem; margin: 0.5rem; border-radius: 6px; cursor: pointer; }
pre { background: #f0f0f0; padding: 1rem; border-radius: 6px; overflow-x: auto; }
.status { margin-top: 1rem; font-weight: bold; }
</style>
</head>
<body>
<h1>PQC Notary Web v1.0</h1>
<p>Drag a file to sign with Dilithium-2 (quantum-safe)</p>
<div class="box" id="drop-zone">Drop file here</div>
<button onclick="signFile()">Sign File</button>
<div id="result"></div>
<script>
let fileToSign;
const dropZone = document.getElementById('drop-zone');
['dragover', 'dragenter'].forEach(e => dropZone.addEventListener(e, ev => { ev.preventDefault(); dropZone.classList.add('dragover'); }));
['dragleave', 'drop'].forEach(e => dropZone.addEventListener(e, ev => { ev.preventDefault(); dropZone.classList.remove('dragover'); }));
dropZone.addEventListener('drop', e => {
fileToSign = e.dataTransfer.files[0];
dropZone.innerText = `File: ${fileToSign.name}`;
});
async function hashFile(file) {
const buffer = await file.arrayBuffer();
const hash = CryptoJS.SHA256(CryptoJS.lib.WordArray.create(buffer));
return hash.toString();
}
async function signFile() {
if (!fileToSign) return alert("Drop a file first");
const result = document.getElementById('result');
result.innerHTML = "Signing...";
const data = await fileToSign.arrayBuffer();
const fileHash = await hashFile(fileToSign);
const timestamp = new Date().toISOString();
const kp = await dilithium.keyPair();
const message = `${fileHash}|${timestamp}`;
const sig = await dilithium.sign(new TextEncoder().encode(message), kp.privateKey);
const proof = {
signature: Array.from(new Uint8Array(sig)).map(b => b.toString(16).padStart(2, '0')).join(''),
public_key: Array.from(new Uint8Array(kp.publicKey)).map(b => b.toString(16).padStart(2, '0')).join(''),
file_hash: fileHash,
timestamp,
filename: fileToSign.name
};
const blob = new Blob([JSON.stringify(proof, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = fileToSign.name + '.sig.json';
a.click();
result.innerHTML = `<pre>${JSON.stringify(proof, null, 2)}</pre><p>Saved: <b>${fileToSign.name}.sig.json</b></p>`;
}
</script>
</body>
</html>
```
---
**FINAL_Web_v1.0.html**
- Open in **any browser**
- Drag file → **Sign File** → downloads `.sig.json`
- Done.
---
**Verify later (any browser):**
```html
<!-- Paste proof + original file into verifier (use standalone verifier or add verify tab) -->
```
---
**Next?**
Say: **Make PWA**
→ I’ll give you **FINAL_PWA_v1.0** (installable)
**Go.**