diff --git a/content/posts/2021-08-17-serving-blog-content-over-dns.md b/content/posts/2021-08-17-serving-blog-content-over-dns.md index f8262c6..7076f99 100644 --- a/content/posts/2021-08-17-serving-blog-content-over-dns.md +++ b/content/posts/2021-08-17-serving-blog-content-over-dns.md @@ -73,7 +73,7 @@ In short: just because I could. It was one of those ideas I was wondering idly a ### Has it any practical use? It is not intended to have any. Since DNS records are fairly small, serving images or something would quickly start -consuming 100s of requests per second. I wouldn't want to do that to Cloudflare 😉 +consuming 100s of requests per second. I wouldn't want to do that to Cloudflare. It would be an interesting experiment to see how feasible that is. diff --git a/content/scripts/verifier.js b/content/scripts/verifier.js new file mode 100644 index 0000000..a64b784 --- /dev/null +++ b/content/scripts/verifier.js @@ -0,0 +1,21 @@ +class Verifier { + /*** + * @param content Content + */ + async verify(content) { + if (!window.isSecureContext) return; + if (typeof TextEncoder === "undefined") return; + if (typeof crypto === "undefined") return; + const encoder = new TextEncoder(); + const digestBuffer = await crypto.subtle.digest(content.index.hashAlgorithm, encoder.encode(content.content)); + + const hashArray = Array.from(new Uint8Array(digestBuffer)); // convert buffer to byte array + const digest = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // convert bytes to hex string + + if (content.index.hash === digest) { + document.getElementById("verification").innerHTML = + "The hash of the content is verified to correspond with the hash" + + " in the metadata. You are now reading exactly what was intended."; + } + } +} \ No newline at end of file diff --git a/index.html b/index.html index ffbab36..497ffb0 100644 --- a/index.html +++ b/index.html @@ -10,13 +10,20 @@ class Content { content = ""; type = ""; - metaData = {} + metaData = {}; + index; - constructor(content, type, metaData = {}) + /*** + * @param content string + * @param type string + * @param index Index + */ + constructor(content, type, index) { this.content = content; this.type = type; - this.metaData = metaData; + this.index = index; + this.metaData = index.metaData; } } @@ -24,13 +31,15 @@ class Index { mimeType = ""; chunks = 0; + hashAlgorithm = ""; hash = ""; metaData = {}; - constructor(mimeType, chunks, hash, metaData = {}) + constructor(mimeType, chunks, hash, hashAlgorithm, metaData = {}) { this.mimeType = mimeType; this.chunks = chunks; + this.hashAlgorithm = hashAlgorithm; this.hash = hash; this.metaData = metaData } @@ -51,7 +60,8 @@ async function readUrl(domain) { const chunks = await Promise.all(chunk_promises); const base64 = chunks.reduce((built, current) => built += current); - return handleContent(new Content(atob(content), index.mimeType, index.metaData)); + const content = atob(base64); + return handleContent(new Content(content, index.mimeType, index)); } async function fetchChunk(id, hash) @@ -84,7 +94,7 @@ async function fetchIndex(domain) }); const metadata = JSON.parse(atob(ret["m"])); - return new Index(ret["t"], ret["c"], ret["h"], metadata); + return new Index(ret["t"], ret["c"], ret["h"], ret["ha"], metadata); } function handleContent(content) @@ -110,7 +120,12 @@ function handleContent(content) function handleJavascript(content) { - console.log("Got some javascript!", content.content); + console.log("Got some javascript!"); + const scripts = document.getElementById("scripts"); + const new_script = document.createElement("script"); + new_script.text = content.content; + + scripts.appendChild(new_script); } async function handleMarkdown(content) @@ -128,20 +143,28 @@ async function handleMarkdown(content) let title = document.createElement("h1"); title.innerHTML = content.metaData.title; document.getElementById("post").prepend(title) - document.getElementById("nojs").style.visibility = "hidden"; + document.getElementById("nojs").remove(); + + if (typeof Verifier !== "undefined") { + await (new Verifier()).verify(content); + } }
- - + +The content of this page is fetched using DNS over HTTP. Since that requires Javascript, please enable that to see the content.