Merge d415871a61 into e876d03608
				
					
				
			This commit is contained in:
		
						commit
						4c13b3a166
					
				
							
								
								
									
										8
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -71,6 +71,7 @@ declare module '@vue/runtime-core' { | ||||
|     DiffViewer: typeof import('./src/tools/json-diff/diff-viewer/diff-viewer.vue')['default'] | ||||
|     DockerRunToDockerComposeConverter: typeof import('./src/tools/docker-run-to-docker-compose-converter/docker-run-to-docker-compose-converter.vue')['default'] | ||||
|     DynamicValues: typeof import('./src/tools/benchmark-builder/dynamic-values.vue')['default'] | ||||
|     EcdsaKeyPairGenerator: typeof import('./src/tools/ecdsa-key-pair-generator/ecdsa-key-pair-generator.vue')['default'] | ||||
|     Editor: typeof import('./src/tools/html-wysiwyg-editor/editor/editor.vue')['default'] | ||||
|     EmojiCard: typeof import('./src/tools/emoji-picker/emoji-card.vue')['default'] | ||||
|     EmojiGrid: typeof import('./src/tools/emoji-picker/emoji-grid.vue')['default'] | ||||
| @ -133,18 +134,15 @@ declare module '@vue/runtime-core' { | ||||
|     NDivider: typeof import('naive-ui')['NDivider'] | ||||
|     NEllipsis: typeof import('naive-ui')['NEllipsis'] | ||||
|     NFormItem: typeof import('naive-ui')['NFormItem'] | ||||
|     NGi: typeof import('naive-ui')['NGi'] | ||||
|     NGrid: typeof import('naive-ui')['NGrid'] | ||||
|     NH1: typeof import('naive-ui')['NH1'] | ||||
|     NH3: typeof import('naive-ui')['NH3'] | ||||
|     NIcon: typeof import('naive-ui')['NIcon'] | ||||
|     NInputNumber: typeof import('naive-ui')['NInputNumber'] | ||||
|     NLabel: typeof import('naive-ui')['NLabel'] | ||||
|     NInput: typeof import('naive-ui')['NInput'] | ||||
|     NLayout: typeof import('naive-ui')['NLayout'] | ||||
|     NLayoutSider: typeof import('naive-ui')['NLayoutSider'] | ||||
|     NMenu: typeof import('naive-ui')['NMenu'] | ||||
|     NScrollbar: typeof import('naive-ui')['NScrollbar'] | ||||
|     NSpin: typeof import('naive-ui')['NSpin'] | ||||
|     NSpace: typeof import('naive-ui')['NSpace'] | ||||
|     NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] | ||||
|     OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] | ||||
|     PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] | ||||
|  | ||||
| @ -42,6 +42,7 @@ | ||||
|     "@tiptap/starter-kit": "2.1.6", | ||||
|     "@tiptap/vue-3": "2.0.3", | ||||
|     "@types/figlet": "^1.5.8", | ||||
|     "@types/sshpk": "^1.17.4", | ||||
|     "@vicons/material": "^0.12.0", | ||||
|     "@vicons/tabler": "^0.12.0", | ||||
|     "@vueuse/core": "^10.3.0", | ||||
| @ -81,11 +82,13 @@ | ||||
|     "plausible-tracker": "^0.3.8", | ||||
|     "qrcode": "^1.5.1", | ||||
|     "sql-formatter": "^13.0.0", | ||||
|     "sshpk": "^1.18.0", | ||||
|     "ua-parser-js": "^1.0.35", | ||||
|     "ulid": "^2.3.0", | ||||
|     "unicode-emoji-json": "^0.4.0", | ||||
|     "unplugin-auto-import": "^0.16.4", | ||||
|     "uuid": "^9.0.0", | ||||
|     "vite-plugin-node-polyfills": "^0.21.0", | ||||
|     "vue": "^3.3.4", | ||||
|     "vue-i18n": "^9.9.1", | ||||
|     "vue-router": "^4.1.6", | ||||
|  | ||||
							
								
								
									
										802
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										802
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -0,0 +1,33 @@ | ||||
| import sshpk from 'sshpk'; | ||||
| 
 | ||||
| export { generateKeyPair }; | ||||
| 
 | ||||
