diff --git a/package.json b/package.json index 218a5228..b2abf225 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "naive-ui": "^2.35.0", "netmask": "^2.0.2", "node-forge": "^1.3.1", + "openpgp": "^5.11.1", "oui-data": "^1.0.10", "pdf-signature-reader": "^1.4.2", "pinia": "^2.0.34", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4e215fd7..69b021d3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -128,6 +128,9 @@ dependencies: node-forge: specifier: ^1.3.1 version: 1.3.1 + openpgp: + specifier: ^5.11.1 + version: 5.11.1 oui-data: specifier: ^1.0.10 version: 1.0.10 @@ -4182,7 +4185,6 @@ packages: inherits: 2.0.4 minimalistic-assert: 1.0.1 safer-buffer: 2.1.2 - dev: true /asn1@0.2.6: resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} @@ -4307,7 +4309,6 @@ packages: /bn.js@4.12.0: resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} - dev: true /bn.js@5.2.1: resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} @@ -7281,7 +7282,6 @@ packages: /minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: true /minimalistic-crypto-utils@1.0.1: resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} @@ -7595,6 +7595,13 @@ packages: is-wsl: 2.2.0 dev: true + /openpgp@5.11.1: + resolution: {integrity: sha512-TynUBPuaSI7dN0gP+A38CjNRLxkOkkptefNanalDQ71BFAKKm+dLbksymSW5bUrB7RcAneMySL/Y+r/TbLpOnQ==} + engines: {node: '>= 8.0.0'} + dependencies: + asn1.js: 5.4.1 + dev: false + /optionator@0.8.3: resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} engines: {node: '>= 0.8.0'} @@ -10071,6 +10078,7 @@ packages: /workbox-google-analytics@7.0.0: resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} + deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained dependencies: workbox-background-sync: 7.0.0 workbox-core: 7.0.0 diff --git a/src/tools/certificate-key-parser/certificate-key-parser.vue b/src/tools/certificate-key-parser/certificate-key-parser.vue index 7f54f70e..12d617d8 100644 --- a/src/tools/certificate-key-parser/certificate-key-parser.vue +++ b/src/tools/certificate-key-parser/certificate-key-parser.vue @@ -15,6 +15,7 @@ import type { PrivateKey, Signature, SignatureFormatType, } from 'sshpk'; import { Base64 } from 'js-base64'; +import * as openpgp from 'openpgp'; import { useDownloadFileFromBase64 } from '@/composable/downloadBase64'; function buf2Hex(buffer: ArrayBuffer) { // buffer is an ArrayBuffer @@ -59,7 +60,7 @@ interface LabelValue { value: string multiline?: boolean } -const parsedSections = computed(() => { +const parsedSections = computedAsync(async () => { try { certificateX509DER.value = ''; const onErrorReturnErrorMessage = (func: () => any) => { @@ -78,6 +79,14 @@ const parsedSections = computed(() => { return null; } }; + const canParseAsync = async (value: string | Buffer, parseFunction: (value: string | Buffer) => Promise) => { + try { + return await parseFunction(value); + } + catch { + return null; + } + }; const inputKeyOrCertificateValue = inputKeyOrCertificate.value !== '' ? inputKeyOrCertificate.value @@ -263,6 +272,74 @@ const parsedSections = computed(() => { ] as LabelValue[]; } + const pgpPrivateKey = await canParseAsync(inputKeyOrCertificateValue, value => openpgp.readPrivateKey({ armoredKey: value.toString() })) as openpgp.Key; + if (pgpPrivateKey) { + return [ + { + label: 'Type: ', + value: 'PGP Private Key', + }, + { + label: ': ', + value: pgpPrivateKey.getCreationTime().toString(), + }, + { + label: ': ', + value: (await pgpPrivateKey.getExpirationTime())?.toString() || '', + }, + { + label: 'Algorithm Info: ', + value: JSON.stringify(pgpPrivateKey.getAlgorithmInfo()), + }, + { + label: 'Fingerprint: ', + value: pgpPrivateKey.getFingerprint(), + }, + { + label: 'User ID(s): ', + value: pgpPrivateKey.getUserIDs().join(', '), + }, + { + label: 'Key ID(s): ', + value: pgpPrivateKey.getKeyIDs().map(k => k.toString()).join(' ; '), + }, + ] as LabelValue[]; + } + + const pgpPublicKey = await canParseAsync(inputKeyOrCertificateValue, value => openpgp.readKey({ armoredKey: value.toString() })) as openpgp.Key; + if (pgpPublicKey) { + return [ + { + label: 'Type: ', + value: 'PGP Public Key', + }, + { + label: ': ', + value: pgpPublicKey.getCreationTime().toString(), + }, + { + label: ': ', + value: (await pgpPublicKey.getExpirationTime())?.toString() || '', + }, + { + label: 'Algorithm Info: ', + value: JSON.stringify(pgpPublicKey.getAlgorithmInfo()), + }, + { + label: 'Fingerprint: ', + value: pgpPublicKey.getFingerprint(), + }, + { + label: 'User ID(s): ', + value: pgpPublicKey.getUserIDs().join(', '), + }, + { + label: 'Key ID(s): ', + value: pgpPublicKey.getKeyIDs().map(k => k.toString()).join(' ; '), + }, + ] as LabelValue[]; + } + const signature = canParse(inputKeyOrCertificateValue, (value) => { // for (const algo of ['dsa', 'rsa', 'ecdsa', 'ed25519']) {