diff options
author | 2023-03-10 18:16:55 +0100 | |
---|---|---|
committer | 2023-03-10 18:16:55 +0100 | |
commit | 30e9149d61c30206d080cf5c88d8cde1a282476c (patch) | |
tree | 2fc2062fd6bee7fe17be2713f57f65a01d87bfdf /src | |
parent | 7958e2e0756e21cb12559322d4dea46bc271ed93 (diff) | |
download | it-tools-30e9149d61c30206d080cf5c88d8cde1a282476c.tar.gz it-tools-30e9149d61c30206d080cf5c88d8cde1a282476c.tar.zst it-tools-30e9149d61c30206d080cf5c88d8cde1a282476c.zip |
feat(new-tool): RSA key pair generator
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/index.ts | 3 | ||||
-rw-r--r-- | src/tools/rsa-key-pair-generator/index.ts | 11 | ||||
-rw-r--r-- | src/tools/rsa-key-pair-generator/rsa-key-pair-generator.service.ts | 25 | ||||
-rw-r--r-- | src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue | 48 | ||||
-rw-r--r-- | src/utils/defaults.ts | 10 |
5 files changed, 95 insertions, 2 deletions
diff --git a/src/tools/index.ts b/src/tools/index.ts index 6ad328f..18208dd 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -1,6 +1,7 @@ import { tool as base64FileConverter } from './base64-file-converter'; import { tool as base64StringConverter } from './base64-string-converter'; import { tool as basicAuthGenerator } from './basic-auth-generator'; +import { tool as rsaKeyPairGenerator } from './rsa-key-pair-generator'; import { tool as textToNatoAlphabet } from './text-to-nato-alphabet'; import { tool as slugifyString } from './slugify-string'; import { tool as keycodeInfo } from './keycode-info'; @@ -44,7 +45,7 @@ import { tool as uuidGenerator } from './uuid-generator'; export const toolsByCategory: ToolCategory[] = [ { name: 'Crypto', - components: [tokenGenerator, hashText, bcrypt, uuidGenerator, cypher, bip39, hmacGenerator], + components: [tokenGenerator, hashText, bcrypt, uuidGenerator, cypher, bip39, hmacGenerator, rsaKeyPairGenerator], }, { name: 'Converter', diff --git a/src/tools/rsa-key-pair-generator/index.ts b/src/tools/rsa-key-pair-generator/index.ts new file mode 100644 index 0000000..c8ab4cd --- /dev/null +++ b/src/tools/rsa-key-pair-generator/index.ts @@ -0,0 +1,11 @@ +import { Certificate } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'RSA key pair generator', + path: '/rsa-key-pair-generator', + description: 'Generate new random RSA private and public key pem certificates.', + keywords: ['rsa', 'key', 'pair', 'generator', 'public', 'private', 'secret', 'ssh', 'pem'], + component: () => import('./rsa-key-pair-generator.vue'), + icon: Certificate, +}); diff --git a/src/tools/rsa-key-pair-generator/rsa-key-pair-generator.service.ts b/src/tools/rsa-key-pair-generator/rsa-key-pair-generator.service.ts new file mode 100644 index 0000000..a41d5cd --- /dev/null +++ b/src/tools/rsa-key-pair-generator/rsa-key-pair-generator.service.ts @@ -0,0 +1,25 @@ +import { pki } from 'node-forge'; + +export { generateKeyPair }; + +function generateRawPairs({ bits = 2048 }) { + return new Promise<pki.rsa.KeyPair>((resolve, reject) => + pki.rsa.generateKeyPair({ bits }, (err, keyPair) => { + if (err) { + reject(err); + return; + } + + resolve(keyPair); + }), + ); +} + +async function generateKeyPair(config: { bits?: number } = {}) { + const { privateKey, publicKey } = await generateRawPairs(config); + + return { + publicKeyPem: pki.publicKeyToPem(publicKey), + privateKeyPem: pki.privateKeyToPem(privateKey), + }; +} diff --git a/src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue b/src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue new file mode 100644 index 0000000..fbad58d --- /dev/null +++ b/src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue @@ -0,0 +1,48 @@ +<template> + <div style="flex: 0 0 100%"> + <n-space item-style="flex: 1 1 0" style="margin: 0 auto; max-width: 600px" justify="center"> + <n-form-item label="Bits :" v-bind="bitsValidationAttrs" label-placement="left" label-width="100"> + <n-input-number v-model:value="bits" min="256" max="16384" step="8" style="width: 150px" /> + </n-form-item> + </n-space> + </div> + + <div> + <h3>Public key</h3> + <textarea-copyable :value="certs.publicKeyPem" /> + </div> + + <div> + <h3>Private key</h3> + <textarea-copyable :value="certs.privateKeyPem" /> + </div> +</template> + +<script setup lang="ts"> +import TextareaCopyable from '@/components/TextareaCopyable.vue'; +import { ref } from 'vue'; +import { computedAsync } from '@vueuse/core'; +import { withDefaultOnErrorAsync } from '@/utils/defaults'; +import { useValidation } from '@/composable/validation'; +import { generateKeyPair } from './rsa-key-pair-generator.service'; + +const bits = ref(2048); +const emptyCerts = { publicKeyPem: '', privateKeyPem: '' }; + +const { attrs: bitsValidationAttrs } = useValidation({ + source: bits, + rules: [ + { + message: 'Bits should be 256 <= bits <= 16384 and be a multiple of 8', + validator: (value) => value >= 256 && value <= 16384 && value % 8 === 0, + }, + ], +}); + +const certs = computedAsync( + () => withDefaultOnErrorAsync(() => generateKeyPair({ bits: bits.value }), emptyCerts), + emptyCerts, +); +</script> + +<style lang="less" scoped></style> diff --git a/src/utils/defaults.ts b/src/utils/defaults.ts index 3d253d5..1e52b49 100644 --- a/src/utils/defaults.ts +++ b/src/utils/defaults.ts @@ -1,4 +1,4 @@ -export { withDefaultOnError }; +export { withDefaultOnError, withDefaultOnErrorAsync }; function withDefaultOnError<A, B>(cb: () => A, defaultValue: B): A | B { try { @@ -7,3 +7,11 @@ function withDefaultOnError<A, B>(cb: () => A, defaultValue: B): A | B { return defaultValue; } } + +async function withDefaultOnErrorAsync<A, B>(cb: () => A, defaultValue: B): Promise<Awaited<A> | B> { + try { + return await cb(); + } catch (_) { + return defaultValue; + } +} |