]> git.ardis.lu - cloudflare-workers/commitdiff
Add pwned worker
authorArdis Lu <ardisglu@gmail.com>
Fri, 4 Jun 2021 05:45:06 +0000 (22:45 -0700)
committerArdis Lu <ardisglu@gmail.com>
Fri, 4 Jun 2021 05:45:06 +0000 (22:45 -0700)
README.md
package.json
pwned/index.js [new file with mode: 0644]
pwned/package.json [new file with mode: 0644]

index e0f06358ad7dca76b1efcc257d06fe51953c9252..c3acfb70b3a5118e462e63ce41335a47a2c1669b 100644 (file)
--- a/README.md
+++ b/README.md
@@ -91,3 +91,22 @@ This reverse proxy injects permissive CORS response headers to a response. Usefu
 ### Usage
 
 Same as `proxy`.
+
+## pwned
+
+Checks a password against the [have i been pwned?](https://haveibeenpwned.com/) API and returns a boolean indicating if the password has been pwned or not. This is a simplified re-implementation of the [Pwned Passwords Cloudflare Worker](https://github.com/HaveIBeenPwned/PwnedPasswordsCloudflareWorker).
+
+### Usage
+
+Pass a plaintext password as the entire query string to the endpoint. For example, if your Cloudflare Worker domain is 
+```
+https://x.y.workers.dev
+```
+and the password you want to check is
+```
+hunter1
+```
+then the final request URL should be
+```
+https://x.y.workers.dev?hunter1
+```
\ No newline at end of file
index 1ed753784e74aba1f998b1f3d89fdbdd4a2dcf0c..1c13088787bf4ec06352d5e3b69e226c9b1d8a5a 100644 (file)
@@ -21,6 +21,7 @@
   "workspaces": [
     "proxy",
     "instagram",
-    "cors"
+    "cors",
+    "pwned"
   ]
 }
diff --git a/pwned/index.js b/pwned/index.js
new file mode 100644 (file)
index 0000000..a2db1ae
--- /dev/null
@@ -0,0 +1,25 @@
+async function handleRequest(request) {
+  const url = new URL(request.url);
+  const queryString = decodeURIComponent(url.search.substring(1));
+
+  // Convert password string to byte array and hash it, then convert hashed byte array to hex string
+  const inputArray = new TextEncoder().encode(queryString);
+  const digest = await crypto.subtle.digest('SHA-1', inputArray);
+  const outputArray = [...new Uint8Array(digest)]; // Need to spread typed array into a non-typed array to allow .map() to output strings
+  const hash = outputArray.map(v => v.toString(16).padStart(2, '0')).join('').toUpperCase();
+
+  // Split the hash as required by the HIBP API (k-Anonymity model)
+  const range = hash.substring(0, 5);
+  const index = hash.substring(5);
+
+  const result = fetch(`https://api.pwnedpasswords.com/range/${range}`)
+    .then(response => response.text())
+    .then(body => body.includes(index))
+    .then(bool => new Response(bool));
+
+  return result;
+}
+
+addEventListener('fetch', event => {
+  event.respondWith(handleRequest(event.request));
+})
diff --git a/pwned/package.json b/pwned/package.json
new file mode 100644 (file)
index 0000000..e0d69b1
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "name": "pwned",
+  "version": "0.1.0",
+  "description": "This is a re-implementation of the Pwned Passwords Cloudflare Worker.",
+  "private": true,
+  "main": "index.js",
+  "scripts": {
+    "login": "wrangler login",
+    "preview": "wrangler preview",
+    "build": "wrangler build",
+    "publish": "wrangler publish"
+  },
+  "author": "Ardis Lu",
+  "license": "ISC",
+  "devDependencies": {
+    "@cloudflare/wrangler": "^1.16.1"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/ardislu/cloudflare-workers.git"
+  }
+}
This page took 0.042653 seconds and 4 git commands to generate.