functionalscript
Version:
FunctionalScript is a purely functional subset of JavaScript
143 lines (142 loc) • 6.12 kB
JavaScript
import { msbUtf8 } from "../../text/module.f.js";
import { empty, msb, vec } from "../../types/bit_vec/module.f.js";
import { map } from "../../types/list/module.f.js";
import { repeat } from "../../types/monoid/module.f.js";
import { base32, base64, computeSync, sha224, sha256, sha384, sha512, sha512x224, sha512x256, } from "./module.f.js";
const { concat: beConcat } = msb;
const checkEmpty = ({ init, end }) => (x) => {
const result = end(init);
if (result !== x) {
throw [result, x];
}
};
// https://en.wikipedia.org/wiki/SHA-2#Test_vectors
//
// https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Secure-Hashing
export default {
base: {
b32: () => {
const { fromV8, compress, chunkLength } = base32;
const e = 1n << (chunkLength - 1n);
return {
s256: () => {
const result = fromV8(compress(sha256.init.hash)(e));
const x = 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855n;
if (result !== x) {
throw [result.toString(16), x.toString(16)];
}
},
s224: () => {
const result = fromV8(compress(sha224.init.hash)(e)) >> 32n;
const x = 0xd14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42fn;
if (result !== x) {
throw [result, x];
}
},
};
},
b64: () => {
const { fromV8, compress, chunkLength } = base64;
const e = 1n << (chunkLength - 1n);
return {
s512: () => {
const result = fromV8(compress(sha512.init.hash)(e));
const x = 0xcf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3en;
if (result !== x) {
throw [result, x];
}
},
s385: () => {
const result = fromV8(compress(sha384.init.hash)(e)) >> 128n;
const x = 0x38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95bn;
if (result !== x) {
throw [result, x];
}
},
s512x256: () => {
const result = fromV8(base64.compress(sha512x256.init.hash)(e)) >> 256n;
const x = 0xc672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967an;
if (result !== x) {
throw [result, x];
}
},
s512x224: () => {
const result = fromV8(compress(sha512x224.init.hash)(e)) >> 288n;
const x = 0x6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4n;
if (result !== x) {
throw [result, x];
}
},
};
}
},
sha2: {
sha256: () => checkEmpty(sha256)(0x1e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855n),
sha224: () => checkEmpty(sha224)(0x1d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42fn),
sha512: () => checkEmpty(sha512)(0x1cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3en),
sha384: () => checkEmpty(sha384)(0x138b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95bn),
sha512x256: () => checkEmpty(sha512x256)(0x1c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967an),
sha512x224: () => checkEmpty(sha512x224)(0x16ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4n),
},
utf8: [
() => {
const e = 0x1730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525n;
{
const s = msbUtf8("The quick brown fox jumps over the lazy dog");
const h = computeSync(sha224)([s]);
if (h !== e) {
throw h;
}
}
{
const s = ['The', ' quick', ' brown', ' fox', ' jumps', ' over', ' the', ' lazy', ' dog'];
const h = computeSync(sha224)(map(msbUtf8)(s));
if (h !== e) {
throw h;
}
}
},
() => {
const s = msbUtf8("The quick brown fox jumps over the lazy dog.");
const h = computeSync(sha224)([s]);
if (h !== 0x1619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4cn) {
throw h;
}
},
() => {
const s = msbUtf8("hello world");
if (s !== 0x168656c6c6f20776f726c64n) {
throw s;
}
let state = sha256.init;
state = sha256.append(state)(s);
const h = sha256.end(state);
if (h !== 0x1b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9n) {
throw h;
}
}
],
fill: () => {
const times = repeat({ identity: empty, operation: beConcat })(vec(32n)(0x31313131n));
return {
8: () => {
const r = times(8n);
let state = sha256.init;
state = sha256.append(state)(r);
const h = sha256.end(state);
if (h >> 224n !== 0x18a83665fn) {
throw h;
}
},
16: () => {
const r = times(16n);
let state = sha256.init;
state = sha256.append(state)(r);
const h = sha256.end(state);
if (h !== 0x13138bb9bc78df27c473ecfd1410f7bd45ebac1f59cf3ff9cfe4db77aab7aedd3n) {
throw h;
}
}
};
}
};