From 90b001747cb80a1127c44b515fd4204779ed2f3e Mon Sep 17 00:00:00 2001 From: Ardis Lu Date: Sun, 31 Mar 2024 01:08:05 -0700 Subject: [PATCH] Allow directly hashing hex byte array --- README.md | 23 ++++++++++++++++++++--- hash/index.js | 22 ++++++++++++++++++---- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b994ae3..450d77d 100644 --- a/README.md +++ b/README.md @@ -238,21 +238,31 @@ PS> (Invoke-WebRequest https://x.y.workers.dev).Content ## hash -Returns the hash of a string using the +Returns the hash of a string or a hexadecimal byte array using the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest). In bash: ```bash -$ curl https://x.y.workers.dev?algorithm=SHA-256&query=Hello%2C%20world%21 +# SHA-256 hash of the string "Hello, world!" +$ curl "https://x.y.workers.dev?algorithm=SHA-256&query=Hello%2C%20world%21" 315F5BDB76D078C43B8AC0064E4A0164612B1FCE77C869345BFC94C75894EDD3 + +# MD5 hash of the literal byte array [00, AA, BB, CC] +$ curl "https://x.y.workers.dev?algorithm=MD5&hex=00AABBCC" +CD7409B51FDE80807E2E1532B7432A00 ``` In PowerShell: ```powershell -PS> (Invoke-WebRequest https://x.y.workers.dev?algorithm=SHA-256&query=Hello%2C%20world%21).Content +# SHA-256 hash of the string "Hello, world!" +PS> (Invoke-WebRequest "https://x.y.workers.dev?algorithm=SHA-256&query=Hello%2C%20world%21").Content 315F5BDB76D078C43B8AC0064E4A0164612B1FCE77C869345BFC94C75894EDD3 + +# MD5 hash of the literal byte array [00, AA, BB, CC] +PS> (Invoke-WebRequest "https://x.y.workers.dev?algorithm=MD5&hex=00AABBCC").Content +CD7409B51FDE80807E2E1532B7432A00 ``` ### `algorithm` (alias `a`) @@ -268,3 +278,10 @@ Supported values are: ### `query` (alias `q`) The string you want to get the hash of. + +### `hex` (alias `h`) + +The hexadecimal byte array you want to get the hash of. An optional "0x" prefix +may be given, the prefix is ignored. + +If both `query` and `hex` are provided, `query` will be used. diff --git a/hash/index.js b/hash/index.js index 1fa697b..7fb5390 100644 --- a/hash/index.js +++ b/hash/index.js @@ -3,6 +3,7 @@ export default { const url = new URL(request.url); let algorithm; let query; + let hex; // Parse URLSearchParams for (const [key, value] of url.searchParams) { @@ -18,18 +19,31 @@ export default { else if ((normalizedKey === 'q' || normalizedKey === 'query') && value) { // Intentionally fail for falsy values because a null or empty string is also invalid query = value; } + else if ((normalizedKey === 'h' || normalizedKey === 'hex') && value) { + hex = value; + } } // Handling bad params if (algorithm === undefined) { return new Response('Invalid algorithm provided. Provide one of the following values for the parameter "a" or "algorithm": MD5, SHA-1, SHA-256, SHA-384, or SHA-512.', { status: 400 }); } - else if (query === undefined) { - return new Response('Invalid query provided. Provide a value for the parameter "q" or "query".', { status: 400 }); + if (query === undefined && hex === undefined) { + return new Response('No input provided. Provide a string value for the parameter "q" or "query", or a hex value for the parameter "h" or "hex".', { status: 400 }); + } + if (hex !== undefined) { + if (hex.length % 2 === 1 || !/^(0x)?[a-fA-F0-9]+$/.test(hex)) { + return new Response('Invalid hexadecimal input provided.', { status: 400 }); + } } - // Convert query string to byte array and hash it, then convert hashed byte array to hex string - const inputArray = new TextEncoder().encode(query); + let inputArray; + if (query) { + inputArray = new TextEncoder().encode(query); + } + else { + inputArray = Uint8Array.from(hex.replace('0x', '').match(/.{2}/g), v => parseInt(v, 16)); + } const digest = await crypto.subtle.digest(algorithm, 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(); -- 2.47.3