feat(Hash Text): more hashing methods

Added ADLER32, BLAKE2B, BLAKE2S, BLAKE3, CRC32, CRC32C, KECCAK, PBKDF2, SM3, WHIRLPOOL, XXHASH128, XXHASH3, XXHASH32, XXHASH64, Argon2, Argon2i, Argon2d, Argon2id
Fix #728 and #641 and #362
This commit is contained in:
sharevb 2024-04-02 08:52:27 +02:00 committed by ShareVB
parent d3b32cc14e
commit 2816ed254a
5 changed files with 225 additions and 11 deletions

View file

@ -61,6 +61,7 @@
"figlet": "^1.7.0",
"figue": "^1.2.0",
"fuse.js": "^6.6.2",
"hash-wasm": "^4.11.0",
"highlight.js": "^11.7.0",
"iarna-toml-esm": "^3.0.5",
"ibantools": "^4.3.3",

19
pnpm-lock.yaml generated
View file

@ -83,6 +83,9 @@ dependencies:
fuse.js:
specifier: ^6.6.2
version: 6.6.2
hash-wasm:
specifier: ^4.11.0
version: 4.11.0
highlight.js:
specifier: ^11.7.0
version: 11.7.0
@ -3351,7 +3354,7 @@ packages:
dependencies:
'@unhead/dom': 0.5.1
'@unhead/schema': 0.5.1
'@vueuse/shared': 10.7.2(vue@3.3.4)
'@vueuse/shared': 10.9.0(vue@3.3.4)
unhead: 0.5.1
vue: 3.3.4
transitivePeerDependencies:
@ -3993,10 +3996,10 @@ packages:
- vue
dev: false
/@vueuse/shared@10.7.2(vue@3.3.4):
resolution: {integrity: sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==}
/@vueuse/shared@10.9.0(vue@3.3.4):
resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==}
dependencies:
vue-demi: 0.14.6(vue@3.3.4)
vue-demi: 0.14.7(vue@3.3.4)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
@ -5969,6 +5972,10 @@ packages:
function-bind: 1.1.2
dev: true
/hash-wasm@4.11.0:
resolution: {integrity: sha512-HVusNXlVqHe0fzIzdQOGolnFN6mX/fqcrSAOcTBXdvzrXVHwTz11vXeKRmkR5gTuwVpvHZEIyKoePDvuAR+XwQ==}
dev: false
/hasown@2.0.0:
resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==}
engines: {node: '>= 0.4'}
@ -9151,8 +9158,8 @@ packages:
vue: 3.3.4
dev: false
/vue-demi@0.14.6(vue@3.3.4):
resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==}
/vue-demi@0.14.7(vue@3.3.4):
resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true

View file

@ -1,7 +1,8 @@
import { useRouteQuery } from '@vueuse/router';
import { computed } from 'vue';
import { useStorage } from '@vueuse/core';
export { useQueryParam };
export { useQueryParam, useQueryParamOrStorage };
const transformers = {
number: {
@ -33,3 +34,31 @@ function useQueryParam<T>({ name, defaultValue }: { name: string; defaultValue:
},
});
}
function useQueryParamOrStorage<T>({ name, storageName, defaultValue }: { name: string; storageName: string; defaultValue?: T }) {
const type = typeof defaultValue;
const transformer = transformers[type as keyof typeof transformers] ?? transformers.string;
const storageRef = useStorage(storageName, defaultValue);
const storageDefaultValue = storageRef.value ?? defaultValue;
const proxy = useRouteQuery(name, transformer.toQuery(storageDefaultValue as never));
const ref = computed<T>({
get() {
return transformer.fromQuery(proxy.value) as unknown as T;
},
set(value) {
proxy.value = transformer.toQuery(value as never);
},
});
watch(
ref,
(newValue) => {
storageRef.value = newValue;
},
);
return ref;
}

View file

