mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
244 lines
8.6 KiB
TypeScript
244 lines
8.6 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { withoutAggressiveGC } from "harness";
|
|
|
|
test("Bun.file in CryptoHasher is not supported yet", () => {
|
|
expect(() => Bun.SHA1.hash(Bun.file(import.meta.path))).toThrow();
|
|
expect(() => Bun.CryptoHasher.hash("sha1", Bun.file(import.meta.path))).toThrow();
|
|
expect(() => new Bun.CryptoHasher("sha1").update(Bun.file(import.meta.path))).toThrow();
|
|
expect(() => new Bun.SHA1().update(Bun.file(import.meta.path))).toThrow();
|
|
});
|
|
test("CryptoHasher update should throw when no parameter/null/undefined is passed", () => {
|
|
// @ts-expect-error
|
|
expect(() => new Bun.CryptoHasher("sha1").update()).toThrow();
|
|
// @ts-expect-error
|
|
expect(() => new Bun.CryptoHasher("sha1").update(undefined)).toThrow();
|
|
// @ts-expect-error
|
|
expect(() => new Bun.CryptoHasher("sha1").update(null)).toThrow();
|
|
});
|
|
|
|
describe("HMAC", () => {
|
|
const hashes = {
|
|
"sha1": "e2e1f7f597941d9b0021978618218a9e08731426",
|
|
"sha256": "c7a7c96c73af32ea6e5b1ca6768b1d822249eb88f85160433d7b09bb2b21e170",
|
|
"sha384": "2483522dcb7cb65fa13f0a3c1efe867abbd79ecb19a6ba4bac45d4f4bac31de2e2463b11838b8055601fad73d0b5af4c",
|
|
"sha512":
|
|
"f82266c950db24eba03f899466fdf905494709f09f98f4b7d7db31f1443a33b4fe5ca82f74fb360609d8a05a87fb065dd77bee912c27de89cbba7897061ac735",
|
|
"blake2b512":
|
|
"9e66ba10f4d7e80abc2584150fc5f9a246634118280fd9ae086794d37cb9919d681ee285b68f9cec2eda9f878d157125cc465c8b0e3c023a7040ed0be7f25023",
|
|
"md5": "4e7eb9f9332e4eb1dc5a2d7d065ba1bf",
|
|
"sha224": "d34c3a2647d4f82a4e6baeaa7d94379eafd931e0c16cbc44b4ba4d1e",
|
|
"sha512-224": "af398c7f21f58e1377580227a89590d3ab8be52b31182fad9ec4d667",
|
|
"sha512-256": "0ed15b2750a2a7281e96af006ab79e82ed54a7a2081bdb49e70a70d8c6bfeff0",
|
|
};
|
|
for (let key of ["key", Buffer.from("key"), Buffer.from("key").buffer]) {
|
|
test.each(Object.entries(hashes))("%s (key: " + key.constructor.name + ")", (algorithm, expected) => {
|
|
const hmac = new Bun.CryptoHasher(algorithm, key);
|
|
hmac.update("data\n");
|
|
const copied = hmac.copy();
|
|
expect(hmac.algorithm).toEqual(algorithm);
|
|
expect(hmac.byteLength).toEqual(hashes[algorithm].length / 2);
|
|
expect(copied.copy()).toBeInstanceOf(Bun.CryptoHasher);
|
|
|
|
expect(hmac.digest("hex")).toEqual(expected);
|
|
|
|
expect(copied.algorithm).toEqual(algorithm);
|
|
expect(copied.byteLength).toEqual(hashes[algorithm].length / 2);
|
|
|
|
expect(copied.digest("hex")).toEqual(expected);
|
|
expect(() => hmac.digest()).toThrow();
|
|
expect(() => copied.digest()).toThrow();
|
|
expect(() => hmac.byteLength).toThrow();
|
|
expect(() => copied.byteLength).toThrow();
|
|
expect(() => copied.copy()).toThrow();
|
|
expect(() => hmac.copy()).toThrow();
|
|
|
|
// Note that algorithm may throw if the first time the property was accessed is after it was already consumed.
|
|
// This is a property caching edgecase that it does not always throw.
|
|
// But let's see if anyone complains about it. It is extremely minor
|
|
});
|
|
}
|
|
|
|
const unsupported = [
|
|
["sha3-224"],
|
|
["sha3-256"],
|
|
["sha3-384"],
|
|
["sha3-512"],
|
|
["shake128"],
|
|
["shake256"],
|
|
["ripemd160"],
|
|
] as const;
|
|
test.each(unsupported)("%s is not supported", algorithm => {
|
|
expect(() => new Bun.CryptoHasher(algorithm, "key")).toThrow();
|
|
expect(() => new Bun.CryptoHasher(algorithm)).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe("Hash is consistent", () => {
|
|
const sourceInputs = [
|
|
Buffer.from([
|
|
103, 87, 129, 242, 154, 82, 159, 206, 176, 124, 10, 39, 235, 214, 121, 13, 34, 155, 131, 178, 40, 34, 252, 134, 7,
|
|
203, 130, 187, 207, 49, 26, 59,
|
|
]),
|
|
Buffer.from([
|
|
68, 19, 111, 163, 85, 179, 103, 138, 17, 70, 173, 22, 247, 232, 100, 158, 148, 251, 79, 194, 31, 231, 126, 131,
|
|
16, 192, 96, 246, 28, 170, 255, 138,
|
|
]),
|
|
Buffer.from([
|
|
219, 133, 5, 84, 59, 236, 191, 241, 104, 167, 186, 223, 204, 158, 177, 43, 205, 52, 120, 28, 60, 233, 156, 159,
|
|
125, 64, 171, 91, 240, 17, 71, 210,
|
|
]),
|
|
Buffer.from([
|
|
34, 93, 2, 87, 76, 190, 175, 238, 185, 96, 201, 38, 104, 215, 236, 99, 223, 134, 157, 237, 254, 36, 49, 242, 100,
|
|
135, 198, 114, 49, 71, 220, 79,
|
|
]),
|
|
];
|
|
|
|
const inputs = [...sourceInputs, ...sourceInputs.map(x => new Blob([x]))];
|
|
|
|
for (let algorithm of [
|
|
Bun.SHA1,
|
|
Bun.SHA224,
|
|
Bun.SHA256,
|
|
Bun.SHA384,
|
|
Bun.SHA512,
|
|
Bun.SHA512_256,
|
|
Bun.MD4,
|
|
Bun.MD5,
|
|
] as const) {
|
|
test(`second digest should throw an error ${algorithm.name}`, () => {
|
|
const hasher = new algorithm().update("hello");
|
|
hasher.digest();
|
|
expect(() => hasher.digest()).toThrow(
|
|
`${algorithm.name} hasher already digested, create a new instance to digest again`,
|
|
);
|
|
expect(() => hasher.update("world")).toThrow(
|
|
`${algorithm.name} hasher already digested, create a new instance to update`,
|
|
);
|
|
});
|
|
}
|
|
|
|
for (let algorithm of ["sha1", "sha256", "sha512", "md5"] as const) {
|
|
describe(algorithm, () => {
|
|
const Class = globalThis.Bun[algorithm.toUpperCase() as "SHA1" | "SHA256" | "SHA512" | "MD5"];
|
|
test("base64", () => {
|
|
for (let buffer of inputs) {
|
|
for (let i = 0; i < 100; i++) {
|
|
const hasher = new Bun.CryptoHasher(algorithm);
|
|
expect(hasher.update(buffer, "base64")).toBeInstanceOf(Bun.CryptoHasher);
|
|
expect(Bun.CryptoHasher.hash(algorithm, buffer, "base64")).toEqual(
|
|
Bun.CryptoHasher.hash(algorithm, buffer, "base64"),
|
|
);
|
|
|
|
const instance1 = new Class();
|
|
instance1.update(buffer);
|
|
const instance2 = new Class();
|
|
instance2.update(buffer);
|
|
|
|
expect(instance1.digest("base64")).toEqual(instance2.digest("base64"));
|
|
expect(Class.hash(buffer, "base64")).toEqual(Class.hash(buffer, "base64"));
|
|
}
|
|
}
|
|
});
|
|
|
|
test("hex", () => {
|
|
for (let buffer of inputs) {
|
|
for (let i = 0; i < 100; i++) {
|
|
const hasher = new Bun.CryptoHasher(algorithm);
|
|
expect(hasher.update(buffer, "hex")).toBeInstanceOf(Bun.CryptoHasher);
|
|
expect(Bun.CryptoHasher.hash(algorithm, buffer, "hex")).toEqual(
|
|
Bun.CryptoHasher.hash(algorithm, buffer, "hex"),
|
|
);
|
|
|
|
const instance1 = new Class();
|
|
instance1.update(buffer);
|
|
const instance2 = new Class();
|
|
instance2.update(buffer);
|
|
|
|
expect(instance1.digest("hex")).toEqual(instance2.digest("hex"));
|
|
expect(Class.hash(buffer, "hex")).toEqual(Class.hash(buffer, "hex"));
|
|
}
|
|
}
|
|
});
|
|
|
|
test("blob", () => {
|
|
for (let buffer of inputs) {
|
|
for (let i = 0; i < 100; i++) {
|
|
const hasher = new Bun.CryptoHasher(algorithm);
|
|
expect(hasher.update(buffer)).toBeInstanceOf(Bun.CryptoHasher);
|
|
expect(Bun.CryptoHasher.hash(algorithm, buffer)).toEqual(Bun.CryptoHasher.hash(algorithm, buffer));
|
|
|
|
const instance1 = new Class();
|
|
instance1.update(buffer);
|
|
const instance2 = new Class();
|
|
instance2.update(buffer);
|
|
|
|
expect(instance1.digest()).toEqual(instance2.digest());
|
|
expect(Class.hash(buffer)).toEqual(Class.hash(buffer));
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
describe("CryptoHasher", () => {
|
|
const algorithms = [
|
|
"blake2b256",
|
|
"blake2b512",
|
|
"blake2s256",
|
|
"ripemd160",
|
|
"rmd160",
|
|
"md4",
|
|
"md5",
|
|
"sha1",
|
|
"sha128",
|
|
"sha224",
|
|
"sha256",
|
|
"sha384",
|
|
"sha512",
|
|
"sha-1",
|
|
"sha-224",
|
|
"sha-256",
|
|
"sha-384",
|
|
"sha-512",
|
|
"sha-512/224",
|
|
"sha-512_224",
|
|
"sha-512224",
|
|
"sha512-224",
|
|
"sha-512/256",
|
|
"sha-512_256",
|
|
"sha-512256",
|
|
"sha512-256",
|
|
"sha384",
|
|
"sha3-224",
|
|
"sha3-256",
|
|
"sha3-384",
|
|
"sha3-512",
|
|
"shake128",
|
|
"shake256",
|
|
] as const;
|
|
|
|
for (let algorithm of algorithms) {
|
|
describe(algorithm, () => {
|
|
for (let encoding of ["hex", "base64", "buffer", undefined, "base64url"] as const) {
|
|
describe(encoding || "default", () => {
|
|
test("instance", () => {
|
|
const hasher = new Bun.CryptoHasher(algorithm || undefined);
|
|
hasher.update("hello");
|
|
expect(hasher.digest(encoding)).toEqual(Bun.CryptoHasher.hash(algorithm, "hello", encoding));
|
|
});
|
|
|
|
test("consistent", () => {
|
|
const first = Bun.CryptoHasher.hash(algorithm, "hello", encoding);
|
|
withoutAggressiveGC(() => {
|
|
for (let i = 0; i < 100; i++) {
|
|
expect(Bun.CryptoHasher.hash(algorithm, "hello", encoding)).toStrictEqual(first);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
});
|