From 30e9149d61c30206d080cf5c88d8cde1a282476c Mon Sep 17 00:00:00 2001 From: Corentin Thomasset Date: Fri, 10 Mar 2023 18:16:55 +0100 Subject: [PATCH] feat(new-tool): RSA key pair generator --- package.json | 2 + pnpm-lock.yaml | 15 ++++++ src/tools/index.ts | 3 +- src/tools/rsa-key-pair-generator/index.ts | 11 +++++ .../rsa-key-pair-generator.service.ts | 25 ++++++++++ .../rsa-key-pair-generator.vue | 48 +++++++++++++++++++ src/utils/defaults.ts | 10 +++- 7 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 src/tools/rsa-key-pair-generator/index.ts create mode 100644 src/tools/rsa-key-pair-generator/rsa-key-pair-generator.service.ts create mode 100644 src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue diff --git a/package.json b/package.json index ea29f119..30fea760 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "mathjs": "^10.6.4", "mime-types": "^2.1.35", "naive-ui": "^2.33.5", + "node-forge": "^1.3.1", "pinia": "^2.0.23", "plausible-tracker": "^0.3.8", "qrcode": "^1.5.1", @@ -73,6 +74,7 @@ "@types/lodash": "^4.14.188", "@types/mime-types": "^2.1.1", "@types/node": "^16.18.3", + "@types/node-forge": "^1.3.1", "@types/qrcode": "^1.5.0", "@types/randombytes": "^2.0.0", "@types/uuid": "^8.3.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 36161e10..49ce4c88 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,7 @@ specifiers: '@types/lodash': ^4.14.188 '@types/mime-types': ^2.1.1 '@types/node': ^16.18.3 + '@types/node-forge': ^1.3.1 '@types/qrcode': ^1.5.0 '@types/randombytes': ^2.0.0 '@types/uuid': ^8.3.4 @@ -50,6 +51,7 @@ specifiers: mathjs: ^10.6.4 mime-types: ^2.1.35 naive-ui: ^2.33.5 + node-forge: ^1.3.1 pinia: ^2.0.23 plausible-tracker: ^0.3.8 prettier: ^2.7.1 @@ -96,6 +98,7 @@ dependencies: mathjs: 10.6.4 mime-types: 2.1.35 naive-ui: 2.33.5_vue@3.2.45 + node-forge: 1.3.1 pinia: 2.0.23_oankqy72ltdeevri3bqxeckw3m plausible-tracker: 0.3.8 qrcode: 1.5.1 @@ -114,6 +117,7 @@ devDependencies: '@types/lodash': 4.14.188 '@types/mime-types': 2.1.1 '@types/node': 16.18.3 + '@types/node-forge': 1.3.1 '@types/qrcode': 1.5.0 '@types/randombytes': 2.0.0 '@types/uuid': 8.3.4 @@ -1732,6 +1736,12 @@ packages: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: true + /@types/node-forge/1.3.1: + resolution: {integrity: sha512-hvQ7Wav8I0j9amPXJtGqI/Yx70zeF62UKlAYq8JPm0nHzjKKzZvo9iR3YI2MiOghZRlOI+tQ2f6D+G6vVf4V2Q==} + dependencies: + '@types/node': 17.0.45 + dev: true + /@types/node/16.18.3: resolution: {integrity: sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==} dev: true @@ -5278,6 +5288,11 @@ packages: tslib: 2.4.1 dev: false + /node-forge/1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + dev: false + /node-releases/2.0.6: resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} dev: true diff --git a/src/tools/index.ts b/src/tools/index.ts index 6ad328f8..18208ddb 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 00000000..c8ab4cdb --- /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 00000000..a41d5cdc --- /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((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 00000000..fbad58d3 --- /dev/null +++ b/src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/src/utils/defaults.ts b/src/utils/defaults.ts index 3d253d54..1e52b495 100644 --- a/src/utils/defaults.ts +++ b/src/utils/defaults.ts @@ -1,4 +1,4 @@ -export { withDefaultOnError }; +export { withDefaultOnError, withDefaultOnErrorAsync }; function withDefaultOnError(cb: () => A, defaultValue: B): A | B { try { @@ -7,3 +7,11 @@ function withDefaultOnError(cb: () => A, defaultValue: B): A | B { return defaultValue; } } + +async function withDefaultOnErrorAsync(cb: () => A, defaultValue: B): Promise | B> { + try { + return await cb(); + } catch (_) { + return defaultValue; + } +}