@ -2,9 +2,30 @@
import type { lib } from 'crypto-js';
import { MD5, RIPEMD160, SHA1, SHA224, SHA256, SHA3, SHA384, SHA512, enc } from 'crypto-js';
import {
adler32,
argon2d,
argon2i,
argon2id,
blake2b,
blake2s,
blake3,
crc32,
crc32c,
createSHA256,
keccak,
pbkdf2,
sm3,
whirlpool,
xxhash128,
xxhash3,
xxhash32,
xxhash64,
} from 'hash-wasm';
import InputCopyable from '../../components/InputCopyable.vue';
import { convertHexToBin } from './hash-text.service';
import { useQueryParam } from '@/composable/queryParams';
import { useQueryParamOrStorage } from '@/composable/queryParams';
const algos = {
MD5,
@ -20,7 +41,27 @@ const algos = {
type AlgoNames = keyof typeof algos;
type Encoding = keyof typeof enc | 'Bin';
const algoNames = Object.keys(algos) as AlgoNames[];
const encoding = useQueryParam<Encoding>({ defaultValue: 'Hex', name: 'encoding' });
const algosWasm = {
adler32,
crc32,
crc32c,
blake2b,
blake2s,
blake3,
keccak,
xxhash32,
xxhash64,
xxhash3,
xxhash128,
sm3,
whirlpool,
} as const;
type AlgoWasmNames = keyof typeof algosWasm;
const algoWasmNames = Object.keys(algosWasm) as AlgoWasmNames[];
const encoding = useQueryParamOrStorage<Encoding>({ defaultValue: 'Hex', storageName: 'hash-text:encoding', name: 'encoding' });
const clearText = ref('');
function formatWithEncoding(words: lib.WordArray, encoding: Encoding) {
@ -32,12 +73,91 @@ function formatWithEncoding(words: lib.WordArray, encoding: Encoding) {
}
const hashText = (algo: AlgoNames, value: string) => formatWithEncoding(algos[algo](value), encoding.value);
const defaultHashWasmValues = {
adler32: '',
crc32: '',
crc32c: '',
blake2b: '',
blake2s: '',
blake3: '',
keccak: '',
xxhash32: '',
xxhash64: '',
xxhash3: '',
xxhash128: '',
sm3: '',
whirlpool: '',
};
const hashWasmValues = computedAsync(async () => {
const encodingValue = encoding.value;
const clearTextValue = clearText.value;
const ret = defaultHashWasmValues;
for (const algo of algoWasmNames) {
ret[algo] = formatWithEncoding(enc.Hex.parse(await algosWasm[algo](clearTextValue)), encodingValue);
}
return ret;
}, defaultHashWasmValues);
const salt = new Uint8Array(16);
window.crypto.getRandomValues(salt);
const hashWasmArgon2i = computedAsync(async () => {
const clearTextValue = clearText.value;
return await argon2i({
password: clearTextValue,
salt,
parallelism: 1,
memorySize: 128,
iterations: 4,
hashLength: 16,
outputType: 'encoded',
});
});
const hashWasmArgon2d = computedAsync(async () => {
const clearTextValue = clearText.value;
return await argon2d({
password: clearTextValue,
salt,
parallelism: 1,
memorySize: 128,
iterations: 4,
hashLength: 16,
outputType: 'encoded',
});
});
const hashWasmArgon2id = computedAsync(async () => {
const clearTextValue = clearText.value;
return await argon2id({
password: clearTextValue,
salt,
parallelism: 1,
memorySize: 128,
iterations: 4,
hashLength: 16,
outputType: 'encoded',
});
});
const hashWasmPBKDF2 = computedAsync(async () => {
const clearTextValue = clearText.value;
return await pbkdf2({
password: clearTextValue,
salt,
iterations: 16,
hashLength: 32,
hashFunction: createSHA256(),
});
});
</script>
<template>
<div>
<c-card>
<c-input-text v-model:value="clearText" multiline raw-text placeholder="Your string to hash..." rows="3" autosize autofocus label="Your text to hash:" />
<c-input-text
v-model:value="clearText"
multiline raw-text
placeholder="Your string to hash..." rows="3"
autosize autofocus label="Your text to hash:"
/>
<n-divider />
@ -73,6 +193,44 @@ const hashText = (algo: AlgoNames, value: string) => formatWithEncoding(algos[al
<InputCopyable :value="hashText(algo, clearText)" readonly />
</n-input-group>
</div>
<div v-for="algo in algoWasmNames" :key="algo" style="margin: 5px 0">
<n-input-group>
<n-input-group-label style="flex: 0 0 120px">
{{ algo.toUpperCase() }}
</n-input-group-label>
<InputCopyable :value="hashWasmValues[algo]" readonly />
</n-input-group>
</div>
<n-divider />
<div style="margin: 5px 0">
<n-input-group>
<n-input-group-label style="flex: 0 0 120px">
Argon2d
</n-input-group-label>
<InputCopyable :value="hashWasmArgon2d" readonly />
</n-input-group>
<n-input-group>
<n-input-group-label style="flex: 0 0 120px">
Argon2i
</n-input-group-label>
<InputCopyable :value="hashWasmArgon2i" readonly />
</n-input-group>
<n-input-group>
<n-input-group-label style="flex: 0 0 120px">
Argon2id
</n-input-group-label>
<InputCopyable :value="hashWasmArgon2id" readonly />
</n-input-group>
<n-input-group>
<n-input-group-label style="flex: 0 0 120px">
PBKDF2
</n-input-group-label>
<InputCopyable :value="hashWasmPBKDF2" readonly />
</n-input-group>
</div>
</c-card>
</div>
</template>

View file

@ -5,7 +5,8 @@ import { translate } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.hash-text.title'),
path: '/hash-text',
description: translate('tools.hash-text.description'),
description:
'Hash a text string using the function you need : MD5, SHA1, SHA256, SHA224, SHA512, SHA384, SHA3, RIPEMD160, ADLER32, CRC32, CRC32C, BLAKE, KECCAK, XXHASH, SM3, WHIRLPOOL or Argon2(i/d/id)',
keywords: [
'hash',
'digest',
@ -20,6 +21,24 @@ export const tool = defineTool({
'SHA384',
'SHA3',
'RIPEMD160',
'ADLER32',
'BLAKE2B',
'BLAKE2S',
'BLAKE3',
'CRC32',
'CRC32C',
'KECCAK',
'PBKDF2',
'SM3',
'WHIRLPOOL',
'XXHASH128',
'XXHASH3',
'XXHASH32',
'XXHASH64',
'Argon2',
'Argon2i',
'Argon2d',
'Argon2id',
],
component: () => import('./hash-text.vue'),
icon: EyeOff,