Skip to content

Commit

Permalink
fix(crypto): support length option in crypto.subtle.digest (#1386)
Browse files Browse the repository at this point in the history
  • Loading branch information
getspooky authored Oct 19, 2021
1 parent bbe2271 commit a3257fa
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 83 deletions.
9 changes: 3 additions & 6 deletions crypto/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,7 @@ const stdCrypto = (<T extends WebCrypto>(x: T) => x)({
// and the data is a single buffer,
bytes
) {
return webCrypto.subtle.digest(
algorithm,
bytes,
);
return webCrypto.subtle.digest(algorithm, bytes);
} else if (wasmDigestAlgorithms.includes(name)) {
if (bytes) {
// Otherwise, we use our bundled WASM implementation via digestSync
Expand Down Expand Up @@ -215,7 +212,7 @@ const stdCrypto = (<T extends WebCrypto>(x: T) => x)({
// they're using.
return webCrypto.subtle.digest(
algorithm,
data as unknown as Uint8Array,
(data as unknown) as Uint8Array,
);
} else {
throw new TypeError(`unsupported digest algorithm: ${algorithm}`);
Expand All @@ -235,7 +232,7 @@ const stdCrypto = (<T extends WebCrypto>(x: T) => x)({
const bytes = bufferSourceBytes(data);

if (bytes) {
return wasmCrypto.digest(algorithm.name, bytes, undefined);
return wasmCrypto.digest(algorithm.name, bytes, algorithm.length);
} else if ((data as Iterable<BufferSource>)[Symbol.iterator]) {
const context = new wasmCrypto.DigestContext(algorithm.name);
for (const chunk of data as Iterable<BufferSource>) {
Expand Down
170 changes: 93 additions & 77 deletions crypto/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,92 +8,108 @@ const moduleDir = dirname(fromFileUrl(import.meta.url));

const webCrypto = globalThis.crypto;

Deno.test("[crypto/digest] Different ways to perform the same operation should produce the same result", async () => {
const inputString = "taking the hobbits to isengard";
const inputBytes = new TextEncoder().encode(inputString);
const inputPieces = [inputBytes.slice(0, 8), inputBytes.slice(8)];

const emptyDigest =
"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b";
const expectedDigest =
"ae30c171b2b5a047b7986c185564407672441934a356686e6df3a8284f35214448c40738e65b8c308e38b068eed91676";

assertEquals(
toHexString(stdCrypto.subtle.digestSync("SHA-384", inputBytes)),
expectedDigest,
);

assertEquals(
toHexString(
await stdCrypto.subtle.digest("SHA-384", new Blob([inputBytes]).stream()),
),
expectedDigest,
);

assertEquals(
toHexString(stdCrypto.subtle.digestSync("SHA-384", [inputBytes])),
expectedDigest,
);

assertEquals(
toHexString(
await stdCrypto.subtle.digest(
"SHA-384",
(async function* () {
yield new Uint16Array();
yield inputPieces[0];
yield new ArrayBuffer(0);
yield inputPieces[1];
})(),
Deno.test(
"[crypto/digest] Different ways to perform the same operation should produce the same result",
async () => {
const inputString = "taking the hobbits to isengard";
const inputBytes = new TextEncoder().encode(inputString);
const inputPieces = [inputBytes.slice(0, 8), inputBytes.slice(8)];

const emptyDigest =
"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b";
const expectedDigest =
"ae30c171b2b5a047b7986c185564407672441934a356686e6df3a8284f35214448c40738e65b8c308e38b068eed91676";

assertEquals(
toHexString(stdCrypto.subtle.digestSync("SHA-384", inputBytes)),
expectedDigest,
);

assertEquals(
toHexString(
await stdCrypto.subtle.digest(
"SHA-384",
new Blob([inputBytes]).stream(),
),
),
),
expectedDigest,
);

assertEquals(
toHexString(
stdCrypto.subtle.digestSync(
"SHA-384",
(function* () {
yield new ArrayBuffer(0);
yield* inputPieces;
yield new Int8Array();
})(),
expectedDigest,
);

assertEquals(
toHexString(stdCrypto.subtle.digestSync("SHA-384", [inputBytes])),
expectedDigest,
);

assertEquals(
toHexString(
await stdCrypto.subtle.digest(
"SHA-384",
(async function* () {
yield new Uint16Array();
yield inputPieces[0];
yield new ArrayBuffer(0);
yield inputPieces[1];
})(),
),
),
),
expectedDigest,
);

assertEquals(
toHexString(
await stdCrypto.subtle.digest(
"SHA-384",
(function* () {
yield inputBytes;
})(),
expectedDigest,
);

assertEquals(
toHexString(
stdCrypto.subtle.digestSync(
"SHA-384",
(function* () {
yield new ArrayBuffer(0);
yield* inputPieces;
yield new Int8Array();
})(),
),
),
),
expectedDigest,
);

assertEquals(
toHexString(await webCrypto.subtle!.digest("SHA-384", inputBytes)),
expectedDigest,
);
expectedDigest,
);

assertEquals(
toHexString(
await stdCrypto.subtle.digest(
"SHA-384",
(function* () {
yield inputBytes;
})(),
),
),
expectedDigest,
);

assertEquals(
toHexString(await webCrypto.subtle!.digest("SHA-384", inputBytes)),
expectedDigest,
);

assertEquals(
toHexString(stdCrypto.subtle.digestSync("SHA-384", new ArrayBuffer(0))),
emptyDigest,
);

assertEquals(
toHexString(await stdCrypto.subtle.digest("SHA-384", new ArrayBuffer(0))),
emptyDigest,
);
},
);

assertEquals(
toHexString(stdCrypto.subtle.digestSync("SHA-384", new ArrayBuffer(0))),
emptyDigest,
);
Deno.test("[crypto/digest] Should not ignore length option", async () => {
const inputString = "taking the hobbits to isengard";
const inputBytes = new TextEncoder().encode(inputString);

assertEquals(
toHexString(await stdCrypto.subtle.digest("SHA-384", new ArrayBuffer(0))),
emptyDigest,
await stdCrypto.subtle.digest({ name: "BLAKE3", length: 0 }, inputBytes),
new Uint8Array(0),
);

assertEquals(
toHexString(await webCrypto.subtle!.digest("SHA-384", new ArrayBuffer(0))),
emptyDigest,
await stdCrypto.subtle.digest({ name: "BLAKE3", length: 6 }, inputBytes),
new Uint8Array([167, 193, 151, 192, 40, 100]),
);
});

Expand Down

0 comments on commit a3257fa

Please sign in to comment.