Skip to content

Commit

Permalink
Merge pull request #93 from nibble-4bits/refactor-18
Browse files Browse the repository at this point in the history
Refactor 18
  • Loading branch information
nibble-4bits authored May 28, 2024
2 parents 7d769bc + 5993770 commit 6d8317a
Show file tree
Hide file tree
Showing 17 changed files with 2,279 additions and 1,422 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pr-run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16'
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run tests
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/prepare-for-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16'
node-version: '18'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16'
node-version: '18'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion __tests__/intrinsicFunctions/StatesHash.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ describe('States.Hash intrinsic function', () => {
expect(funcCallWrapper).toThrow(StatesRuntimeError);
});

test('should throw error if passed hashing algorithm is not one of the supported algorithms', () => {
test('should throw error if passed hash algorithm is not one of the supported algorithms', () => {
const func = new StatesHash();
const input = {};
const context = {};
Expand Down
2,805 changes: 1,419 additions & 1,386 deletions package-lock.json

Large diffs are not rendered by default.

27 changes: 13 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,32 +46,31 @@
"scripts": {
"test": "jest",
"build": "tsup && rm build/main.d.cts",
"build:watch": "tsup --watch",
"prettier": "prettier --check \"src/**/*.ts\"",
"prettier:fix": "prettier --write \"src/**/*.ts\"",
"lint": "eslint \"src/**/*.ts\"",
"lint:fix": "eslint --fix \"src/**/*.ts\""
},
"devDependencies": {
"@types/crypto-js": "^4.2.1",
"@types/jest": "^29.5.11",
"@types/lodash": "^4.14.202",
"@types/node": "^18.19.3",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
"eslint": "^8.56.0",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.17.4",
"@types/node": "^18.19.33",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"prettier": "^3.2.4",
"ts-jest": "^29.1.1",
"tsup": "^8.0.1",
"typescript": "^5.3.3"
"prettier": "^3.2.5",
"ts-jest": "^29.1.3",
"tsup": "^8.0.2",
"typescript": "^5.4.5"
},
"dependencies": {
"@aws-sdk/client-lambda": "^3.481.0",
"@aws-sdk/credential-providers": "^3.481.0",
"@aws-sdk/client-lambda": "^3.583.0",
"@aws-sdk/credential-providers": "^3.583.0",
"asl-validator": "^3.8.2",
"commander": "^11.1.0",
"crypto-js": "^4.2.0",
"jsonpath-plus": "^7.2.0",
"lodash": "^4.17.21",
"p-limit": "^3.1.0",
Expand Down
2 changes: 1 addition & 1 deletion src/stateMachine/StateExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export class StateExecutor {
nextState,
isEndState,
} = await this.stateHandlers[this.stateDefinition.Type](
// @ts-expect-error Indexing `this.stateActions` by non-literal value produces a `never` type for the `this.stateDefinition` parameter of the handler being called
// @ts-expect-error Indexing `this.stateHandlers` by non-literal value produces a `never` type for the `this.stateDefinition` parameter of the handler being called
this.stateDefinition,
rawInput,
processedInput,
Expand Down
24 changes: 10 additions & 14 deletions src/stateMachine/intrinsicFunctions/StatesHash.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import type { IntrinsicFunctionDefinition } from '../../typings/IntrinsicFunctionsImplementation';
import type { HashingAlgorithm } from '../../typings/IntrinsicFunctions';
import type { HashAlgorithm } from '../../typings/IntrinsicFunctions';
import type { JSONValue } from '../../typings/JSONValue';
import { StatesRuntimeError } from '../../error/predefined/StatesRuntimeError';
import { BaseIntrinsicFunction } from './BaseIntrinsicFunction';
import md5 from 'crypto-js/md5.js';
import sha1 from 'crypto-js/sha1.js';
import sha256 from 'crypto-js/sha256.js';
import sha384 from 'crypto-js/sha384.js';
import sha512 from 'crypto-js/sha512.js';
import { md5, sha1, sha256, sha384, sha512 } from '../../util/hash';

class StatesHash extends BaseIntrinsicFunction {
protected readonly funcDefinition: IntrinsicFunctionDefinition;
Expand All @@ -29,32 +25,32 @@ class StatesHash extends BaseIntrinsicFunction {
};
}

protected execute(str: string, algorithm: HashingAlgorithm): JSONValue {
protected execute(str: string, algorithm: HashAlgorithm): JSONValue {
if (str.length > 10000) {
throw new StatesRuntimeError(
`Intrinsic function ${this.funcDefinition.name} cannot hash a string with more than 10,000 characters`
);
}

const algorithms: HashingAlgorithm[] = ['MD5', 'SHA-1', 'SHA-256', 'SHA-384', 'SHA-512'];
const algorithms: HashAlgorithm[] = ['MD5', 'SHA-1', 'SHA-256', 'SHA-384', 'SHA-512'];
const supportedAlgorithms = algorithms.join(', ');
if (!algorithms.includes(algorithm)) {
throw new StatesRuntimeError(
`Unsupported hashing algorithm provided to intrinsic function ${this.funcDefinition.name}. The supported algorithms are: ${supportedAlgorithms}`
`Unsupported hash algorithm '${algorithm}' provided to intrinsic function ${this.funcDefinition.name}. The supported algorithms are: ${supportedAlgorithms}`
);
}

switch (algorithm) {
case 'MD5':
return md5(str).toString();
return md5.getDigest(str);
case 'SHA-1':
return sha1(str).toString();
return sha1.getDigest(str);
case 'SHA-256':
return sha256(str).toString();
return sha256.getDigest(str);
case 'SHA-384':
return sha384(str).toString();
return sha384.getDigest(str);
case 'SHA-512':
return sha512(str).toString();
return sha512.getDigest(str);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/typings/IntrinsicFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ export type IntrinsicFunctionName =
| 'States.StringSplit'
| 'States.UUID';

export type HashingAlgorithm = 'MD5' | 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512';
export type HashAlgorithm = 'MD5' | 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512';
11 changes: 11 additions & 0 deletions src/util/hash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { MD5 } from './hash/MD5';
import { SHA1 } from './hash/SHA1';
import { SHA256 } from './hash/SHA256';
import { SHA384 } from './hash/SHA384';
import { SHA512 } from './hash/SHA512';

export const md5 = new MD5();
export const sha1 = new SHA1();
export const sha256 = new SHA256();
export const sha384 = new SHA384();
export const sha512 = new SHA512();
125 changes: 125 additions & 0 deletions src/util/hash/BaseHash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// TypeScript's DOM library has to be referenced for `TextEncoder` to be recognized as a type
/// <reference lib="dom" />

export abstract class BaseHashAlgorithm {
private textEncoder: TextEncoder;

constructor() {
this.textEncoder = new TextEncoder();
}

getDigest(input: string): string {
const message = this.textEncoder.encode(input);

const paddedMessage = this.padMessage(message);
const hash = this.computeHash(paddedMessage);
const digest = this.hashToString(hash);

return digest;
}

protected abstract padMessage(message: Uint8Array): ArrayBuffer;

protected abstract computeHash(paddedMessage: ArrayBuffer): ArrayBuffer;

protected abstract hashToString(hash: ArrayBuffer): string;

protected rotl(n: number, x: number): number;
protected rotl(n: bigint, x: bigint): bigint;
protected rotl(n: number | bigint, x: number | bigint): number | bigint {
if (typeof n === 'number' && typeof x === 'number') return (x << n) | (x >>> (32 - n));
if (typeof n === 'bigint' && typeof x === 'bigint') return (x << n) | (x >> (64n - n));

throw new Error('Both arguments must be of the same type');
}

protected rotr(n: number, x: number): number;
protected rotr(n: bigint, x: bigint): bigint;
protected rotr(n: number | bigint, x: number | bigint): number | bigint {
if (typeof n === 'number' && typeof x === 'number') return (x >>> n) | (x << (32 - n));
if (typeof n === 'bigint' && typeof x === 'bigint') return (x >> n) | (x << (64n - n));

throw new Error('Both arguments must be of the same type');
}

protected ch(x: number, y: number, z: number): number;
protected ch(x: bigint, y: bigint, z: bigint): bigint;
protected ch(x: number | bigint, y: number | bigint, z: number | bigint): number | bigint {
if (typeof x === typeof y && typeof y === typeof z) {
// @ts-expect-error TypeScript can't disambiguate between number and bigint
return (x & y) ^ (~x & z);
}

throw new Error('All arguments must be of the same type');
}

protected parity(x: number, y: number, z: number): number;
protected parity(x: bigint, y: bigint, z: bigint): bigint;
protected parity(x: number | bigint, y: number | bigint, z: number | bigint): number | bigint {
if (typeof x === typeof y && typeof y === typeof z) {
// @ts-expect-error TypeScript can't disambiguate between number and bigint
return x ^ y ^ z;
}

throw new Error('All arguments must be of the same type');
}

protected maj(x: number, y: number, z: number): number;
protected maj(x: bigint, y: bigint, z: bigint): bigint;
protected maj(x: number | bigint, y: number | bigint, z: number | bigint): number | bigint {
if (typeof x === typeof y && typeof y === typeof z) {
// @ts-expect-error TypeScript can't disambiguate between number and bigint
return (x & y) ^ (x & z) ^ (y & z);
}

throw new Error('All arguments must be of the same type');
}

protected bigSigma0(x: number): number;
protected bigSigma0(x: bigint): bigint;
protected bigSigma0(x: number | bigint): number | bigint {
if (typeof x === 'number') {
// number version used by SHA1 and SHA256
return this.rotr(2, x) ^ this.rotr(13, x) ^ this.rotr(22, x);
}

// BigInt version used by SHA384 and SHA512
return this.rotr(28n, x) ^ this.rotr(34n, x) ^ this.rotr(39n, x);
}

protected bigSigma1(x: number): number;
protected bigSigma1(x: bigint): bigint;
protected bigSigma1(x: number | bigint): number | bigint {
if (typeof x === 'number') {
// number version used by SHA1 and SHA256
return this.rotr(6, x) ^ this.rotr(11, x) ^ this.rotr(25, x);
}

// BigInt version used by SHA384 and SHA512
return this.rotr(14n, x) ^ this.rotr(18n, x) ^ this.rotr(41n, x);
}

protected smallSigma0(x: number): number;
protected smallSigma0(x: bigint): bigint;
protected smallSigma0(x: number | bigint): number | bigint {
if (typeof x === 'number') {
// number version used by SHA1 and SHA256
return this.rotr(7, x) ^ this.rotr(18, x) ^ (x >>> 3);
}

// BigInt version used by SHA384 and SHA512
return this.rotr(1n, x) ^ this.rotr(8n, x) ^ (x >> 7n);
}

protected smallSigma1(x: number): number;
protected smallSigma1(x: bigint): bigint;
protected smallSigma1(x: number | bigint): number | bigint {
if (typeof x === 'number') {
// number version used by SHA1 and SHA256
return this.rotr(17, x) ^ this.rotr(19, x) ^ (x >>> 10);
}

// BigInt version used by SHA384 and SHA512
return this.rotr(19n, x) ^ this.rotr(61n, x) ^ (x >> 6n);
}
}
Loading

0 comments on commit 6d8317a

Please sign in to comment.