mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-09 22:24:05 -08:00
feat(core): Remove discontinued crypto-js (#8104)
Since crypto-js was
[discontinued](1da3dabf93
),
[we migrated all our backend encryption to native
crypto](https://github.com/n8n-io/n8n/pull/7556).
However I decided back then to not remove crypto-js just yet in
expressions, as I wanted to use `SubtleCrypto`. Unfortunately for that
to work, we'd need to make expressions async.
So, to get rid of `crypto-js`, I propose this interim solution.
## Related tickets and issues
N8N-7020
## Review / Merge checklist
- [x] PR title and summary are descriptive
- [x] Tests included
This commit is contained in:
parent
b67b5ae6b2
commit
01e9a79238
|
@ -2,6 +2,17 @@
|
|||
|
||||
This list shows all the versions which include breaking changes and how to upgrade.
|
||||
|
||||
## 1.22.0
|
||||
|
||||
### What changed?
|
||||
|
||||
Hash algorithm `ripemd160` is dropped from `.hash()` expressions.
|
||||
`sha3` hash algorithm now returns a valid sha3-512 has, unlike the previous implementation that returned a `Keccak` hash instead.
|
||||
|
||||
### When is action necessary?
|
||||
|
||||
If you are using `.hash` helpers in expressions with hash algorithm `ripemd160`, you need to switch to one of the other supported algorithms.
|
||||
|
||||
## 1.15.0
|
||||
|
||||
### What changed?
|
||||
|
|
|
@ -39,12 +39,12 @@
|
|||
"dist/**/*"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/crypto-js": "^4.1.3",
|
||||
"@types/deep-equal": "^1.0.1",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/jmespath": "^0.15.0",
|
||||
"@types/lodash": "^4.14.195",
|
||||
"@types/luxon": "^3.2.0",
|
||||
"@types/md5": "^2.3.5",
|
||||
"@types/xml2js": "^0.4.11"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -52,14 +52,15 @@
|
|||
"@n8n_io/riot-tmpl": "4.0.0",
|
||||
"ast-types": "0.15.2",
|
||||
"callsites": "3.1.0",
|
||||
"crypto-js": "4.2.0",
|
||||
"deep-equal": "2.2.0",
|
||||
"esprima-next": "5.8.4",
|
||||
"form-data": "4.0.0",
|
||||
"jmespath": "0.16.0",
|
||||
"js-base64": "3.7.2",
|
||||
"jssha": "3.3.1",
|
||||
"lodash": "4.17.21",
|
||||
"luxon": "3.3.0",
|
||||
"md5": "2.3.0",
|
||||
"recast": "0.21.5",
|
||||
"title-case": "3.0.3",
|
||||
"transliteration": "2.3.5",
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
// import { createHash } from 'crypto';
|
||||
import SHA from 'jssha';
|
||||
import MD5 from 'md5';
|
||||
import { encode } from 'js-base64';
|
||||
import { titleCase } from 'title-case';
|
||||
import type { ExtensionMap } from './Extensions';
|
||||
import CryptoJS from 'crypto-js';
|
||||
import { encode } from 'js-base64';
|
||||
import { transliterate } from 'transliteration';
|
||||
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
||||
|
||||
const hashFunctions: Record<string, typeof CryptoJS.MD5> = {
|
||||
md5: CryptoJS.MD5,
|
||||
sha1: CryptoJS.SHA1,
|
||||
sha224: CryptoJS.SHA224,
|
||||
sha256: CryptoJS.SHA256,
|
||||
sha384: CryptoJS.SHA384,
|
||||
sha512: CryptoJS.SHA512,
|
||||
sha3: CryptoJS.SHA3,
|
||||
ripemd160: CryptoJS.RIPEMD160,
|
||||
};
|
||||
export const SupportedHashAlgorithms = [
|
||||
'md5',
|
||||
'sha1',
|
||||
'sha224',
|
||||
'sha256',
|
||||
'sha384',
|
||||
'sha512',
|
||||
'sha3',
|
||||
] as const;
|
||||
|
||||
// All symbols from https://www.xe.com/symbols/ as for 2022/11/09
|
||||
const CURRENCY_REGEXP =
|
||||
|
@ -113,23 +112,35 @@ const URL_REGEXP =
|
|||
const CHAR_TEST_REGEXP = /\p{L}/u;
|
||||
const PUNC_TEST_REGEXP = /[!?.]/;
|
||||
|
||||
function hash(value: string, extraArgs?: unknown): string {
|
||||
const [algorithm = 'MD5'] = extraArgs as string[];
|
||||
if (algorithm.toLowerCase() === 'base64') {
|
||||
// We're using a library instead of btoa because btoa only
|
||||
// works on ASCII
|
||||
return encode(value);
|
||||
function hash(value: string, extraArgs: string[]): string {
|
||||
const algorithm = extraArgs[0]?.toLowerCase() ?? 'md5';
|
||||
switch (algorithm) {
|
||||
case 'base64':
|
||||
return encode(value);
|
||||
case 'md5':
|
||||
return MD5(value);
|
||||
case 'sha1':
|
||||
case 'sha224':
|
||||
case 'sha256':
|
||||
case 'sha384':
|
||||
case 'sha512':
|
||||
case 'sha3':
|
||||
const variant = (
|
||||
{
|
||||
sha1: 'SHA-1',
|
||||
sha224: 'SHA-224',
|
||||
sha256: 'SHA-256',
|
||||
sha384: 'SHA-384',
|
||||
sha512: 'SHA-512',
|
||||
sha3: 'SHA3-512',
|
||||
} as const
|
||||
)[algorithm];
|
||||
return new SHA(variant, 'TEXT').update(value).getHash('HEX');
|
||||
default:
|
||||
throw new ExpressionExtensionError(
|
||||
`Unknown algorithm ${algorithm}. Available algorithms are: ${SupportedHashAlgorithms.join()}, and Base64.`,
|
||||
);
|
||||
}
|
||||
const hashFunction = hashFunctions[algorithm.toLowerCase()];
|
||||
if (!hashFunction) {
|
||||
throw new ExpressionExtensionError(
|
||||
`Unknown algorithm ${algorithm}. Available algorithms are: ${Object.keys(hashFunctions)
|
||||
.map((s) => s.toUpperCase())
|
||||
.join(', ')}, and Base64.`,
|
||||
);
|
||||
}
|
||||
return hashFunction(value.toString()).toString();
|
||||
// return createHash(format).update(value.toString()).digest('hex');
|
||||
}
|
||||
|
||||
function isEmpty(value: string): boolean {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
|
||||
import { stringExtensions } from '@/Extensions/StringExtensions';
|
||||
import { evaluate } from './Helpers';
|
||||
|
||||
describe('Data Transformation Functions', () => {
|
||||
|
@ -15,28 +13,28 @@ describe('Data Transformation Functions', () => {
|
|||
expect(evaluate('={{"".isEmpty()}}')).toEqual(true);
|
||||
});
|
||||
|
||||
test('.hash() should work correctly on a string', () => {
|
||||
expect(evaluate('={{ "12345".hash("sha256") }}')).toEqual(
|
||||
stringExtensions.functions.hash('12345', ['sha256']),
|
||||
);
|
||||
|
||||
expect(evaluate('={{ "12345".hash("sha256") }}')).not.toEqual(
|
||||
stringExtensions.functions.hash('12345', ['MD5']),
|
||||
);
|
||||
|
||||
expect(evaluate('={{ "12345".hash("MD5") }}')).toEqual(
|
||||
stringExtensions.functions.hash('12345', ['MD5']),
|
||||
);
|
||||
|
||||
expect(evaluate('={{ "12345".hash("sha256") }}')).toEqual(
|
||||
'5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5',
|
||||
);
|
||||
});
|
||||
|
||||
test('.hash() alias should work correctly on a string', () => {
|
||||
expect(evaluate('={{ "12345".hash("sha256") }}')).toEqual(
|
||||
'5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5',
|
||||
);
|
||||
describe('.hash()', () => {
|
||||
test.each([
|
||||
['md5', '827ccb0eea8a706c4c34a16891f84e7b'],
|
||||
['sha1', '8cb2237d0679ca88db6464eac60da96345513964'],
|
||||
['sha224', 'a7470858e79c282bc2f6adfd831b132672dfd1224c1e78cbf5bcd057'],
|
||||
['sha256', '5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5'],
|
||||
[
|
||||
'sha384',
|
||||
'0fa76955abfa9dafd83facca8343a92aa09497f98101086611b0bfa95dbc0dcc661d62e9568a5a032ba81960f3e55d4a',
|
||||
],
|
||||
[
|
||||
'sha512',
|
||||
'3627909a29c31381a071ec27f7c9ca97726182aed29a7ddd2e54353322cfb30abb9e3a6df2ac2c20fe23436311d678564d0c8d305930575f60e2d3d048184d79',
|
||||
],
|
||||
[
|
||||
'sha3',
|
||||
'0a2a1719bf3ce682afdbedf3b23857818d526efbe7fcb372b31347c26239a0f916c398b7ad8dd0ee76e8e388604d0b0f925d5e913ad2d3165b9b35b3844cd5e6',
|
||||
],
|
||||
])('should work for %p', (hashFn, hashValue) => {
|
||||
expect(evaluate(`={{ "12345".hash("${hashFn}") }}`)).toEqual(hashValue);
|
||||
expect(evaluate(`={{ "12345".hash("${hashFn.toLowerCase()}") }}`)).toEqual(hashValue);
|
||||
});
|
||||
});
|
||||
|
||||
test('.urlDecode should work correctly on a string', () => {
|
||||
|
|
|
@ -1494,9 +1494,6 @@ importers:
|
|||
callsites:
|
||||
specifier: 3.1.0
|
||||
version: 3.1.0
|
||||
crypto-js:
|
||||
specifier: 4.2.0
|
||||
version: 4.2.0
|
||||
deep-equal:
|
||||
specifier: 2.2.0
|
||||
version: 2.2.0
|
||||
|
@ -1512,12 +1509,18 @@ importers:
|
|||
js-base64:
|
||||
specifier: 3.7.2
|
||||
version: 3.7.2
|
||||
jssha:
|
||||
specifier: 3.3.1
|
||||
version: 3.3.1
|
||||
lodash:
|
||||
specifier: 4.17.21
|
||||
version: 4.17.21
|
||||
luxon:
|
||||
specifier: 3.3.0
|
||||
version: 3.3.0
|
||||
md5:
|
||||
specifier: 2.3.0
|
||||
version: 2.3.0
|
||||
recast:
|
||||
specifier: 0.21.5
|
||||
version: 0.21.5
|
||||
|
@ -1531,9 +1534,6 @@ importers:
|
|||
specifier: ^0.5.0
|
||||
version: 0.5.0
|
||||
devDependencies:
|
||||
'@types/crypto-js':
|
||||
specifier: ^4.1.3
|
||||
version: 4.1.3
|
||||
'@types/deep-equal':
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
|
@ -1549,6 +1549,9 @@ importers:
|
|||
'@types/luxon':
|
||||
specifier: ^3.2.0
|
||||
version: 3.2.0
|
||||
'@types/md5':
|
||||
specifier: ^2.3.5
|
||||
version: 2.3.5
|
||||
'@types/xml2js':
|
||||
specifier: ^0.4.11
|
||||
version: 0.4.11
|
||||
|
@ -9095,10 +9098,6 @@ packages:
|
|||
'@types/node': 18.16.16
|
||||
dev: true
|
||||
|
||||
/@types/crypto-js@4.1.3:
|
||||
resolution: {integrity: sha512-YP1sYYayLe7Eg5oXyLLvOLfxBfZ5Fgpz6sVWkpB18wDMywCLPWmqzRz+9gyuOoLF0fzDTTFwlyNbx7koONUwqA==}
|
||||
dev: true
|
||||
|
||||
/@types/dateformat@3.0.1:
|
||||
resolution: {integrity: sha512-KlPPdikagvL6ELjWsljbyDIPzNCeliYkqRpI+zea99vBBbCIA5JNshZAwQKTON139c87y9qvTFVgkFd14rtS4g==}
|
||||
dev: true
|
||||
|
@ -9364,6 +9363,10 @@ packages:
|
|||
'@types/linkify-it': 3.0.2
|
||||
'@types/mdurl': 1.0.2
|
||||
|
||||
/@types/md5@2.3.5:
|
||||
resolution: {integrity: sha512-/i42wjYNgE6wf0j2bcTX6kuowmdL/6PE4IVitMpm2eYKBUuYCprdcWVK+xEF0gcV6ufMCRhtxmReGfc6hIK7Jw==}
|
||||
dev: true
|
||||
|
||||
/@types/mdurl@1.0.2:
|
||||
resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
|
||||
|
||||
|
@ -17661,6 +17664,10 @@ packages:
|
|||
resolution: {integrity: sha512-w9OtT4ALL+fbbwG3gw7erAO0jvS5nfvrukGPMWIAoea359B26ALXGpzy4YJSp9yGnpUvuvOw1nSjSoHDfWSr1w==}
|
||||
dev: false
|
||||
|
||||
/jssha@3.3.1:
|
||||
resolution: {integrity: sha512-VCMZj12FCFMQYcFLPRm/0lOBbLi8uM2BhXPTqw3U4YAfs4AZfiApOoBLoN8cQE60Z50m1MYMTQVCfgF/KaCVhQ==}
|
||||
dev: false
|
||||
|
||||
/jstransformer@1.0.0:
|
||||
resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==}
|
||||
dependencies:
|
||||
|
|
Loading…
Reference in a new issue