Skip to content

Commit d016212

Browse files
Add a hash to the stamp
The hash doesn't need to be cryptographic, so we'll use a simple non-cryptographic hash that we can be assured is always available. Signed-off-by: David A. Wheeler <[email protected]>
1 parent 12a4eeb commit d016212

File tree

1 file changed

+38
-7
lines changed

1 file changed

+38
-7
lines changed

docs/labs/checker.js

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -227,17 +227,48 @@ function findIndexes(form) {
227227
}
228228
}
229229

230+
/** Compute cyrb53 non-cryptographic hash */
231+
// cyrb53 (c) 2018 bryc (github.com/bryc). License: Public domain. Attribution appreciated.
232+
// A fast and simple 64-bit (or 53-bit) string hash function with decent collision resistance.
233+
// Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity.
234+
// See https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript/52171480#52171480
235+
// https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js
236+
// https://gist.github.com/jlevy/c246006675becc446360a798e2b2d781
237+
const cyrb64 = (str, seed = 0) => {
238+
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
239+
for(let i = 0, ch; i < str.length; i++) {
240+
ch = str.charCodeAt(i);
241+
h1 = Math.imul(h1 ^ ch, 2654435761);
242+
h2 = Math.imul(h2 ^ ch, 1597334677);
243+
}
244+
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
245+
h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
246+
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);
247+
h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);
248+
// For a single 53-bit numeric return value we could return
249+
// 4294967296 * (2097151 & h2) + (h1 >>> 0);
250+
// but we instead return the full 64-bit value:
251+
return [h2>>>0, h1>>>0];
252+
};
253+
254+
// An improved, *insecure* 64-bit hash that's short, fast, and has no dependencies.
255+
// Output is always 14 characters.
256+
// https://gist.github.com/jlevy/c246006675becc446360a798e2b2d781
257+
const cyrb64Hash = (str, seed = 0) => {
258+
const [h2, h1] = cyrb64(str, seed);
259+
return h2.toString(36).padStart(7, '0') + h1.toString(36).padStart(7, '0');
260+
}
261+
262+
/** Create a stamp to indicate completion. */
230263
function makeStamp() {
231264
let timeStamp = (new Date()).toISOString();
232265
let uuid = crypto.randomUUID();
233266
let resultBeginning = `${timeStamp} ${uuid}`;
234-
return resultBeginning;
235-
// TODO: Add hash. JavaScript has such a function
236-
// in the browser, but it's only available in secure contexts and
237-
// returns a promise, so it's not clear we should use it.
238-
// let digestHex = digestMessage(resultBeginning);
239-
// let digestEnding = digestHex.slice(-8);
240-
// return `${resultBeginning} ${digestEnding}`;
267+
// Browsers have a SHA-256 cryptographic hash available, but *only*
268+
// when they're in a "secure state". We don't need the hash to be
269+
// cryptographic, since the data is clearly in view. Use a simple one.
270+
let hash = cyrb64Hash(resultBeginning);
271+
return `${resultBeginning} ${hash}`;
241272
}
242273

243274
/**

0 commit comments

Comments
 (0)