From 509647931b72dcabd905bfa8a3bf054eabf87950 Mon Sep 17 00:00:00 2001 From: Dan Armbrust Date: Fri, 22 Apr 2022 21:17:48 -0500 Subject: [PATCH 1/2] replace hash routine md5 with sha256 swapping out the md5 hash routine with sha256 (truncated to 32 chars) and base64url encoded. this allows jest to run on a system where openssl is in a fips enabled mode. --- packages/babel-jest/src/index.ts | 5 +++-- .../jest-circus/src/__mocks__/testUtils.ts | 5 ++++- .../src/__tests__/normalize.test.ts | 5 +++-- packages/jest-config/src/normalize.ts | 5 +++-- .../src/index.ts | 10 ++++++---- packages/jest-haste-map/src/index.ts | 12 ++++++++--- .../jest-transform/src/ScriptTransformer.ts | 20 +++++++++++++------ 7 files changed, 42 insertions(+), 20 deletions(-) diff --git a/packages/babel-jest/src/index.ts b/packages/babel-jest/src/index.ts index e4ac550eaf14..da93a3c4cecf 100644 --- a/packages/babel-jest/src/index.ts +++ b/packages/babel-jest/src/index.ts @@ -78,7 +78,7 @@ function getCacheKeyFromConfig( const configPath = [babelOptions.config || '', babelOptions.babelrc || '']; - return createHash('md5') + return createHash('sha256') .update(THIS_FILE) .update('\0', 'utf8') .update(JSON.stringify(babelOptions.options)) @@ -98,7 +98,8 @@ function getCacheKeyFromConfig( .update(process.env.BABEL_ENV || '') .update('\0', 'utf8') .update(process.version) - .digest('hex'); + .digest('hex') + .substring(0, 32); } function loadBabelConfig( diff --git a/packages/jest-circus/src/__mocks__/testUtils.ts b/packages/jest-circus/src/__mocks__/testUtils.ts index 52557f72fcb8..300159fd3e71 100644 --- a/packages/jest-circus/src/__mocks__/testUtils.ts +++ b/packages/jest-circus/src/__mocks__/testUtils.ts @@ -31,7 +31,10 @@ interface Result extends ExecaSyncReturnValue { } export const runTest = (source: string) => { - const filename = createHash('md5').update(source).digest('hex'); + const filename = createHash('sha256') + .update(source) + .digest('hex') + .substring(0, 32); const tmpFilename = path.join(tmpdir(), filename); const content = ` diff --git a/packages/jest-config/src/__tests__/normalize.test.ts b/packages/jest-config/src/__tests__/normalize.test.ts index 1fc435b0ecfb..a480b4b4229e 100644 --- a/packages/jest-config/src/__tests__/normalize.test.ts +++ b/packages/jest-config/src/__tests__/normalize.test.ts @@ -68,10 +68,11 @@ afterEach(() => { it('picks an id based on the rootDir', async () => { const rootDir = '/root/path/foo'; - const expected = createHash('md5') + const expected = createHash('sha256') .update('/root/path/foo') .update(String(Infinity)) - .digest('hex'); + .digest('hex') + .substring(0, 32); const {options} = await normalize( { rootDir, diff --git a/packages/jest-config/src/normalize.ts b/packages/jest-config/src/normalize.ts index d2fc5ade328e..0086b64ec97f 100644 --- a/packages/jest-config/src/normalize.ts +++ b/packages/jest-config/src/normalize.ts @@ -333,12 +333,13 @@ const normalizeMissingOptions = ( projectIndex: number, ): Config.InitialOptionsWithRootDir => { if (!options.id) { - options.id = createHash('md5') + options.id = createHash('sha256') .update(options.rootDir) // In case we load config from some path that has the same root dir .update(configPath || '') .update(String(projectIndex)) - .digest('hex'); + .digest('hex') + .substring(0, 32); } if (!options.setupFiles) { diff --git a/packages/jest-create-cache-key-function/src/index.ts b/packages/jest-create-cache-key-function/src/index.ts index 8f1a6f1eed80..835edc088885 100644 --- a/packages/jest-create-cache-key-function/src/index.ts +++ b/packages/jest-create-cache-key-function/src/index.ts @@ -49,9 +49,10 @@ function getGlobalCacheKey(files: Array, values: Array) { ] .reduce( (hash, chunk) => hash.update('\0', 'utf8').update(chunk || ''), - createHash('md5'), + createHash('sha256'), ) - .digest('hex'); + .digest('hex') + .substring(0, 32); } function getCacheKeyFunction(globalCacheKey: string): GetCacheKeyFunction { @@ -61,7 +62,7 @@ function getCacheKeyFunction(globalCacheKey: string): GetCacheKeyFunction { const inferredOptions = options || configString; const {config, instrument} = inferredOptions; - return createHash('md5') + return createHash('sha256') .update(globalCacheKey) .update('\0', 'utf8') .update(sourceText) @@ -69,7 +70,8 @@ function getCacheKeyFunction(globalCacheKey: string): GetCacheKeyFunction { .update(config.rootDir ? relative(config.rootDir, sourcePath) : '') .update('\0', 'utf8') .update(instrument ? 'instrument' : '') - .digest('hex'); + .digest('hex') + .substring(0, 32); }; } diff --git a/packages/jest-haste-map/src/index.ts b/packages/jest-haste-map/src/index.ts index a203bea0a845..f3762703050c 100644 --- a/packages/jest-haste-map/src/index.ts +++ b/packages/jest-haste-map/src/index.ts @@ -298,7 +298,10 @@ export default class HasteMap extends EventEmitter { } private async setupCachePath(options: Options): Promise { - const rootDirHash = createHash('md5').update(options.rootDir).digest('hex'); + const rootDirHash = createHash('sha256') + .update(options.rootDir) + .digest('hex') + .substring(0, 32); let hasteImplHash = ''; let dependencyExtractorHash = ''; @@ -344,8 +347,11 @@ export default class HasteMap extends EventEmitter { id: string, ...extra: Array ): string { - const hash = createHash('md5').update(extra.join('')); - return path.join(tmpdir, `${id.replace(/\W/g, '-')}-${hash.digest('hex')}`); + const hash = createHash('sha256').update(extra.join('')); + return path.join( + tmpdir, + `${id.replace(/\W/g, '-')}-${hash.digest('hex').substring(0, 32)}`, + ); } static getModuleMapFromJSON(json: SerializableModuleMap): HasteModuleMap { diff --git a/packages/jest-transform/src/ScriptTransformer.ts b/packages/jest-transform/src/ScriptTransformer.ts index 1c78f616f4bc..fc674e22ebac 100644 --- a/packages/jest-transform/src/ScriptTransformer.ts +++ b/packages/jest-transform/src/ScriptTransformer.ts @@ -116,19 +116,21 @@ class ScriptTransformer { transformerCacheKey: string | undefined, ): string { if (transformerCacheKey) { - return createHash('md5') + return createHash('sha256') .update(transformerCacheKey) .update(CACHE_VERSION) - .digest('hex'); + .digest('hex') + .substring(0, 32); } - return createHash('md5') + return createHash('sha256') .update(fileData) .update(transformOptions.configString) .update(transformOptions.instrument ? 'instrument' : '') .update(filename) .update(CACHE_VERSION) - .digest('hex'); + .digest('hex') + .substring(0, 32); } private _getCacheKey( @@ -869,7 +871,10 @@ const stripShebang = (content: string) => { * could get corrupted, out-of-sync, etc. */ function writeCodeCacheFile(cachePath: string, code: string) { - const checksum = createHash('md5').update(code).digest('hex'); + const checksum = createHash('sha256') + .update(code) + .digest('hex') + .substring(0, 32); writeCacheFile(cachePath, `${checksum}\n${code}`); } @@ -885,7 +890,10 @@ function readCodeCacheFile(cachePath: string): string | null { return null; } const code = content.substring(33); - const checksum = createHash('md5').update(code).digest('hex'); + const checksum = createHash('sha256') + .update(code) + .digest('hex') + .substring(0, 32); if (checksum === content.substring(0, 32)) { return code; } From 6eb9d165992fd771eefe0345e4774493aa90a0fd Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 25 Apr 2022 08:39:08 +0200 Subject: [PATCH 2/2] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 913b7572a4d3..2a6ab7f87d59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ ### Fixes +- `[*]` Use `sha256` instead of `md5` as hashing algortihm for compatibility with FIPS systems ([#12722](https://github.com/facebook/jest/pull/12722)) - `[babel-jest]` [**BREAKING**] Pass `rootDir` as `root` in Babel's options ([#12689](https://github.com/facebook/jest/pull/12689)) - `[expect]` Move typings of `.not`, `.rejects` and `.resolves` modifiers outside of `Matchers` interface ([#12346](https://github.com/facebook/jest/pull/12346)) - `[expect]` Throw useful error if `expect.extend` is called with invalid matchers ([#12488](https://github.com/facebook/jest/pull/12488))