From 5b134d7e9ec2b7cd036c8a2f4e52ddc39a6135d7 Mon Sep 17 00:00:00 2001 From: MikeCAT Date: Wed, 2 Nov 2022 21:54:45 +0900 Subject: [PATCH] fix Fletcher-32/64 Checksum * Operate on words, not bytes * Add tests --- src/core/operations/Fletcher32Checksum.mjs | 14 ++- src/core/operations/Fletcher64Checksum.mjs | 18 +++- tests/operations/index.mjs | 1 + tests/operations/tests/FletcherChecksum.mjs | 108 +++++++++++++++++++ tests/operations/tests/GenerateAllHashes.mjs | 4 +- 5 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 tests/operations/tests/FletcherChecksum.mjs diff --git a/src/core/operations/Fletcher32Checksum.mjs b/src/core/operations/Fletcher32Checksum.mjs index 29c74535..7b41ce55 100644 --- a/src/core/operations/Fletcher32Checksum.mjs +++ b/src/core/operations/Fletcher32Checksum.mjs @@ -35,10 +35,18 @@ class Fletcher32Checksum extends Operation { run(input, args) { let a = 0, b = 0; - input = new Uint8Array(input); + if (ArrayBuffer.isView(input)) { + input = new DataView(input.buffer, input.byteOffset, input.byteLength); + } else { + input = new DataView(input); + } - for (let i = 0; i < input.length; i++) { - a = (a + input[i]) % 0xffff; + for (let i = 0; i < input.byteLength - 1; i += 2) { + a = (a + input.getUint16(i, true)) % 0xffff; + b = (b + a) % 0xffff; + } + if (input.byteLength % 2 !== 0) { + a = (a + input.getUint8(input.byteLength - 1)) % 0xffff; b = (b + a) % 0xffff; } diff --git a/src/core/operations/Fletcher64Checksum.mjs b/src/core/operations/Fletcher64Checksum.mjs index 1d0d5bd9..68328ea3 100644 --- a/src/core/operations/Fletcher64Checksum.mjs +++ b/src/core/operations/Fletcher64Checksum.mjs @@ -35,10 +35,22 @@ class Fletcher64Checksum extends Operation { run(input, args) { let a = 0, b = 0; - input = new Uint8Array(input); + if (ArrayBuffer.isView(input)) { + input = new DataView(input.buffer, input.byteOffset, input.byteLength); + } else { + input = new DataView(input); + } - for (let i = 0; i < input.length; i++) { - a = (a + input[i]) % 0xffffffff; + for (let i = 0; i < input.byteLength - 3; i += 4) { + a = (a + input.getUint32(i, true)) % 0xffffffff; + b = (b + a) % 0xffffffff; + } + if (input.byteLength % 4 !== 0) { + let lastValue = 0; + for (let i = 0; i < input.byteLength % 4; i++) { + lastValue = (lastValue << 8) | input.getUint8(input.byteLength - 1 - i); + } + a = (a + lastValue) % 0xffffffff; b = (b + a) % 0xffffffff; } diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index 19e70970..fe1c4e00 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -124,6 +124,7 @@ import "./tests/UnescapeString.mjs"; import "./tests/LS47.mjs"; import "./tests/LZString.mjs"; import "./tests/NTLM.mjs"; +import "./tests/FletcherChecksum.mjs"; // Cannot test operations that use the File type yet // import "./tests/SplitColourChannels.mjs"; diff --git a/tests/operations/tests/FletcherChecksum.mjs b/tests/operations/tests/FletcherChecksum.mjs new file mode 100644 index 00000000..de23abdc --- /dev/null +++ b/tests/operations/tests/FletcherChecksum.mjs @@ -0,0 +1,108 @@ +/** + * @author mikecat + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "Fletcher-16 Checksum: abcde", + input: "abcde", + expectedOutput: "c8f0", + recipeConfig: [ + { + op: "Fletcher-16 Checksum", + args: [], + }, + ], + }, + { + name: "Fletcher-16 Checksum: abcdef", + input: "abcdef", + expectedOutput: "2057", + recipeConfig: [ + { + op: "Fletcher-16 Checksum", + args: [], + }, + ], + }, + { + name: "Fletcher-16 Checksum: abcdefgh", + input: "abcdefgh", + expectedOutput: "0627", + recipeConfig: [ + { + op: "Fletcher-16 Checksum", + args: [], + }, + ], + }, + { + name: "Fletcher-32 Checksum: abcde", + input: "abcde", + expectedOutput: "f04fc729", + recipeConfig: [ + { + op: "Fletcher-32 Checksum", + args: [], + }, + ], + }, + { + name: "Fletcher-32 Checksum: abcdef", + input: "abcdef", + expectedOutput: "56502d2a", + recipeConfig: [ + { + op: "Fletcher-32 Checksum", + args: [], + }, + ], + }, + { + name: "Fletcher-32 Checksum: abcdefgh", + input: "abcdefgh", + expectedOutput: "ebe19591", + recipeConfig: [ + { + op: "Fletcher-32 Checksum", + args: [], + }, + ], + }, + { + name: "Fletcher-64 Checksum: abcde", + input: "abcde", + expectedOutput: "c8c6c527646362c6", + recipeConfig: [ + { + op: "Fletcher-64 Checksum", + args: [], + }, + ], + }, + { + name: "Fletcher-64 Checksum: abcdef", + input: "abcdef", + expectedOutput: "c8c72b276463c8c6", + recipeConfig: [ + { + op: "Fletcher-64 Checksum", + args: [], + }, + ], + }, + { + name: "Fletcher-64 Checksum: abcdefgh", + input: "abcdefgh", + expectedOutput: "312e2b28cccac8c6", + recipeConfig: [ + { + op: "Fletcher-64 Checksum", + args: [], + }, + ], + }, +]); diff --git a/tests/operations/tests/GenerateAllHashes.mjs b/tests/operations/tests/GenerateAllHashes.mjs index 28707bde..8e4a849a 100644 --- a/tests/operations/tests/GenerateAllHashes.mjs +++ b/tests/operations/tests/GenerateAllHashes.mjs @@ -58,8 +58,8 @@ CTPH: A:E:E Checksums: Fletcher-8: 3d Fletcher-16: 5dc1 -Fletcher-32: 045901c0 -Fletcher-64: 00000459000001c0 +Fletcher-32: 3f5cd9e7 +Fletcher-64: 7473657474736574 Adler-32: 045d01c1 CRC-8: b9 CRC-16: f82e