Skip to content

Commit 8617af9

Browse files
committed
Merge branch 'feat/ecdsa-keygen' into chore/all-my-stuffs
# Conflicts: # components.d.ts # package.json # pnpm-lock.yaml # src/tools/index.ts # vite.config.ts
2 parents 8e373d2 + d415871 commit 8617af9

File tree

5 files changed

+150
-0
lines changed

5 files changed

+150
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
"@types/figlet": "^1.5.8",
100100
"@types/markdown-it": "^13.0.7",
101101
"@types/figlet": "^1.5.8",
102+
"@types/sshpk": "^1.17.4",
102103
"@vicons/material": "^0.12.0",
103104
"@vicons/tabler": "^0.12.0",
104105
"@vueuse/core": "^10.11.1",
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import sshpk from 'sshpk';
2+
3+
export { generateKeyPair };
4+
5+
async function generateKeyPair(config: {
6+
password?: string
7+
format?: sshpk.PrivateKeyFormatType
8+
curve?: sshpk.CurveType
9+
comment?: string
10+
} = {}) {
11+
const privKey = sshpk.generatePrivateKey('ecdsa', {
12+
curve: config?.curve,
13+
});
14+
privKey.comment = config?.comment;
15+
16+
const pubFormat = config.format ?? 'ssh';
17+
let privFormat: sshpk.PrivateKeyFormatType = config.format ?? 'ssh';
18+
if (privFormat === 'ssh') {
19+
privFormat = 'ssh-private';
20+
}
21+
const pubKey = privKey.toPublic();
22+
return {
23+
publicKey: pubKey.toString(pubFormat),
24+
privateKey: config?.password
25+
? privKey.toString(privFormat,
26+
{
27+
passphrase: config?.password,
28+
comment: config?.comment,
29+
},
30+
)
31+
: privKey.toString(privFormat, { comment: config?.comment }),
32+
};
33+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<script setup lang="ts">
2+
import type sshpk from 'sshpk';
3+
import { generateKeyPair } from './ecdsa-key-pair-generator.service';
4+
import TextareaCopyable from '@/components/TextareaCopyable.vue';
5+
import { withDefaultOnErrorAsync } from '@/utils/defaults';
6+
import { computedRefreshableAsync } from '@/composable/computedRefreshable';
7+
8+
const password = ref('');
9+
const comment = ref('');
10+
const emptyCerts = { publicKey: '', privateKey: '' };
11+
const curve = useStorage('ecdsa-key-pair-generator:curve', 'nistp256');
12+
const curveOptions = [
13+
{ value: 'nistp256', label: 'nistp256' },
14+
{ value: 'nistp384', label: 'nistp384' },
15+
{ value: 'nistp521', label: 'nistp521' },
16+
];
17+
18+
const format = useStorage('ecdsa-key-pair-generator:format', 'ssh');
19+
const formatOptions = [
20+
{ value: 'pem', label: 'PEM' },
21+
{ value: 'pkcs8', label: 'PKCS#8' },
22+
{ value: 'ssh', label: 'OpenSSH Standard' },
23+
{ value: 'openssh', label: 'OpenSSH New' },
24+
{ value: 'putty', label: 'PuTTY' },
25+
];
26+
27+
const supportsPassphrase = computed(() => format.value === 'ssh');
28+
const [certs, refreshCerts] = computedRefreshableAsync(
29+
() => withDefaultOnErrorAsync(() => generateKeyPair(
30+
{
31+
password: password.value,
32+
format: format.value as sshpk.PrivateKeyFormatType,
33+
curve: curve.value as sshpk.CurveType,
34+
comment: comment.value,
35+
},
36+
), emptyCerts),
37+
emptyCerts,
38+
);
39+
</script>
40+
41+
<template>
42+
<div max-w-600px>
43+
<n-space mb-1>
44+
<c-select
45+
v-model:value="format"
46+
label-position="left"
47+
label="Format:"
48+
:options="formatOptions"
49+
placeholder="Select a key format"
50+
/>
51+
52+
<c-select
53+
v-model:value="curve"
54+
label-position="left"
55+
label="Curve:"
56+
:options="curveOptions"
57+
placeholder="Select a curve type"
58+
/>
59+
</n-space>
60+
61+
<div v-if="supportsPassphrase" mb-1 mt-3>
62+
<n-form-item label="Passphrase :" label-placement="left">
63+
<n-input
64+
v-model:value="password"
65+
type="password"
66+
show-password-on="mousedown"
67+
placeholder="Passphrase"
68+
/>
69+
</n-form-item>
70+
</div>
71+
72+
<div mb-2>
73+
<n-form-item label="Comment :" label-placement="left">
74+
<n-input
75+
v-model:value="comment"
76+
type="text"
77+
placeholder="Comment"
78+
/>
79+
</n-form-item>
80+
</div>
81+
82+
<n-space justify="center" mb-1>
83+
<c-button @click="refreshCerts">
84+
Refresh key-pair
85+
</c-button>
86+
</n-space>
87+
88+
<n-divider />
89+
90+
<div>
91+
<h3>Public key</h3>
92+
<TextareaCopyable :value="certs.publicKey" :word-wrap="true" />
93+
</div>
94+
95+
<div>
96+
<h3>Private key</h3>
97+
<TextareaCopyable :value="certs.privateKey" />
98+
</div>
99+
</div>
100+
</template>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Certificate } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'ECDSA key pair generator',
6+
path: '/ecdsa-key-pair-generator',
7+
description: 'Generate new random ECDSA private and public keys (with or without passphrase).',
8+
keywords: ['ecdsa', 'key', 'pair', 'generator', 'public', 'private', 'secret', 'ssh', 'pem', 'passphrase', 'password'],
9+
component: () => import('./ecdsa-key-pair-generator.vue'),
10+
icon: Certificate,
11+
createdAt: new Date('2024-04-20'),
12+
});

src/tools/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ import { tool as textToUnicode } from './text-to-unicode';
109109
import { tool as csrGenerator } from './csr-generator';
110110
import { tool as dockerRunToKubernetesConverter } from './docker-run-to-kubernetes';
111111
import { tool as dockerComposeValidator } from './docker-compose-validator';
112+
import { tool as ecdsaKeyPairGenerator } from './ecdsa-key-pair-generator';
112113
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
113114
import { tool as numeronymGenerator } from './numeronym-generator';
114115
import { tool as macAddressGenerator } from './mac-address-generator';
@@ -240,6 +241,9 @@ export const toolsByCategory: ToolCategory[] = [
240241
csrGenerator,
241242
passwordStrengthAnalyser,
242243
pdfSignatureChecker,
244+
passwordStrengthAnalyser,
245+
pdfSignatureChecker,
246+
ecdsaKeyPairGenerator,
243247
],
244248
},
245249
{

0 commit comments

Comments
 (0)