mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20: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.
|
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
|
## 1.15.0
|
||||||
|
|
||||||
### What changed?
|
### What changed?
|
||||||
|
|
|
@ -39,12 +39,12 @@
|
||||||
"dist/**/*"
|
"dist/**/*"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/crypto-js": "^4.1.3",
|
|
||||||
"@types/deep-equal": "^1.0.1",
|
"@types/deep-equal": "^1.0.1",
|
||||||
"@types/express": "^4.17.6",
|
"@types/express": "^4.17.6",
|
||||||
"@types/jmespath": "^0.15.0",
|
"@types/jmespath": "^0.15.0",
|
||||||
"@types/lodash": "^4.14.195",
|
"@types/lodash": "^4.14.195",
|
||||||
"@types/luxon": "^3.2.0",
|
"@types/luxon": "^3.2.0",
|
||||||
|
"@types/md5": "^2.3.5",
|
||||||
"@types/xml2js": "^0.4.11"
|
"@types/xml2js": "^0.4.11"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -52,14 +52,15 @@
|
||||||
"@n8n_io/riot-tmpl": "4.0.0",
|
"@n8n_io/riot-tmpl": "4.0.0",
|
||||||
"ast-types": "0.15.2",
|
"ast-types": "0.15.2",
|
||||||
"callsites": "3.1.0",
|
"callsites": "3.1.0",
|
||||||
"crypto-js": "4.2.0",
|
|
||||||
"deep-equal": "2.2.0",
|
"deep-equal": "2.2.0",
|
||||||
"esprima-next": "5.8.4",
|
"esprima-next": "5.8.4",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"jmespath": "0.16.0",
|
"jmespath": "0.16.0",
|
||||||
"js-base64": "3.7.2",
|
"js-base64": "3.7.2",
|
||||||
|
"jssha": "3.3.1",
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"luxon": "3.3.0",
|
"luxon": "3.3.0",
|
||||||
|
"md5": "2.3.0",
|
||||||
"recast": "0.21.5",
|
"recast": "0.21.5",
|
||||||
"title-case": "3.0.3",
|
"title-case": "3.0.3",
|
||||||
"transliteration": "2.3.5",
|
"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 { titleCase } from 'title-case';
|
||||||
import type { ExtensionMap } from './Extensions';
|
import type { ExtensionMap } from './Extensions';
|
||||||
import CryptoJS from 'crypto-js';
|
|
||||||
import { encode } from 'js-base64';
|
|
||||||
import { transliterate } from 'transliteration';
|
import { transliterate } from 'transliteration';
|
||||||
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
||||||
|
|
||||||
const hashFunctions: Record<string, typeof CryptoJS.MD5> = {
|
export const SupportedHashAlgorithms = [
|
||||||
md5: CryptoJS.MD5,
|
'md5',
|
||||||
sha1: CryptoJS.SHA1,
|
'sha1',
|
||||||
sha224: CryptoJS.SHA224,
|
'sha224',
|
||||||
sha256: CryptoJS.SHA256,
|
'sha256',
|
||||||
sha384: CryptoJS.SHA384,
|
'sha384',
|
||||||
sha512: CryptoJS.SHA512,
|
'sha512',
|
||||||
sha3: CryptoJS.SHA3,
|
'sha3',
|
||||||
ripemd160: CryptoJS.RIPEMD160,
|
] as const;
|
||||||
};
|
|
||||||
|
|
||||||
// All symbols from https://www.xe.com/symbols/ as for 2022/11/09
|
// All symbols from https://www.xe.com/symbols/ as for 2022/11/09
|
||||||
const CURRENCY_REGEXP =
|
const CURRENCY_REGEXP =
|
||||||
|
@ -113,23 +112,35 @@ const URL_REGEXP =
|
||||||
const CHAR_TEST_REGEXP = /\p{L}/u;
|
const CHAR_TEST_REGEXP = /\p{L}/u;
|
||||||
const PUNC_TEST_REGEXP = /[!?.]/;
|
const PUNC_TEST_REGEXP = /[!?.]/;
|
||||||
|
|
||||||
function hash(value: string, extraArgs?: unknown): string {
|
function hash(value: string, extraArgs: string[]): string {
|
||||||
const [algorithm = 'MD5'] = extraArgs as string[];
|
const algorithm = extraArgs[0]?.toLowerCase() ?? 'md5';
|
||||||
if (algorithm.toLowerCase() === 'base64') {
|
switch (algorithm) {
|
||||||
// We're using a library instead of btoa because btoa only
|
case 'base64':
|
||||||
// works on ASCII
|
return encode(value);
|
||||||
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 {
|
function isEmpty(value: string): boolean {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @jest-environment jsdom
|
* @jest-environment jsdom
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { stringExtensions } from '@/Extensions/StringExtensions';
|
|
||||||
import { evaluate } from './Helpers';
|
import { evaluate } from './Helpers';
|
||||||
|
|
||||||
describe('Data Transformation Functions', () => {
|
describe('Data Transformation Functions', () => {
|
||||||
|
@ -15,28 +13,28 @@ describe('Data Transformation Functions', () => {
|
||||||
expect(evaluate('={{"".isEmpty()}}')).toEqual(true);
|
expect(evaluate('={{"".isEmpty()}}')).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('.hash() should work correctly on a string', () => {
|
describe('.hash()', () => {
|
||||||
expect(evaluate('={{ "12345".hash("sha256") }}')).toEqual(
|
test.each([
|
||||||
stringExtensions.functions.hash('12345', ['sha256']),
|
['md5', '827ccb0eea8a706c4c34a16891f84e7b'],
|
||||||
);
|
['sha1', '8cb2237d0679ca88db6464eac60da96345513964'],
|
||||||
|
['sha224', 'a7470858e79c282bc2f6adfd831b132672dfd1224c1e78cbf5bcd057'],
|
||||||
expect(evaluate('={{ "12345".hash("sha256") }}')).not.toEqual(
|
['sha256', '5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5'],
|
||||||
stringExtensions.functions.hash('12345', ['MD5']),
|
[
|
||||||
);
|
'sha384',
|
||||||
|
'0fa76955abfa9dafd83facca8343a92aa09497f98101086611b0bfa95dbc0dcc661d62e9568a5a032ba81960f3e55d4a',
|
||||||
expect(evaluate('={{ "12345".hash("MD5") }}')).toEqual(
|
],
|
||||||
stringExtensions.functions.hash('12345', ['MD5']),
|
[
|
||||||
);
|
'sha512',
|
||||||
|
'3627909a29c31381a071ec27f7c9ca97726182aed29a7ddd2e54353322cfb30abb9e3a6df2ac2c20fe23436311d678564d0c8d305930575f60e2d3d048184d79',
|
||||||
expect(evaluate('={{ "12345".hash("sha256") }}')).toEqual(
|
],
|
||||||
'5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5',
|
[
|
||||||
);
|
'sha3',
|
||||||
});
|
'0a2a1719bf3ce682afdbedf3b23857818d526efbe7fcb372b31347c26239a0f916c398b7ad8dd0ee76e8e388604d0b0f925d5e913ad2d3165b9b35b3844cd5e6',
|
||||||
|
],
|
||||||
test('.hash() alias should work correctly on a string', () => {
|
])('should work for %p', (hashFn, hashValue) => {
|
||||||
expect(evaluate('={{ "12345".hash("sha256") }}')).toEqual(
|
expect(evaluate(`={{ "12345".hash("${hashFn}") }}`)).toEqual(hashValue);
|
||||||
'5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5',
|
expect(evaluate(`={{ "12345".hash("${hashFn.toLowerCase()}") }}`)).toEqual(hashValue);
|
||||||
);
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('.urlDecode should work correctly on a string', () => {
|
test('.urlDecode should work correctly on a string', () => {
|
||||||
|
|
|
@ -1494,9 +1494,6 @@ importers:
|
||||||
callsites:
|
callsites:
|
||||||
specifier: 3.1.0
|
specifier: 3.1.0
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
crypto-js:
|
|
||||||
specifier: 4.2.0
|
|
||||||
version: 4.2.0
|
|
||||||
deep-equal:
|
deep-equal:
|
||||||
specifier: 2.2.0
|
specifier: 2.2.0
|
||||||
version: 2.2.0
|
version: 2.2.0
|
||||||
|
@ -1512,12 +1509,18 @@ importers:
|
||||||
js-base64:
|
js-base64:
|
||||||
specifier: 3.7.2
|
specifier: 3.7.2
|
||||||
version: 3.7.2
|
version: 3.7.2
|
||||||
|
jssha:
|
||||||
|
specifier: 3.3.1
|
||||||
|
version: 3.3.1
|
||||||
lodash:
|
lodash:
|
||||||
specifier: 4.17.21
|
specifier: 4.17.21
|
||||||
version: 4.17.21
|
version: 4.17.21
|
||||||
luxon:
|
luxon:
|
||||||
specifier: 3.3.0
|
specifier: 3.3.0
|
||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
|
md5:
|
||||||
|
specifier: 2.3.0
|
||||||
|
version: 2.3.0
|
||||||
recast:
|
recast:
|
||||||
specifier: 0.21.5
|
specifier: 0.21.5
|
||||||
version: 0.21.5
|
version: 0.21.5
|
||||||
|
@ -1531,9 +1534,6 @@ importers:
|
||||||
specifier: ^0.5.0
|
specifier: ^0.5.0
|
||||||
version: 0.5.0
|
version: 0.5.0
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@types/crypto-js':
|
|
||||||
specifier: ^4.1.3
|
|
||||||
version: 4.1.3
|
|
||||||
'@types/deep-equal':
|
'@types/deep-equal':
|
||||||
specifier: ^1.0.1
|
specifier: ^1.0.1
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
|
@ -1549,6 +1549,9 @@ importers:
|
||||||
'@types/luxon':
|
'@types/luxon':
|
||||||
specifier: ^3.2.0
|
specifier: ^3.2.0
|
||||||
version: 3.2.0
|
version: 3.2.0
|
||||||
|
'@types/md5':
|
||||||
|
specifier: ^2.3.5
|
||||||
|
version: 2.3.5
|
||||||
'@types/xml2js':
|
'@types/xml2js':
|
||||||
specifier: ^0.4.11
|
specifier: ^0.4.11
|
||||||
version: 0.4.11
|
version: 0.4.11
|
||||||
|
@ -9095,10 +9098,6 @@ packages:
|
||||||
'@types/node': 18.16.16
|
'@types/node': 18.16.16
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/crypto-js@4.1.3:
|
|
||||||
resolution: {integrity: sha512-YP1sYYayLe7Eg5oXyLLvOLfxBfZ5Fgpz6sVWkpB18wDMywCLPWmqzRz+9gyuOoLF0fzDTTFwlyNbx7koONUwqA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/dateformat@3.0.1:
|
/@types/dateformat@3.0.1:
|
||||||
resolution: {integrity: sha512-KlPPdikagvL6ELjWsljbyDIPzNCeliYkqRpI+zea99vBBbCIA5JNshZAwQKTON139c87y9qvTFVgkFd14rtS4g==}
|
resolution: {integrity: sha512-KlPPdikagvL6ELjWsljbyDIPzNCeliYkqRpI+zea99vBBbCIA5JNshZAwQKTON139c87y9qvTFVgkFd14rtS4g==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -9364,6 +9363,10 @@ packages:
|
||||||
'@types/linkify-it': 3.0.2
|
'@types/linkify-it': 3.0.2
|
||||||
'@types/mdurl': 1.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:
|
/@types/mdurl@1.0.2:
|
||||||
resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
|
resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
|
||||||
|
|
||||||
|
@ -17661,6 +17664,10 @@ packages:
|
||||||
resolution: {integrity: sha512-w9OtT4ALL+fbbwG3gw7erAO0jvS5nfvrukGPMWIAoea359B26ALXGpzy4YJSp9yGnpUvuvOw1nSjSoHDfWSr1w==}
|
resolution: {integrity: sha512-w9OtT4ALL+fbbwG3gw7erAO0jvS5nfvrukGPMWIAoea359B26ALXGpzy4YJSp9yGnpUvuvOw1nSjSoHDfWSr1w==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/jssha@3.3.1:
|
||||||
|
resolution: {integrity: sha512-VCMZj12FCFMQYcFLPRm/0lOBbLi8uM2BhXPTqw3U4YAfs4AZfiApOoBLoN8cQE60Z50m1MYMTQVCfgF/KaCVhQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/jstransformer@1.0.0:
|
/jstransformer@1.0.0:
|
||||||
resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==}
|
resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
Loading…
Reference in a new issue