Dilithium CodeSign PWA v1
Dilithium CodeSign PWA v1
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Dilithium Code-Sign PWA v1.0</title>
<link rel="manifest" href="manifest.json">
<link rel="icon" href="icon-192.png">
<meta name="theme-color" content="#007acc">
<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; }
button { background: #007acc; color: white; border: none; padding: 0.8rem 1.2rem; margin: 0.5rem; border-radius: 6px; cursor: pointer; }
input { padding: 0.5rem; margin: 0.5rem; width: 100%; }
.status { margin-top: 1rem; font-weight: bold; }
</style>
</head>
<body>
<h1>Dilithium Code-Sign PWA v1.0</h1>
<p>Sign & verify git commits — offline</p>
<button onclick="initRepo()">Init Repo</button>
<button onclick="signCommit()">Sign Current Commit</button>
<input type="text" id="commit-sha" placeholder="Commit SHA" />
<button onclick="verifyCommit()">Verify Commit</button>
<button onclick="verifyChain()">Verify Chain</button>
<div class="status" id="status"></div>
<script>
let pk, sk;
const SIG_DIR = 'dilithium-sigs';
let deferredPrompt;
async function sha3_256(data) {
const buffer = await crypto.subtle.digest('SHA-256', data);
return Array.from(new Uint8Array(buffer)).map(b => b.toString(16).padStart(2, '0')).join('');
}
async function initRepo() {
const kp = await dilithium.keyPair();
pk = kp.publicKey;
sk = kp.privateKey;
const pkHex = Array.from(pk).map(b => b.toString(16).padStart(2, '0')).join('');
localStorage.setItem('dilithium_pk', pkHex);
setStatus("Initialized", "green");
}
async function signCommit() {
if (!sk) return setStatus("Init repo first", "red");
const commitData = prompt("Paste commit data (tree+parents+msg):");
if (!commitData) return;
const hash = await sha3_256(new TextEncoder().encode(commitData));
const sig = await dilithium.sign(hash, sk);
const sigHex = Array.from(sig).map(b => b.toString(16).padStart(2, '0')).join('');
const commitId = prompt("Commit SHA:");
const sigObj = { commit_id: commitId, signature: sigHex, public_key: localStorage.getItem('dilithium_pk'), timestamp: new Date().toISOString() };
localStorage.setItem(`${SIG_DIR}/${commitId}`, JSON.stringify(sigObj));
setStatus("Signed", "green");
}
async function verifyCommit() {
const sha = document.getElementById('commit-sha').value;
if (!sha) return setStatus("Enter SHA", "red");
const sigJson = localStorage.getItem(`${SIG_DIR}/${sha}`);
if (!sigJson) return setStatus("No sig", "red");
const sigObj = JSON.parse(sigJson);
const commitData = prompt("Paste same commit data:");
const hash = await sha3_256(new TextEncoder().encode(commitData));
const sig = hexToBytes(sigObj.signature);
const pk = hexToBytes(sigObj.public_key);
const valid = await dilithium.verify(hash, sig, pk);
setStatus(valid ? "Verified" : "Failed", valid ? "green" : "red");
}
async function verifyChain() {
setStatus("Chain verify not supported in browser", "red");
}
function hexToBytes(hex) {
return Uint8Array.from(hex.match(/.{1,2}/g).map(b => parseInt(b, 16)));
}
function setStatus(msg, color) {
const el = document.getElementById('status');
el.textContent = msg;
el.style.color = color;
}
// PWA Install
window.addEventListener('beforeinstallprompt', e => {
e.preventDefault();
deferredPrompt = e;
const installBtn = document.createElement('button');
installBtn.textContent = 'Install App';
installBtn.style.position = 'fixed';
installBtn.style.bottom = '20px';
installBtn.style.right = '20px';
installBtn.style.zIndex = '1000';
installBtn.onclick = () => {
deferredPrompt.prompt();
deferredPrompt.userChoice.then(() => installBtn.remove());
};
document.body.appendChild(installBtn);
});
// Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js');
}
</script>
</body>
</html>
```
```json
// manifest.json
{
"name": "Dilithium Code-Sign PWA",
"short_name": "Code-Sign",
"start_url": "/",
"display": "standalone",
"background_color": "#f9f9fb",
"theme_color": "#007acc",
"icons": [
{
"src": "icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
```
```js
// sw.js
const CACHE = 'dilithium-codesign-pwa-v1';
const FILES = ['/', 'index.html', 'manifest.json', 'icon-192.png', 'icon-512.png'];
self.addEventListener('install', e => {
e.waitUntil(caches.open(CACHE).then(cache => cache.addAll(FILES)));
});
self.addEventListener('fetch', e => {
e.respondWith(caches.match(e.request).then(resp => resp || fetch(e.request)));
});
```
---
**FINAL_PWA_v1.0**
- Open in Chrome → **Install App**
- Works **offline**
- Full sign/verify (chain not supported)
---
**Next?**
Say: **Make TPM**
→ I’ll give you **FINAL_TPM_v1.0_core**
**Go.**