mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-05-05 05:47:10 -04:00
Merge 97a2a11613
into e876d03608
This commit is contained in:
commit
123ff422f7
7 changed files with 251 additions and 8 deletions
1
components.d.ts
vendored
1
components.d.ts
vendored
|
@ -158,6 +158,7 @@ declare module '@vue/runtime-core' {
|
||||||
RomanNumeralConverter: typeof import('./src/tools/roman-numeral-converter/roman-numeral-converter.vue')['default']
|
RomanNumeralConverter: typeof import('./src/tools/roman-numeral-converter/roman-numeral-converter.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
RsaEncryption: typeof import('./src/tools/rsa-encryption/rsa-encryption.vue')['default']
|
||||||
RsaKeyPairGenerator: typeof import('./src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue')['default']
|
RsaKeyPairGenerator: typeof import('./src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue')['default']
|
||||||
SafelinkDecoder: typeof import('./src/tools/safelink-decoder/safelink-decoder.vue')['default']
|
SafelinkDecoder: typeof import('./src/tools/safelink-decoder/safelink-decoder.vue')['default']
|
||||||
SlugifyString: typeof import('./src/tools/slugify-string/slugify-string.vue')['default']
|
SlugifyString: typeof import('./src/tools/slugify-string/slugify-string.vue')['default']
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
"highlight.js": "^11.7.0",
|
"highlight.js": "^11.7.0",
|
||||||
"iarna-toml-esm": "^3.0.5",
|
"iarna-toml-esm": "^3.0.5",
|
||||||
"ibantools": "^4.3.3",
|
"ibantools": "^4.3.3",
|
||||||
|
"js-base64": "^3.7.7",
|
||||||
"json5": "^2.2.3",
|
"json5": "^2.2.3",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"libphonenumber-js": "^1.10.28",
|
"libphonenumber-js": "^1.10.28",
|
||||||
|
|
20
pnpm-lock.yaml
generated
20
pnpm-lock.yaml
generated
|
@ -92,6 +92,9 @@ dependencies:
|
||||||
ibantools:
|
ibantools:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3
|
version: 4.3.3
|
||||||
|
js-base64:
|
||||||
|
specifier: ^3.7.7
|
||||||
|
version: 3.7.7
|
||||||
json5:
|
json5:
|
||||||
specifier: ^2.2.3
|
specifier: ^2.2.3
|
||||||
version: 2.2.3
|
version: 2.2.3
|
||||||
|
@ -3351,7 +3354,7 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@unhead/dom': 0.5.1
|
'@unhead/dom': 0.5.1
|
||||||
'@unhead/schema': 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
|
unhead: 0.5.1
|
||||||
vue: 3.3.4
|
vue: 3.3.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -3993,10 +3996,10 @@ packages:
|
||||||
- vue
|
- vue
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@vueuse/shared@10.7.2(vue@3.3.4):
|
/@vueuse/shared@10.9.0(vue@3.3.4):
|
||||||
resolution: {integrity: sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==}
|
resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
vue-demi: 0.14.6(vue@3.3.4)
|
vue-demi: 0.14.7(vue@3.3.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@vue/composition-api'
|
- '@vue/composition-api'
|
||||||
- vue
|
- vue
|
||||||
|
@ -6472,6 +6475,10 @@ packages:
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/js-base64@3.7.7:
|
||||||
|
resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/js-beautify@1.14.6:
|
/js-beautify@1.14.6:
|
||||||
resolution: {integrity: sha512-GfofQY5zDp+cuHc+gsEXKPpNw2KbPddreEo35O6jT6i0RVK6LhsoYBhq5TvK4/n74wnA0QbK8gGd+jUZwTMKJw==}
|
resolution: {integrity: sha512-GfofQY5zDp+cuHc+gsEXKPpNw2KbPddreEo35O6jT6i0RVK6LhsoYBhq5TvK4/n74wnA0QbK8gGd+jUZwTMKJw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
@ -9151,8 +9158,8 @@ packages:
|
||||||
vue: 3.3.4
|
vue: 3.3.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vue-demi@0.14.6(vue@3.3.4):
|
/vue-demi@0.14.7(vue@3.3.4):
|
||||||
resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==}
|
resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
|
@ -9442,6 +9449,7 @@ packages:
|
||||||
|
|
||||||
/workbox-google-analytics@7.0.0:
|
/workbox-google-analytics@7.0.0:
|
||||||
resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
|
resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
|
||||||
|
deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
|
||||||
dependencies:
|
dependencies:
|
||||||
workbox-background-sync: 7.0.0
|
workbox-background-sync: 7.0.0
|
||||||
workbox-core: 7.0.0
|
workbox-core: 7.0.0
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { type Ref, ref, watchEffect } from 'vue';
|
import { type Ref, ref, watchEffect } from 'vue';
|
||||||
|
|
||||||
export { computedCatch };
|
export { computedCatch, computedCatchAsync };
|
||||||
|
|
||||||
function computedCatch<T, D>(getter: () => T, { defaultValue }: { defaultValue: D; defaultErrorMessage?: string }): [Ref<T | D>, Ref<string | undefined>];
|
function computedCatch<T, D>(getter: () => T, { defaultValue }: { defaultValue: D; defaultErrorMessage?: string }): [Ref<T | D>, Ref<string | undefined>];
|
||||||
function computedCatch<T, D>(getter: () => T, { defaultValue, defaultErrorMessage = 'Unknown error' }: { defaultValue?: D; defaultErrorMessage?: string } = {}) {
|
function computedCatch<T, D>(getter: () => T, { defaultValue, defaultErrorMessage = 'Unknown error' }: { defaultValue?: D; defaultErrorMessage?: string } = {}) {
|
||||||
|
@ -20,3 +20,22 @@ function computedCatch<T, D>(getter: () => T, { defaultValue, defaultErrorMessag
|
||||||
|
|
||||||
return [value, error] as const;
|
return [value, error] as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function computedCatchAsync<T, D>(getterAsync: () => Promise<T>, { defaultValue }: { defaultValue: D; defaultErrorMessage?: string }): [Ref<T | D>, Ref<string | undefined>];
|
||||||
|
function computedCatchAsync<T, D>(getterAsync: () => Promise<T>, { defaultValue, defaultErrorMessage = 'Unknown error' }: { defaultValue?: D; defaultErrorMessage?: string } = {}) {
|
||||||
|
const error = ref<string | undefined>();
|
||||||
|
const value = ref<T | D | undefined>();
|
||||||
|
|
||||||
|
watchEffect(async () => {
|
||||||
|
try {
|
||||||
|
error.value = undefined;
|
||||||
|
value.value = await getterAsync();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
error.value = err instanceof Error ? err.message : err?.toString() ?? defaultErrorMessage;
|
||||||
|
value.value = defaultValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return [value, error] as const;
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { tool as asciiTextDrawer } from './ascii-text-drawer';
|
||||||
|
|
||||||
import { tool as textToUnicode } from './text-to-unicode';
|
import { tool as textToUnicode } from './text-to-unicode';
|
||||||
import { tool as safelinkDecoder } from './safelink-decoder';
|
import { tool as safelinkDecoder } from './safelink-decoder';
|
||||||
|
import { tool as rsaEncryption } from './rsa-encryption';
|
||||||
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
|
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
|
||||||
import { tool as numeronymGenerator } from './numeronym-generator';
|
import { tool as numeronymGenerator } from './numeronym-generator';
|
||||||
import { tool as macAddressGenerator } from './mac-address-generator';
|
import { tool as macAddressGenerator } from './mac-address-generator';
|
||||||
|
@ -85,7 +86,20 @@ import { tool as yamlViewer } from './yaml-viewer';
|
||||||
export const toolsByCategory: ToolCategory[] = [
|
export const toolsByCategory: ToolCategory[] = [
|
||||||
{
|
{
|
||||||
name: 'Crypto',
|
name: 'Crypto',
|
||||||
components: [tokenGenerator, hashText, bcrypt, uuidGenerator, ulidGenerator, cypher, bip39, hmacGenerator, rsaKeyPairGenerator, passwordStrengthAnalyser, pdfSignatureChecker],
|
components: [
|
||||||
|
tokenGenerator,
|
||||||
|
hashText,
|
||||||
|
bcrypt,
|
||||||
|
uuidGenerator,
|
||||||
|
ulidGenerator,
|
||||||
|
cypher,
|
||||||
|
bip39,
|
||||||
|
hmacGenerator,
|
||||||
|
rsaKeyPairGenerator,
|
||||||
|
passwordStrengthAnalyser,
|
||||||
|
pdfSignatureChecker,
|
||||||
|
rsaEncryption,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Converter',
|
name: 'Converter',
|
||||||
|
|
12
src/tools/rsa-encryption/index.ts
Normal file
12
src/tools/rsa-encryption/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Lock } from '@vicons/tabler';
|
||||||
|
import { defineTool } from '../tool';
|
||||||
|
|
||||||
|
export const tool = defineTool({
|
||||||
|
name: 'RSA encryption',
|
||||||
|
path: '/rsa-encryption',
|
||||||
|
description: 'Encrypt and decrypt text clear text using RSA Keys.',
|
||||||
|
keywords: ['rsa', 'encryption', 'cypher', 'encipher', 'crypt', 'decrypt'],
|
||||||
|
component: () => import('./rsa-encryption.vue'),
|
||||||
|
icon: Lock,
|
||||||
|
createdAt: new Date('2024-04-20'),
|
||||||
|
});
|
188
src/tools/rsa-encryption/rsa-encryption.vue
Normal file
188
src/tools/rsa-encryption/rsa-encryption.vue
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { md, pki } from 'node-forge';
|
||||||
|
import { Base64 } from 'js-base64';
|
||||||
|
import { computedCatchAsync } from '@/composable/computed/catchedComputed';
|
||||||
|
import TextareaCopyable from '@/components/TextareaCopyable.vue';
|
||||||
|
|
||||||
|
const schemes = [
|
||||||
|
{ value: 'RSAES-PKCS1-V1_5', label: 'RSAES PKCS#1 v1.5' },
|
||||||
|
{ value: 'RSAES-OAEP', label: 'RSAES-OAEP' },
|
||||||
|
{ value: 'RSAES-OAEP/SHA-256', label: 'RSAES-OAEP/SHA-256' },
|
||||||
|
{ value: 'RSAES-OAEP/SHA-256/MGF1-SHA-1', label: 'RSAES-OAEP/SHA-256/MGF1-SHA-1 (RSA/ECB/OAEPWithSHA-256AndMGF1Padding)' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const cryptInput = ref('');
|
||||||
|
const cryptScheme = ref('RSAES-PKCS1-V1_5');
|
||||||
|
const cryptPublicKey = ref('');
|
||||||
|
const [cryptOutput, cryptError] = computedCatchAsync(async () => {
|
||||||
|
const publicKeyPEM = cryptPublicKey.value;
|
||||||
|
const text = cryptInput.value;
|
||||||
|
const scheme = cryptScheme.value;
|
||||||
|
|
||||||
|
const publicKey = pki.publicKeyFromPem(publicKeyPEM);
|
||||||
|
|
||||||
|
let encrypted;
|
||||||
|
if (scheme === 'RSAES-PKCS1-V1_5') {
|
||||||
|
// encrypt data with a public key using RSAES PKCS#1 v1.5
|
||||||
|
encrypted = publicKey.encrypt(text, 'RSAES-PKCS1-V1_5');
|
||||||
|
}
|
||||||
|
else if (scheme === 'RSAES-OAEP') {
|
||||||
|
// encrypt data with a public key using RSAES-OAEP
|
||||||
|
encrypted = publicKey.encrypt(text, 'RSA-OAEP');
|
||||||
|
}
|
||||||
|
else if (scheme === 'RSAES-OAEP/SHA-256') {
|
||||||
|
// encrypt data with a public key using RSAES-OAEP/SHA-256
|
||||||
|
encrypted = publicKey.encrypt(text, 'RSA-OAEP', {
|
||||||
|
md: md.sha256.create(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (scheme === 'RSAES-OAEP/SHA-256/MGF1-SHA-1') {
|
||||||
|
// encrypt data with a public key using RSAES-OAEP/SHA-256/MGF1-SHA-1
|
||||||
|
// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding
|
||||||
|
encrypted = publicKey.encrypt(text, 'RSA-OAEP', {
|
||||||
|
md: md.sha256.create(),
|
||||||
|
mgf1: {
|
||||||
|
md: md.sha1.create(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Base64.encode(encrypted || '');
|
||||||
|
}, {
|
||||||
|
defaultValue: '',
|
||||||
|
defaultErrorMessage: 'Unable to encrypt your text',
|
||||||
|
});
|
||||||
|
|
||||||
|
const decryptInput = ref('');
|
||||||
|
const decryptScheme = ref('RSAES-PKCS1-V1_5');
|
||||||
|
const decryptPrivateKey = ref('');
|
||||||
|
const decryptPrivateKeyPassphrase = ref('');
|
||||||
|
const [decryptOutput, decryptError] = computedCatchAsync(async () => {
|
||||||
|
const privateKeyPEM = decryptPrivateKey.value;
|
||||||
|
const passphrase = decryptPrivateKeyPassphrase.value;
|
||||||
|
const encrypted = Base64.decode(decryptInput.value);
|
||||||
|
const scheme = decryptScheme.value;
|
||||||
|
|
||||||
|
const privateKey = pki.decryptRsaPrivateKey(privateKeyPEM, passphrase);
|
||||||
|
|
||||||
|
let decrypted;
|
||||||
|
if (scheme === 'RSAES-PKCS1-V1_5') {
|
||||||
|
// decrypt data with a private key using RSAES PKCS#1 v1.5
|
||||||
|
decrypted = privateKey.decrypt(encrypted, 'RSAES-PKCS1-V1_5');
|
||||||
|
}
|
||||||
|
else if (scheme === 'RSAES-OAEP') {
|
||||||
|
// decrypt data with a private key using RSAES-OAEP
|
||||||
|
decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP');
|
||||||
|
}
|
||||||
|
else if (scheme === 'RSAES-OAEP/SHA-256') {
|
||||||
|
// decrypt data with a private key using RSAES-OAEP/SHA-256
|
||||||
|
decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {
|
||||||
|
md: md.sha256.create(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (scheme === 'RSAES-OAEP/SHA-256/MGF1-SHA-1') {
|
||||||
|
// decrypt data with a private key using RSAES-OAEP/SHA-256/MGF1-SHA-1
|
||||||
|
// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding
|
||||||
|
decrypted = privateKey.decrypt(encrypted, 'RSA-OAEP', {
|
||||||
|
md: md.sha256.create(),
|
||||||
|
mgf1: {
|
||||||
|
md: md.sha1.create(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return decrypted;
|
||||||
|
}, {
|
||||||
|
defaultValue: '',
|
||||||
|
defaultErrorMessage: 'Unable to encrypt your text',
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<c-card title="Encrypt">
|
||||||
|
<div>
|
||||||
|
<c-input-text
|
||||||
|
v-model:value="cryptInput"
|
||||||
|
label="Your text:"
|
||||||
|
placeholder="The string to encrypt"
|
||||||
|
rows="4"
|
||||||
|
multiline raw-text monospace autosize flex-1
|
||||||
|
/>
|
||||||
|
<c-select
|
||||||
|
v-model:value="cryptScheme"
|
||||||
|
label="Scheme:"
|
||||||
|
:options="schemes"
|
||||||
|
placeholder="Select the encryption scheme"
|
||||||
|
/>
|
||||||
|
<div flex flex-1 flex-col gap-2>
|
||||||
|
<c-input-text
|
||||||
|
v-model:value="cryptPublicKey"
|
||||||
|
label="Target public key:"
|
||||||
|
placeholder="Target public key"
|
||||||
|
rows="5"
|
||||||
|
multiline raw-text monospace autosize flex-1
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<c-alert v-if="cryptError && cryptPublicKey !== ''" type="error" mt-12 title="Error while encrypting">
|
||||||
|
{{ cryptError }}
|
||||||
|
</c-alert>
|
||||||
|
|
||||||
|
<n-form-item label="Your text encrypted:" mt-3>
|
||||||
|
<TextareaCopyable
|
||||||
|
:value="cryptOutput || ''"
|
||||||
|
rows="3"
|
||||||
|
placeholder="Your string encrypted"
|
||||||
|
multiline monospace readonly autosize mt-5
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
</c-card>
|
||||||
|
|
||||||
|
<c-card title="Decrypt">
|
||||||
|
<div>
|
||||||
|
<c-input-text
|
||||||
|
v-model:value="decryptInput"
|
||||||
|
label="Your PGP Message to decrypt:"
|
||||||
|
placeholder="The string to decrypt"
|
||||||
|
rows="4"
|
||||||
|
multiline raw-text monospace autosize flex-1
|
||||||
|
/>
|
||||||
|
|
||||||
|
<c-select
|
||||||
|
v-model:value="decryptScheme"
|
||||||
|
label="Scheme:"
|
||||||
|
:options="schemes"
|
||||||
|
placeholder="Select the encryption scheme"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div flex flex-1 flex-col gap-2>
|
||||||
|
<c-input-text
|
||||||
|
v-model:value="decryptPrivateKey"
|
||||||
|
label="Your private key:"
|
||||||
|
placeholder="The private key to use to decrypt message"
|
||||||
|
rows="5"
|
||||||
|
multiline raw-text monospace autosize flex-1
|
||||||
|
/>
|
||||||
|
|
||||||
|
<c-input-text
|
||||||
|
v-model:value="decryptPrivateKeyPassphrase"
|
||||||
|
label="Your private key password:" clearable raw-text
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<c-alert v-if="decryptError && decryptPrivateKey !== ''" type="error" mt-12 title="Error while decrypting">
|
||||||
|
{{ decryptError }}
|
||||||
|
</c-alert>
|
||||||
|
|
||||||
|
<n-form-item label="Your text decrypted:" mt-3>
|
||||||
|
<TextareaCopyable
|
||||||
|
:value="decryptOutput || ''"
|
||||||
|
rows="3"
|
||||||
|
placeholder="Your string decrypted"
|
||||||
|
multiline monospace readonly autosize mt-5
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
</c-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
Loading…
Add table
Add a link
Reference in a new issue