Skip to content

Commit b942b46

Browse files
committed
Merge branch 'feat/pgp-keygen' into chore/all-my-stuffs
# Conflicts: # components.d.ts # pnpm-lock.yaml # src/tools/index.ts
2 parents 95a83fe + aa0f705 commit b942b46

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed

pnpm-lock.yaml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/tools/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ import { tool as markdownEditor } from './markdown-editor';
128128
import { tool as nanoMemo } from './nano-memo';
129129
import { tool as option43Generator } from './option43-generator';
130130
import { tool as pgpEncryption } from './pgp-encryption';
131+
import { tool as pgpKeygen } from './pgp-keygen';
131132
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
132133
import { tool as numeronymGenerator } from './numeronym-generator';
133134
import { tool as macAddressGenerator } from './mac-address-generator';
@@ -274,6 +275,9 @@ export const toolsByCategory: ToolCategory[] = [
274275
passwordStrengthAnalyser,
275276
pdfSignatureChecker,
276277
pgpEncryption,
278+
passwordStrengthAnalyser,
279+
pdfSignatureChecker,
280+
pgpKeygen,
277281
],
278282
},
279283
{

src/tools/pgp-keygen/index.ts

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: 'PGP keygen',
6+
path: '/pgp-key-pair-generator',
7+
description: 'Generate new random PGP private and public keys (with or without passphrase).',
8+
keywords: ['pgp', 'key', 'pair', 'generator', 'public', 'private', 'secret', 'ssh', 'pem', 'passphrase', 'password'],
9+
component: () => import('./pgp-keygen.vue'),
10+
icon: Certificate,
11+
createdAt: new Date('2024-04-20'),
12+
});

src/tools/pgp-keygen/pgp-keygen.vue

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<script setup lang="ts">
2+
import * as openpgp from 'openpgp';
3+
import TextareaCopyable from '@/components/TextareaCopyable.vue';
4+
import { useValidation } from '@/composable/validation';
5+
import { computedRefreshableAsync } from '@/composable/computedRefreshable';
6+
7+
const bits = ref(4096);
8+
const username = ref('');
9+
const useremail = ref('');
10+
const password = ref('');
11+
12+
const format = useStorage('pgp-key-pair-generator:format', 'curve25519');
13+
const formats = [
14+
'rsa',
15+
'curve25519',
16+
'ed25519',
17+
'p256', 'p384', 'p521',
18+
'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1',
19+
'secp256k1',
20+
];
21+
22+
const { attrs: bitsValidationAttrs } = useValidation({
23+
source: bits,
24+
rules: [
25+
{
26+
message: 'Bits should be 256 <= bits <= 16384 and be a multiple of 8',
27+
validator: value => value >= 256 && value <= 16384 && value % 8 === 0,
28+
},
29+
],
30+
});
31+
32+
const [certs, refreshCerts] = computedRefreshableAsync(
33+
async () => {
34+
const formatValue = format.value;
35+
const passphrase = password.value;
36+
const name = username.value;
37+
const email = useremail.value;
38+
const rsaBits = bits.value;
39+
40+
try {
41+
if (format.value === 'rsa') {
42+
const { privateKey, publicKey } = await openpgp.generateKey({
43+
type: 'rsa', // Type of the key
44+
rsaBits, // RSA key size (defaults to 4096 bits)
45+
userIDs: [{ name, email }], // you can pass multiple user IDs
46+
passphrase, // protects the private key
47+
format: 'armored',
48+
});
49+
50+
return { privateKey, publicKey, revocationCertificate: '' };
51+
}
52+
53+
const { privateKey, publicKey, revocationCertificate } = await openpgp.generateKey({
54+
type: 'ecc', // Type of the key, defaults to ECC
55+
curve: formatValue as openpgp.EllipticCurveName, // ECC curve name, defaults to curve25519
56+
userIDs: [{ name, email }], // you can pass multiple user IDs
57+
passphrase, // protects the private key
58+
format: 'armored',
59+
});
60+
return { privateKey, publicKey, revocationCertificate };
61+
}
62+
catch (e: any) {
63+
return { privateKey: `#${e.toString()}`, publicKey: `#${e.toString()}`, revocationCertificate: '' };
64+
}
65+
}, { privateKey: '', publicKey: '', revocationCertificate: '' },
66+
);
67+
</script>
68+
69+
<template>
70+
<div>
71+
<div mb-4>
72+
<div style="flex: 0 0 100%">
73+
<div item-style="flex: 1 1 0" style="max-width: 600px" mx-auto flex gap-3>
74+
<c-select
75+
v-model:value="format"
76+
label-position="left"
77+
label="Format:"
78+
:options="formats"
79+
placeholder="Select a key format"
80+
/>
81+
82+
<n-form-item v-if="format === 'rsa'" label="RSA Bits :" v-bind="bitsValidationAttrs as any" label-placement="left">
83+
<n-input-number v-model:value="bits" min="256" max="16384" step="8" />
84+
</n-form-item>
85+
</div>
86+
</div>
87+
</div>
88+
89+
<div>
90+
<n-form-item label="User Name :" label-placement="left">
91+
<n-input
92+
v-model:value="username"
93+
type="text"
94+
placeholder="User Name"
95+
/>
96+
</n-form-item>
97+
<n-form-item label="User Email :" label-placement="left">
98+
<n-input
99+
v-model:value="useremail"
100+
:input-props="{ type: 'email' }"
101+
placeholder="User Email"
102+
/>
103+
</n-form-item>
104+
105+
<n-form-item label="Passphrase :" label-placement="left">
106+
<n-input
107+
v-model:value="password"
108+
type="password"
109+
show-password-on="mousedown"
110+
placeholder="Passphrase"
111+
/>
112+
</n-form-item>
113+
114+
<div text-center>
115+
<c-button @click="refreshCerts">
116+
Refresh key-pair
117+
</c-button>
118+
</div>
119+
</div>
120+
121+
<div>
122+
<h3>Public key</h3>
123+
<TextareaCopyable :value="certs?.publicKey || ''" word-wrap="true" />
124+
</div>
125+
126+
<div>
127+
<h3>Private key</h3>
128+
<TextareaCopyable :value="certs?.privateKey || ''" word-wrap="true" />
129+
</div>
130+
131+
<div>
132+
<h3>Revocation Certificate</h3>
133+
<TextareaCopyable :value="certs?.revocationCertificate || ''" word-wrap="true" />
134+
</div>
135+
</div>
136+
</template>

0 commit comments

Comments
 (0)