1 | import { jsSHABase, packedLEConcat, sha_variant_error, mac_rounds_error, TWO_PWR_32, parseInputOption } from "./common";
|
2 | import {
|
3 | packedValue,
|
4 | CSHAKEOptionsNoEncodingType,
|
5 | CSHAKEOptionsEncodingType,
|
6 | SHAKEOptionsNoEncodingType,
|
7 | SHAKEOptionsEncodingType,
|
8 | KMACOptionsNoEncodingType,
|
9 | KMACOptionsEncodingType,
|
10 | FixedLengthOptionsEncodingType,
|
11 | FixedLengthOptionsNoEncodingType,
|
12 | FormatNoTextType,
|
13 | ResolvedCSHAKEOptionsNoEncodingType,
|
14 | ResolvedKMACOptionsNoEncodingType,
|
15 | } from "./custom_types";
|
16 | import { getStrConverter } from "./converters";
|
17 | import { Int_64, rotl_64, xor_64_2, xor_64_5 } from "./primitives_64";
|
18 |
|
19 | type FixedLengthVariantType = "SHA3-224" | "SHA3-256" | "SHA3-384" | "SHA3-512" | "SHAKE128" | "SHAKE256";
|
20 |
|
21 | type VariantType = FixedLengthVariantType | "SHAKE128" | "SHAKE256" | "CSHAKE128" | "CSHAKE256" | "KMAC128" | "KMAC256";
|
22 |
|
23 | const rc_sha3 = [
|
24 | new Int_64(0x00000000, 0x00000001),
|
25 | new Int_64(0x00000000, 0x00008082),
|
26 | new Int_64(0x80000000, 0x0000808a),
|
27 | new Int_64(0x80000000, 0x80008000),
|
28 | new Int_64(0x00000000, 0x0000808b),
|
29 | new Int_64(0x00000000, 0x80000001),
|
30 | new Int_64(0x80000000, 0x80008081),
|
31 | new Int_64(0x80000000, 0x00008009),
|
32 | new Int_64(0x00000000, 0x0000008a),
|
33 | new Int_64(0x00000000, 0x00000088),
|
34 | new Int_64(0x00000000, 0x80008009),
|
35 | new Int_64(0x00000000, 0x8000000a),
|
36 | new Int_64(0x00000000, 0x8000808b),
|
37 | new Int_64(0x80000000, 0x0000008b),
|
38 | new Int_64(0x80000000, 0x00008089),
|
39 | new Int_64(0x80000000, 0x00008003),
|
40 | new Int_64(0x80000000, 0x00008002),
|
41 | new Int_64(0x80000000, 0x00000080),
|
42 | new Int_64(0x00000000, 0x0000800a),
|
43 | new Int_64(0x80000000, 0x8000000a),
|
44 | new Int_64(0x80000000, 0x80008081),
|
45 | new Int_64(0x80000000, 0x00008080),
|
46 | new Int_64(0x00000000, 0x80000001),
|
47 | new Int_64(0x80000000, 0x80008008),
|
48 | ];
|
49 |
|
50 | const r_sha3 = [
|
51 | [0, 36, 3, 41, 18],
|
52 | [1, 44, 10, 45, 2],
|
53 | [62, 6, 43, 15, 61],
|
54 | [28, 55, 25, 21, 56],
|
55 | [27, 20, 39, 8, 14],
|
56 | ];
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | function getNewState(_variant: VariantType): Int_64[][] {
|
65 | let i;
|
66 | const retVal = [];
|
67 |
|
68 | for (i = 0; i < 5; i += 1) {
|
69 | retVal[i] = [new Int_64(0, 0), new Int_64(0, 0), new Int_64(0, 0), new Int_64(0, 0), new Int_64(0, 0)];
|
70 | }
|
71 |
|
72 | return retVal;
|
73 | }
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 | function cloneSHA3State(state: Int_64[][]): Int_64[][] {
|
82 | let i;
|
83 | const clone = [];
|
84 | for (i = 0; i < 5; i += 1) {
|
85 | clone[i] = state[i].slice();
|
86 | }
|
87 |
|
88 | return clone;
|
89 | }
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 | function roundSHA3(block: number[] | null, state: Int_64[][]): Int_64[][] {
|
99 | let round, x, y, B;
|
100 | const C = [],
|
101 | D = [];
|
102 |
|
103 | if (null !== block) {
|
104 | for (x = 0; x < block.length; x += 2) {
|
105 | state[(x >>> 1) % 5][((x >>> 1) / 5) | 0] = xor_64_2(
|
106 | state[(x >>> 1) % 5][((x >>> 1) / 5) | 0],
|
107 | new Int_64(block[x + 1], block[x])
|
108 | );
|
109 | }
|
110 | }
|
111 |
|
112 | for (round = 0; round < 24; round += 1) {
|
113 |
|
114 | B = getNewState("SHA3-384");
|
115 |
|
116 |
|
117 | for (x = 0; x < 5; x += 1) {
|
118 | C[x] = xor_64_5(state[x][0], state[x][1], state[x][2], state[x][3], state[x][4]);
|
119 | }
|
120 | for (x = 0; x < 5; x += 1) {
|
121 | D[x] = xor_64_2(C[(x + 4) % 5], rotl_64(C[(x + 1) % 5], 1));
|
122 | }
|
123 | for (x = 0; x < 5; x += 1) {
|
124 | for (y = 0; y < 5; y += 1) {
|
125 | state[x][y] = xor_64_2(state[x][y], D[x]);
|
126 | }
|
127 | }
|
128 |
|
129 |
|
130 | for (x = 0; x < 5; x += 1) {
|
131 | for (y = 0; y < 5; y += 1) {
|
132 | B[y][(2 * x + 3 * y) % 5] = rotl_64(state[x][y], r_sha3[x][y]);
|
133 | }
|
134 | }
|
135 |
|
136 |
|
137 | for (x = 0; x < 5; x += 1) {
|
138 | for (y = 0; y < 5; y += 1) {
|
139 | state[x][y] = xor_64_2(
|
140 | B[x][y],
|
141 | new Int_64(
|
142 | ~B[(x + 1) % 5][y].highOrder & B[(x + 2) % 5][y].highOrder,
|
143 | ~B[(x + 1) % 5][y].lowOrder & B[(x + 2) % 5][y].lowOrder
|
144 | )
|
145 | );
|
146 | }
|
147 | }
|
148 |
|
149 |
|
150 | state[0][0] = xor_64_2(state[0][0], rc_sha3[round]);
|
151 | }
|
152 |
|
153 | return state;
|
154 | }
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 | function finalizeSHA3(
|
169 | remainder: number[],
|
170 | remainderBinLen: number,
|
171 | _processedBinLen: number,
|
172 | state: Int_64[][],
|
173 | blockSize: number,
|
174 | delimiter: number,
|
175 | outputLen: number
|
176 | ): number[] {
|
177 | let i,
|
178 | state_offset = 0,
|
179 | temp;
|
180 | const retVal = [],
|
181 | binaryStringInc = blockSize >>> 5,
|
182 | remainderIntLen = remainderBinLen >>> 5;
|
183 |
|
184 | |
185 |
|
186 |
|
187 | for (i = 0; i < remainderIntLen && remainderBinLen >= blockSize; i += binaryStringInc) {
|
188 | state = roundSHA3(remainder.slice(i, i + binaryStringInc), state);
|
189 | remainderBinLen -= blockSize;
|
190 | }
|
191 |
|
192 | remainder = remainder.slice(i);
|
193 | remainderBinLen = remainderBinLen % blockSize;
|
194 |
|
195 |
|
196 | while (remainder.length < binaryStringInc) {
|
197 | remainder.push(0);
|
198 | }
|
199 |
|
200 |
|
201 | i = remainderBinLen >>> 3;
|
202 | remainder[i >> 2] ^= delimiter << (8 * (i % 4));
|
203 |
|
204 | remainder[binaryStringInc - 1] ^= 0x80000000;
|
205 | state = roundSHA3(remainder, state);
|
206 |
|
207 | while (retVal.length * 32 < outputLen) {
|
208 | temp = state[state_offset % 5][(state_offset / 5) | 0];
|
209 | retVal.push(temp.lowOrder);
|
210 | if (retVal.length * 32 >= outputLen) {
|
211 | break;
|
212 | }
|
213 | retVal.push(temp.highOrder);
|
214 | state_offset += 1;
|
215 |
|
216 | if (0 === (state_offset * 64) % blockSize) {
|
217 | roundSHA3(null, state);
|
218 | state_offset = 0;
|
219 | }
|
220 | }
|
221 |
|
222 | return retVal;
|
223 | }
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 | function left_encode(x: number): packedValue {
|
232 | let byteOffset,
|
233 | byte,
|
234 | numEncodedBytes = 0;
|
235 |
|
236 | const retVal = [0, 0],
|
237 | x_64 = [x & 0xffffffff, (x / TWO_PWR_32) & 0x1fffff];
|
238 |
|
239 | for (byteOffset = 6; byteOffset >= 0; byteOffset--) {
|
240 |
|
241 | byte = (x_64[byteOffset >> 2] >>> (8 * byteOffset)) & 0xff;
|
242 |
|
243 | |
244 |
|
245 | if (byte !== 0 || numEncodedBytes !== 0) {
|
246 | retVal[(numEncodedBytes + 1) >> 2] |= byte << ((numEncodedBytes + 1) * 8);
|
247 | numEncodedBytes += 1;
|
248 | }
|
249 | }
|
250 | numEncodedBytes = numEncodedBytes !== 0 ? numEncodedBytes : 1;
|
251 | retVal[0] |= numEncodedBytes;
|
252 |
|
253 | return { value: numEncodedBytes + 1 > 4 ? retVal : [retVal[0]], binLen: 8 + numEncodedBytes * 8 };
|
254 | }
|
255 |
|
256 |
|
257 |
|
258 |
|
259 |
|
260 |
|
261 |
|
262 | function right_encode(x: number): packedValue {
|
263 | let byteOffset,
|
264 | byte,
|
265 | numEncodedBytes = 0;
|
266 |
|
267 | const retVal = [0, 0],
|
268 | x_64 = [x & 0xffffffff, (x / TWO_PWR_32) & 0x1fffff];
|
269 |
|
270 | for (byteOffset = 6; byteOffset >= 0; byteOffset--) {
|
271 |
|
272 | byte = (x_64[byteOffset >> 2] >>> (8 * byteOffset)) & 0xff;
|
273 |
|
274 | |
275 |
|
276 | if (byte !== 0 || numEncodedBytes !== 0) {
|
277 | retVal[numEncodedBytes >> 2] |= byte << (numEncodedBytes * 8);
|
278 | numEncodedBytes += 1;
|
279 | }
|
280 | }
|
281 | numEncodedBytes = numEncodedBytes !== 0 ? numEncodedBytes : 1;
|
282 | retVal[numEncodedBytes >> 2] |= numEncodedBytes << (numEncodedBytes * 8);
|
283 |
|
284 | return { value: numEncodedBytes + 1 > 4 ? retVal : [retVal[0]], binLen: 8 + numEncodedBytes * 8 };
|
285 | }
|
286 |
|
287 |
|
288 |
|
289 |
|
290 |
|
291 |
|
292 |
|
293 | function encode_string(input: packedValue): packedValue {
|
294 | return packedLEConcat(left_encode(input["binLen"]), input);
|
295 | }
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 | function byte_pad(packed: packedValue, outputByteLen: number): number[] {
|
305 | let encodedLen = left_encode(outputByteLen),
|
306 | i;
|
307 |
|
308 | encodedLen = packedLEConcat(encodedLen, packed);
|
309 | const outputIntLen = outputByteLen >>> 2,
|
310 | intsToAppend = (outputIntLen - (encodedLen["value"].length % outputIntLen)) % outputIntLen;
|
311 |
|
312 | for (i = 0; i < intsToAppend; i++) {
|
313 | encodedLen["value"].push(0);
|
314 | }
|
315 |
|
316 | return encodedLen["value"];
|
317 | }
|
318 |
|
319 |
|
320 |
|
321 |
|
322 |
|
323 |
|
324 | function resolveCSHAKEOptions(options: CSHAKEOptionsNoEncodingType): ResolvedCSHAKEOptionsNoEncodingType {
|
325 | const resolvedOptions = options || {};
|
326 |
|
327 | return {
|
328 | funcName: parseInputOption("funcName", resolvedOptions["funcName"], 1, { value: [], binLen: 0 }),
|
329 | customization: parseInputOption("Customization", resolvedOptions["customization"], 1, { value: [], binLen: 0 }),
|
330 | };
|
331 | }
|
332 |
|
333 |
|
334 |
|
335 |
|
336 |
|
337 |
|
338 | function resolveKMACOptions(options: KMACOptionsNoEncodingType): ResolvedKMACOptionsNoEncodingType {
|
339 | const resolvedOptions = options || {};
|
340 |
|
341 | return {
|
342 | kmacKey: parseInputOption("kmacKey", resolvedOptions["kmacKey"], 1),
|
343 |
|
344 | funcName: { value: [0x43414d4b], binLen: 32 },
|
345 | customization: parseInputOption("Customization", resolvedOptions["customization"], 1, { value: [], binLen: 0 }),
|
346 | };
|
347 | }
|
348 |
|
349 | export default class jsSHA extends jsSHABase<Int_64[][], VariantType> {
|
350 | intermediateState: Int_64[][];
|
351 | variantBlockSize: number;
|
352 | bigEndianMod: -1 | 1;
|
353 | outputBinLen: number;
|
354 | isVariableLen: boolean;
|
355 | HMACSupported: boolean;
|
356 |
|
357 |
|
358 | converterFunc: (input: any, existingBin: number[], existingBinLen: number) => packedValue;
|
359 | roundFunc: (block: number[], H: Int_64[][]) => Int_64[][];
|
360 | finalizeFunc: (
|
361 | remainder: number[],
|
362 | remainderBinLen: number,
|
363 | processedBinLen: number,
|
364 | H: Int_64[][],
|
365 | outputLen: number
|
366 | ) => number[];
|
367 | stateCloneFunc: (state: Int_64[][]) => Int_64[][];
|
368 | newStateFunc: (variant: VariantType) => Int_64[][];
|
369 | getMAC: ((options: { outputLen: number }) => number[]) | null;
|
370 |
|
371 | constructor(variant: FixedLengthVariantType, inputFormat: "TEXT", options?: FixedLengthOptionsEncodingType);
|
372 | constructor(
|
373 | variant: FixedLengthVariantType,
|
374 | inputFormat: FormatNoTextType,
|
375 | options?: FixedLengthOptionsNoEncodingType
|
376 | );
|
377 | constructor(variant: "SHAKE128" | "SHAKE256", inputFormat: "TEXT", options?: SHAKEOptionsEncodingType);
|
378 | constructor(variant: "SHAKE128" | "SHAKE256", inputFormat: FormatNoTextType, options?: SHAKEOptionsNoEncodingType);
|
379 | constructor(variant: "CSHAKE128" | "CSHAKE256", inputFormat: "TEXT", options?: CSHAKEOptionsEncodingType);
|
380 | constructor(variant: "CSHAKE128" | "CSHAKE256", inputFormat: FormatNoTextType, options?: CSHAKEOptionsNoEncodingType);
|
381 | constructor(variant: "KMAC128" | "KMAC256", inputFormat: "TEXT", options: KMACOptionsEncodingType);
|
382 | constructor(variant: "KMAC128" | "KMAC256", inputFormat: FormatNoTextType, options: KMACOptionsNoEncodingType);
|
383 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
384 | constructor(variant: any, inputFormat: any, options?: any) {
|
385 | let delimiter = 0x06,
|
386 | variantBlockSize = 0;
|
387 | super(variant, inputFormat, options);
|
388 | const resolvedOptions = options || {};
|
389 |
|
390 | /* In other variants, this was done after variable initialization but need to do it earlier here becaue we want to
|
391 | avoid KMAC initialization */
|
392 | if (this.numRounds !== 1) {
|
393 | if (resolvedOptions["kmacKey"] || resolvedOptions["hmacKey"]) {
|
394 | throw new Error(mac_rounds_error);
|
395 | } else if (this.shaVariant === "CSHAKE128" || this.shaVariant === "CSHAKE256") {
|
396 | throw new Error("Cannot set numRounds for CSHAKE variants");
|
397 | }
|
398 | }
|
399 |
|
400 | this.bigEndianMod = 1;
|
401 | this.converterFunc = getStrConverter(this.inputFormat, this.utfType, this.bigEndianMod);
|
402 | this.roundFunc = roundSHA3;
|
403 | this.stateCloneFunc = cloneSHA3State;
|
404 | this.newStateFunc = getNewState;
|
405 | this.intermediateState = getNewState(variant);
|
406 |
|
407 | this.isVariableLen = false;
|
408 | switch (variant) {
|
409 | case "SHA3-224":
|
410 | this.variantBlockSize = variantBlockSize = 1152;
|
411 | this.outputBinLen = 224;
|
412 | this.HMACSupported = true;
|
413 | // eslint-disable-next-line @typescript-eslint/unbound-method
|
414 | this.getMAC = this._getHMAC;
|
415 | break;
|
416 | case "SHA3-256":
|
417 | this.variantBlockSize = variantBlockSize = 1088;
|
418 | this.outputBinLen = 256;
|
419 | this.HMACSupported = true;
|
420 | // eslint-disable-next-line @typescript-eslint/unbound-method
|
421 | this.getMAC = this._getHMAC;
|
422 | break;
|
423 | case "SHA3-384":
|
424 | this.variantBlockSize = variantBlockSize = 832;
|
425 | this.outputBinLen = 384;
|
426 | this.HMACSupported = true;
|
427 | // eslint-disable-next-line @typescript-eslint/unbound-method
|
428 | this.getMAC = this._getHMAC;
|
429 | break;
|
430 | case "SHA3-512":
|
431 | this.variantBlockSize = variantBlockSize = 576;
|
432 | this.outputBinLen = 512;
|
433 | this.HMACSupported = true;
|
434 | // eslint-disable-next-line @typescript-eslint/unbound-method
|
435 | this.getMAC = this._getHMAC;
|
436 | break;
|
437 | case "SHAKE128":
|
438 | delimiter = 0x1f;
|
439 | this.variantBlockSize = variantBlockSize = 1344;
|
440 | /* This will be set in getHash */
|
441 | this.outputBinLen = -1;
|
442 | this.isVariableLen = true;
|
443 | this.HMACSupported = false;
|
444 | this.getMAC = null;
|
445 | break;
|
446 | case "SHAKE256":
|
447 | delimiter = 0x1f;
|
448 | this.variantBlockSize = variantBlockSize = 1088;
|
449 | /* This will be set in getHash */
|
450 | this.outputBinLen = -1;
|
451 | this.isVariableLen = true;
|
452 | this.HMACSupported = false;
|
453 | this.getMAC = null;
|
454 | break;
|
455 | case "KMAC128":
|
456 | delimiter = 0x4;
|
457 | this.variantBlockSize = variantBlockSize = 1344;
|
458 | this._initializeKMAC(options);
|
459 | /* This will be set in getHash */
|
460 | this.outputBinLen = -1;
|
461 | this.isVariableLen = true;
|
462 | this.HMACSupported = false;
|
463 | // eslint-disable-next-line @typescript-eslint/unbound-method
|
464 | this.getMAC = this._getKMAC;
|
465 | break;
|
466 | case "KMAC256":
|
467 | delimiter = 0x4;
|
468 | this.variantBlockSize = variantBlockSize = 1088;
|
469 | this._initializeKMAC(options);
|
470 | /* This will be set in getHash */
|
471 | this.outputBinLen = -1;
|
472 | this.isVariableLen = true;
|
473 | this.HMACSupported = false;
|
474 | // eslint-disable-next-line @typescript-eslint/unbound-method
|
475 | this.getMAC = this._getKMAC;
|
476 | break;
|
477 | case "CSHAKE128":
|
478 | this.variantBlockSize = variantBlockSize = 1344;
|
479 | delimiter = this._initializeCSHAKE(options);
|
480 | /* This will be set in getHash */
|
481 | this.outputBinLen = -1;
|
482 | this.isVariableLen = true;
|
483 | this.HMACSupported = false;
|
484 | this.getMAC = null;
|
485 | break;
|
486 | case "CSHAKE256":
|
487 | this.variantBlockSize = variantBlockSize = 1088;
|
488 | delimiter = this._initializeCSHAKE(options);
|
489 | /* This will be set in getHash */
|
490 | this.outputBinLen = -1;
|
491 | this.isVariableLen = true;
|
492 | this.HMACSupported = false;
|
493 | this.getMAC = null;
|
494 | break;
|
495 | default:
|
496 | throw new Error(sha_variant_error);
|
497 | }
|
498 |
|
499 | /* This needs to be down here as CSHAKE can change its delimiter */
|
500 | this.finalizeFunc = function (remainder, remainderBinLen, processedBinLen, state, outputBinLen): number[] {
|
501 | return finalizeSHA3(
|
502 | remainder,
|
503 | remainderBinLen,
|
504 | processedBinLen,
|
505 | state,
|
506 | variantBlockSize,
|
507 | delimiter,
|
508 | outputBinLen
|
509 | );
|
510 | };
|
511 |
|
512 | if (resolvedOptions["hmacKey"]) {
|
513 | this._setHMACKey(parseInputOption("hmacKey", resolvedOptions["hmacKey"], this.bigEndianMod));
|
514 | }
|
515 | }
|
516 |
|
517 | /**
|
518 | * Initialize CSHAKE variants.
|
519 | *
|
520 | * @param options Options containing CSHAKE params.
|
521 | * @param funcNameOverride Overrides any "funcName" present in `options` (used with KMAC)
|
522 | * @returns The delimiter to be used
|
523 | */
|
524 | protected _initializeCSHAKE(options?: CSHAKEOptionsNoEncodingType, funcNameOverride?: packedValue): number {
|
525 | const resolvedOptions = resolveCSHAKEOptions(options || {});
|
526 | if (funcNameOverride) {
|
527 | resolvedOptions["funcName"] = funcNameOverride;
|
528 | }
|
529 | const packedParams = packedLEConcat(
|
530 | encode_string(resolvedOptions["funcName"]),
|
531 | encode_string(resolvedOptions["customization"])
|
532 | );
|
533 |
|
534 | /* CSHAKE is defined to be a call to SHAKE iff both the customization and function-name string are both empty. This
|
535 | can be accomplished by processing nothing in this step. */
|
536 | if (resolvedOptions["customization"]["binLen"] !== 0 || resolvedOptions["funcName"]["binLen"] !== 0) {
|
537 | const byte_pad_out = byte_pad(packedParams, this.variantBlockSize >>> 3);
|
538 | for (let i = 0; i < byte_pad_out.length; i += this.variantBlockSize >>> 5) {
|
539 | this.intermediateState = this.roundFunc(
|
540 | byte_pad_out.slice(i, i + (this.variantBlockSize >>> 5)),
|
541 | this.intermediateState
|
542 | );
|
543 | this.processedLen += this.variantBlockSize;
|
544 | }
|
545 | return 0x04;
|
546 | } else {
|
547 | return 0x1f;
|
548 | }
|
549 | }
|
550 |
|
551 | /**
|
552 | * Initialize KMAC variants.
|
553 | *
|
554 | * @param options Options containing KMAC params.
|
555 | */
|
556 | protected _initializeKMAC(options: KMACOptionsNoEncodingType): void {
|
557 | const resolvedOptions = resolveKMACOptions(options || {});
|
558 |
|
559 | this._initializeCSHAKE(options, resolvedOptions["funcName"]);
|
560 | const byte_pad_out = byte_pad(encode_string(resolvedOptions["kmacKey"]), this.variantBlockSize >>> 3);
|
561 | for (let i = 0; i < byte_pad_out.length; i += this.variantBlockSize >>> 5) {
|
562 | this.intermediateState = this.roundFunc(
|
563 | byte_pad_out.slice(i, i + (this.variantBlockSize >>> 5)),
|
564 | this.intermediateState
|
565 | );
|
566 | this.processedLen += this.variantBlockSize;
|
567 | }
|
568 | this.macKeySet = true;
|
569 | }
|
570 |
|
571 | /**
|
572 | * Returns the the KMAC in the specified format.
|
573 | *
|
574 | * @param options Hashmap of extra outputs options. `outputLen` must be specified.
|
575 | * @returns The KMAC in the format specified.
|
576 | */
|
577 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
578 | protected _getKMAC(options: { outputLen: number }): number[] {
|
579 | const concatedRemainder = packedLEConcat(
|
580 | { value: this.remainder.slice(), binLen: this.remainderLen },
|
581 | right_encode(options["outputLen"])
|
582 | );
|
583 |
|
584 | return this.finalizeFunc(
|
585 | concatedRemainder["value"],
|
586 | concatedRemainder["binLen"],
|
587 | this.processedLen,
|
588 | this.stateCloneFunc(this.intermediateState),
|
589 | options["outputLen"]
|
590 | );
|
591 | }
|
592 | }
|
593 |
|
\ | No newline at end of file |