-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsigner.html
More file actions
65 lines (62 loc) · 3.37 KB
/
signer.html
File metadata and controls
65 lines (62 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<!doctype html><html lang="en"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Signer — ProofLens</title>
<link rel="icon" href="/assets/favicon.svg">
<link rel="stylesheet" href="/assets/styles.css">
</head><body>
<header class="header"><div class="container nav">
<a class="brand" href="/"><svg viewBox="0 0 96 96"><rect width="96" height="96" rx="18" fill="#0f1426"/><circle cx="48" cy="48" r="20" fill="#6ea8ff" opacity=".25"/></svg><strong>ProofLens</strong></a>
<nav class="menu"><a href="/demo-embed.html">Demo</a><a href="/embed.html">Embed</a><a href="/signer.html">Signer</a><a href="/showcase.html">Showcase</a><a href="/pricing.html">Pricing</a></nav>
</div></header>
<main class="container">
<div class="panel">
<h1 class="title">Client-side signer</h1>
<p class="lead">Create a detached manifest (<code>.manifest.json</code>) for an image in your browser. No upload leaves your device.</p>
<label>Choose an image</label>
<input id="file" type="file" accept="image/*">
<label>Creator</label>
<input id="creator" placeholder="Moiz / DePaul Student Media" style="width:100%">
<div class="spaced"><button class="btn" id="go">Create manifest</button></div>
<div id="result" style="display:none">
<h3>Manifest</h3>
<pre id="json"></pre>
<div class="spaced"><button class="btn" id="dl">Download manifest</button></div>
<h3>Embed snippet</h3>
<pre id="snippet"></pre>
</div>
</div>
</main>
<footer class="footer"><div class="container footer-inner"><div>© ProofLens</div></div></footer>
<script>
async function sha256Hex(buf){ const h=await crypto.subtle.digest("SHA-256",buf); return Array.from(new Uint8Array(h)).map(b=>b.toString(16).padStart(2,"0")).join(""); }
function nowIso(){ return new Date().toISOString(); }
document.getElementById('go').onclick = async ()=>{
const fi=document.getElementById('file').files[0];
const creator=(document.getElementById('creator').value||"unknown").trim();
if(!fi){ alert("Choose an image first."); return; }
const buf=await fi.arrayBuffer();
const hash=await sha256Hex(buf);
const man={
manifest_version:"demo-1",
created_at:nowIso(),
tool:"prooflens-client-signer v0",
creator,
source_file:fi.name,
source_sha256:hash,
asset:{filename:fi.name,mime:fi.type||"application/octet-stream",bytes:fi.size,sha256:hash},
signing:{type:"demo-self-signed",key_id:"browser",note:"Demo manifest (no cryptographic cert)"},
edits:[]
};
const jsonStr=JSON.stringify(man,null,2);
document.getElementById('json').textContent=jsonStr;
document.getElementById('result').style.display="block";
const blob=new Blob([jsonStr],{type:"application/json"});
const url=URL.createObjectURL(blob); const dl=document.getElementById('dl');
dl.onclick=()=>{ const a=document.createElement('a'); a.href=url; a.download=fi.name+".manifest.json"; a.click(); setTimeout(()=>URL.revokeObjectURL(url),800); };
const snippet=`<script src="https://prooflens.netlify.app/assets/prooflens-verify.min.js?v=1"><\/script>
<img src="/path/${fi.name}" data-manifest-url="/path/${fi.name}.manifest.json" alt="">`;
document.getElementById('snippet').textContent=snippet;
};
</script>
<script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "0e6b1abf18e948e2a934cf8b67476294"}'></script>
</body></html>