| async function generateKeyPair(config: { | ||||
|   password?: string | ||||
|   format?: sshpk.PrivateKeyFormatType | ||||
|   curve?: sshpk.CurveType | ||||
|   comment?: string | ||||
| } = {}) { | ||||
|   const privKey = sshpk.generatePrivateKey('ecdsa', { | ||||
|     curve: config?.curve, | ||||
|   }); | ||||
|   privKey.comment = config?.comment; | ||||
| 
 | ||||
|   const pubFormat = config.format ?? 'ssh'; | ||||
|   let privFormat: sshpk.PrivateKeyFormatType = config.format ?? 'ssh'; | ||||
|   if (privFormat === 'ssh') { | ||||
|     privFormat = 'ssh-private'; | ||||
|   } | ||||
|   const pubKey = privKey.toPublic(); | ||||
|   return { | ||||
|     publicKey: pubKey.toString(pubFormat), | ||||
|     privateKey: config?.password | ||||
|       ? privKey.toString(privFormat, | ||||
|         { | ||||
|           passphrase: config?.password, | ||||
|           comment: config?.comment, | ||||
|         }, | ||||
|       ) | ||||
|       : privKey.toString(privFormat, { comment: config?.comment }), | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										100
									
								
								src/tools/ecdsa-key-pair-generator/ecdsa-key-pair-generator.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/tools/ecdsa-key-pair-generator/ecdsa-key-pair-generator.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,100 @@ | ||||
| <script setup lang="ts"> | ||||
| import type sshpk from 'sshpk'; | ||||
| import { generateKeyPair } from './ecdsa-key-pair-generator.service'; | ||||
| import TextareaCopyable from '@/components/TextareaCopyable.vue'; | ||||
| import { withDefaultOnErrorAsync } from '@/utils/defaults'; | ||||
| import { computedRefreshableAsync } from '@/composable/computedRefreshable'; | ||||
| 
 | ||||
| const password = ref(''); | ||||
| const comment = ref(''); | ||||
| const emptyCerts = { publicKey: '', privateKey: '' }; | ||||
| const curve = useStorage('ecdsa-key-pair-generator:curve', 'nistp256'); | ||||
| const curveOptions = [ | ||||
|   { value: 'nistp256', label: 'nistp256' }, | ||||
|   { value: 'nistp384', label: 'nistp384' }, | ||||
|   { value: 'nistp521', label: 'nistp521' }, | ||||
| ]; | ||||
| 
 | ||||
| const format = useStorage('ecdsa-key-pair-generator:format', 'ssh'); | ||||
| const formatOptions = [ | ||||
|   { value: 'pem', label: 'PEM' }, | ||||
|   { value: 'pkcs8', label: 'PKCS#8' }, | ||||
|   { value: 'ssh', label: 'OpenSSH Standard' }, | ||||
|   { value: 'openssh', label: 'OpenSSH New' }, | ||||
|   { value: 'putty', label: 'PuTTY' }, | ||||
| ]; | ||||
| 
 | ||||
| const supportsPassphrase = computed(() => format.value === 'ssh'); | ||||
| const [certs, refreshCerts] = computedRefreshableAsync( | ||||
|   () => withDefaultOnErrorAsync(() => generateKeyPair( | ||||
|     { | ||||
|       password: password.value, | ||||
|       format: format.value as sshpk.PrivateKeyFormatType, | ||||
|       curve: curve.value as sshpk.CurveType, | ||||
|       comment: comment.value, | ||||
|     }, | ||||
|   ), emptyCerts), | ||||
|   emptyCerts, | ||||
| ); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <div max-w-600px> | ||||
|     <n-space mb-1> | ||||
|       <c-select | ||||
|         v-model:value="format" | ||||
|         label-position="left" | ||||
|         label="Format:" | ||||
|         :options="formatOptions" | ||||
|         placeholder="Select a key format" | ||||
|       /> | ||||
| 
 | ||||
|       <c-select | ||||
|         v-model:value="curve" | ||||
|         label-position="left" | ||||
|         label="Curve:" | ||||
|         :options="curveOptions" | ||||
|         placeholder="Select a curve type" | ||||
|       /> | ||||
|     </n-space> | ||||
| 
 | ||||
|     <div v-if="supportsPassphrase" mb-1 mt-3> | ||||
|       <n-form-item label="Passphrase :" label-placement="left"> | ||||
|         <n-input | ||||
|           v-model:value="password" | ||||
|           type="password" | ||||
|           show-password-on="mousedown" | ||||
|           placeholder="Passphrase" | ||||
|         /> | ||||
|       </n-form-item> | ||||
|     </div> | ||||
| 
 | ||||
|     <div mb-2> | ||||
|       <n-form-item label="Comment :" label-placement="left"> | ||||
|         <n-input | ||||
|           v-model:value="comment" | ||||
|           type="text" | ||||
|           placeholder="Comment" | ||||
|         /> | ||||
|       </n-form-item> | ||||
|     </div> | ||||
| 
 | ||||
|     <n-space justify="center" mb-1> | ||||
|       <c-button @click="refreshCerts"> | ||||
|         Refresh key-pair | ||||
|       </c-button> | ||||
|     </n-space> | ||||
| 
 | ||||
|     <n-divider /> | ||||
| 
 | ||||
|     <div> | ||||
|       <h3>Public key</h3> | ||||
|       <TextareaCopyable :value="certs.publicKey" :word-wrap="true" /> | ||||
|     </div> | ||||
| 
 | ||||
|     <div> | ||||
|       <h3>Private key</h3> | ||||
|       <TextareaCopyable :value="certs.privateKey" /> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
							
								
								
									
										12
									
								
								src/tools/ecdsa-key-pair-generator/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/tools/ecdsa-key-pair-generator/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| import { Certificate } from '@vicons/tabler'; | ||||
| import { defineTool } from '../tool'; | ||||
| 
 | ||||
| export const tool = defineTool({ | ||||
|   name: 'ECDSA key pair generator', | ||||
|   path: '/ecdsa-key-pair-generator', | ||||
|   description: 'Generate new random ECDSA private and public keys (with or without passphrase).', | ||||
|   keywords: ['ecdsa', 'key', 'pair', 'generator', 'public', 'private', 'secret', 'ssh', 'pem', 'passphrase', 'password'], | ||||
|   component: () => import('./ecdsa-key-pair-generator.vue'), | ||||
|   icon: Certificate, | ||||
|   createdAt: new Date('2024-04-20'), | ||||
| }); | ||||
| @ -6,6 +6,7 @@ import { tool as asciiTextDrawer } from './ascii-text-drawer'; | ||||
| 
 | ||||
| import { tool as textToUnicode } from './text-to-unicode'; | ||||
| import { tool as safelinkDecoder } from './safelink-decoder'; | ||||
| import { tool as ecdsaKeyPairGenerator } from './ecdsa-key-pair-generator'; | ||||
| import { tool as pdfSignatureChecker } from './pdf-signature-checker'; | ||||
| import { tool as numeronymGenerator } from './numeronym-generator'; | ||||
| import { tool as macAddressGenerator } from './mac-address-generator'; | ||||
| @ -85,7 +86,20 @@ import { tool as yamlViewer } from './yaml-viewer'; | ||||
| export const toolsByCategory: ToolCategory[] = [ | ||||
|   { | ||||
|     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, | ||||
|       ecdsaKeyPairGenerator, | ||||
|     ], | ||||
|   }, | ||||
|   { | ||||
|     name: 'Converter', | ||||
|  | ||||
| @ -15,6 +15,7 @@ import { VitePWA } from 'vite-plugin-pwa'; | ||||
| import markdown from 'vite-plugin-vue-markdown'; | ||||
| import svgLoader from 'vite-svg-loader'; | ||||
| import { configDefaults } from 'vitest/config'; | ||||
| import { nodePolyfills } from 'vite-plugin-node-polyfills'; | ||||
| 
 | ||||
| const baseUrl = process.env.BASE_URL ?? '/'; | ||||
| 
 | ||||
| @ -97,6 +98,7 @@ export default defineConfig({ | ||||
|       resolvers: [NaiveUiResolver(), IconsResolver({ prefix: 'icon' })], | ||||
|     }), | ||||
|     Unocss(), | ||||
|     nodePolyfills(), | ||||
|   ], | ||||
|   base: baseUrl, | ||||
|   resolve: { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user