aboutsummaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
authorGravatar Corentin THOMASSET <corentin.thomasset74@gmail.com> 2023-11-12 23:22:41 +0100
committerGravatar GitHub <noreply@github.com> 2023-11-12 22:22:41 +0000
commit478192065e6a251579a08089235ad1f26e0cc9c9 (patch)
treeb309be21ca831eaf38436f78d06101f50cec401c /src/tools
parent205e360400d588a5f9ddc9595fca29db68a07bf6 (diff)
downloadit-tools-478192065e6a251579a08089235ad1f26e0cc9c9.tar.gz
it-tools-478192065e6a251579a08089235ad1f26e0cc9c9.tar.zst
it-tools-478192065e6a251579a08089235ad1f26e0cc9c9.zip
feat(new tool): pdf signature checker (#745)
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/iban-validator-and-parser/iban-validator-and-parser.vue6
-rw-r--r--src/tools/index.ts3
-rw-r--r--src/tools/pdf-signature-checker/components/pdf-signature-details.vue99
-rw-r--r--src/tools/pdf-signature-checker/index.ts12
-rw-r--r--src/tools/pdf-signature-checker/pdf-signature-checker.e2e.spec.ts11
-rw-r--r--src/tools/pdf-signature-checker/pdf-signature-checker.types.ts39
-rw-r--r--src/tools/pdf-signature-checker/pdf-signature-checker.vue59
7 files changed, 226 insertions, 3 deletions
diff --git a/src/tools/iban-validator-and-parser/iban-validator-and-parser.vue b/src/tools/iban-validator-and-parser/iban-validator-and-parser.vue
index 647be98..6844dc5 100644
--- a/src/tools/iban-validator-and-parser/iban-validator-and-parser.vue
+++ b/src/tools/iban-validator-and-parser/iban-validator-and-parser.vue
@@ -60,9 +60,11 @@ const ibanExamples = [
<div>
<c-input-text v-model:value="rawIban" placeholder="Enter an IBAN to check for validity..." test-id="iban-input" />
- <c-key-value-list :items="ibanInfo" my-5 data-test-id="iban-info" />
+ <c-card v-if="ibanInfo.length > 0" mt-5>
+ <c-key-value-list :items="ibanInfo" data-test-id="iban-info" />
+ </c-card>
- <c-card title="Valid IBAN examples">
+ <c-card title="Valid IBAN examples" mt-5>
<div v-for="iban in ibanExamples" :key="iban">
<c-text-copyable :value="iban" font-mono :displayed-value="friendlyFormatIBAN(iban)" />
</div>
diff --git a/src/tools/index.ts b/src/tools/index.ts
index fa63d3d..52bdf8e 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 pdfSignatureChecker } from './pdf-signature-checker';
import { tool as numeronymGenerator } from './numeronym-generator';
import { tool as macAddressGenerator } from './mac-address-generator';
import { tool as textToBinary } from './text-to-binary';
@@ -78,7 +79,7 @@ import { tool as xmlFormatter } from './xml-formatter';
export const toolsByCategory: ToolCategory[] = [
{
name: 'Crypto',
- components: [tokenGenerator, hashText, bcrypt, uuidGenerator, ulidGenerator, cypher, bip39, hmacGenerator, rsaKeyPairGenerator, passwordStrengthAnalyser],
+ components: [tokenGenerator, hashText, bcrypt, uuidGenerator, ulidGenerator, cypher, bip39, hmacGenerator, rsaKeyPairGenerator, passwordStrengthAnalyser, pdfSignatureChecker],
},
{
name: 'Converter',
diff --git a/src/tools/pdf-signature-checker/components/pdf-signature-details.vue b/src/tools/pdf-signature-checker/components/pdf-signature-details.vue
new file mode 100644
index 0000000..c39f616
--- /dev/null
+++ b/src/tools/pdf-signature-checker/components/pdf-signature-details.vue
@@ -0,0 +1,99 @@
+<script setup lang="ts">
+import type { SignatureInfo } from '../pdf-signature-checker.types';
+
+const props = defineProps<{ signature: SignatureInfo }>();
+const { signature } = toRefs(props);
+
+const tableHeaders = {
+ validityPeriod: 'Validity period',
+ issuedBy: 'Issued by',
+ issuedTo: 'Issued to',
+ pemCertificate: 'PEM certificate',
+};
+
+const certs = computed(() => signature.value.meta.certs.map((certificate, index) => ({
+ ...certificate,
+ validityPeriod: {
+ notBefore: new Date(certificate.validityPeriod.notBefore).toLocaleString(),
+ notAfter: new Date(certificate.validityPeriod.notAfter).toLocaleString(),
+ },
+ certificateName: `Certificate ${index + 1}`,
+})),
+);
+</script>
+
+<template>
+ <div flex flex-col gap-2>
+ <c-table :data="certs" :headers="tableHeaders">
+ <template #validityPeriod="{ value }">
+ <c-key-value-list
+ :items="[{
+ label: 'Not before',
+ value: value.notBefore,
+ }, {
+ label: 'Not after',
+ value: value.notAfter,
+ }]"
+ />
+ </template>
+
+ <template #issuedBy="{ value }">
+ <c-key-value-list
+ :items="[{
+ label: 'Common name',
+ value: value.commonName,
+ }, {
+ label: 'Organization name',
+ value: value.organizationName,
+ }, {
+ label: 'Country name',
+ value: value.countryName,
+ }, {
+ label: 'Locality name',
+ value: value.localityName,
+ }, {
+ label: 'Organizational unit name',
+ value: value.organizationalUnitName,
+ }, {
+ label: 'State or province name',
+ value: value.stateOrProvinceName,
+ }]"
+ />
+ </template>
+
+ <template #issuedTo="{ value }">
+ <c-key-value-list
+ :items="[{
+ label: 'Common name',
+ value: value.commonName,
+ }, {
+ label: 'Organization name',
+ value: value.organizationName,
+ }, {
+ label: 'Country name',
+ value: value.countryName,
+ }, {
+ label: 'Locality name',
+ value: value.localityName,
+ }, {
+ label: 'Organizational unit name',
+ value: value.organizationalUnitName,
+ }, {
+ label: 'State or province name',
+ value: value.stateOrProvinceName,
+ }]"
+ />
+ </template>
+
+ <template #pemCertificate="{ value }">
+ <c-modal-value :value="value" label="View PEM cert">
+ <template #value>
+ <div break-all text-xs>
+ {{ value }}
+ </div>
+ </template>
+ </c-modal-value>
+ </template>
+ </c-table>
+ </div>
+</template>
diff --git a/src/tools/pdf-signature-checker/index.ts b/src/tools/pdf-signature-checker/index.ts
new file mode 100644
index 0000000..5456397
--- /dev/null
+++ b/src/tools/pdf-signature-checker/index.ts
@@ -0,0 +1,12 @@
+import { defineTool } from '../tool';
+import FileCertIcon from '~icons/mdi/file-certificate-outline';
+
+export const tool = defineTool({
+ name: 'PDF signature checker',
+ path: '/pdf-signature-checker',
+ description: 'Verify the signatures of a PDF file. A signed PDF file contains one or more signatures that may be used to determine whether the contents of the file have been altered since the file was signed.',
+ keywords: ['pdf', 'signature', 'checker', 'verify', 'validate', 'sign'],
+ component: () => import('./pdf-signature-checker.vue'),
+ icon: FileCertIcon,
+ createdAt: new Date('2023-12-09'),
+});
diff --git a/src/tools/pdf-signature-checker/pdf-signature-checker.e2e.spec.ts b/src/tools/pdf-signature-checker/pdf-signature-checker.e2e.spec.ts
new file mode 100644
index 0000000..8e9a287
--- /dev/null
+++ b/src/tools/pdf-signature-checker/pdf-signature-checker.e2e.spec.ts
@@ -0,0 +1,11 @@
+import { expect, test } from '@playwright/test';
+
+test.describe('Tool - Pdf signature checker', () => {
+ test.beforeEach(async ({ page }) => {
+ await page.goto('/pdf-signature-checker');
+ });
+
+ test('Has correct title', async ({ page }) => {
+ await expect(page).toHaveTitle('PDF signature checker - IT Tools');
+ });
+});
diff --git a/src/tools/pdf-signature-checker/pdf-signature-checker.types.ts b/src/tools/pdf-signature-checker/pdf-signature-checker.types.ts
new file mode 100644
index 0000000..6932509
--- /dev/null
+++ b/src/tools/pdf-signature-checker/pdf-signature-checker.types.ts
@@ -0,0 +1,39 @@
+export interface SignatureInfo {
+ verified: boolean
+ authenticity: boolean
+ integrity: boolean
+ expired: boolean
+ meta: {
+ certs: {
+ clientCertificate?: boolean
+ issuedBy: {
+ commonName: string
+ organizationalUnitName?: string
+ organizationName: string
+ countryName?: string
+ localityName?: string
+ stateOrProvinceName?: string
+ }
+ issuedTo: {
+ commonName: string
+ serialNumber?: string
+ organizationalUnitName?: string
+ organizationName: string
+ countryName?: string
+ localityName?: string
+ stateOrProvinceName?: string
+ }
+ validityPeriod: {
+ notBefore: string
+ notAfter: string
+ }
+ pemCertificate: string
+ }[]
+ signatureMeta: {
+ reason: string
+ contactInfo: string | null
+ location: string
+ name: string | null
+ }
+ }
+}
diff --git a/src/tools/pdf-signature-checker/pdf-signature-checker.vue b/src/tools/pdf-signature-checker/pdf-signature-checker.vue
new file mode 100644
index 0000000..0220616
--- /dev/null
+++ b/src/tools/pdf-signature-checker/pdf-signature-checker.vue
@@ -0,0 +1,59 @@
+<script setup lang="ts">
+import verifyPDF from 'pdf-signature-reader';
+import type { SignatureInfo } from './pdf-signature-checker.types';
+import { formatBytes } from '@/utils/convert';
+
+const signatures = ref<SignatureInfo[]>([]);
+const status = ref<'idle' | 'parsed' | 'error' | 'loading'>('idle');
+const file = ref<File | null>(null);
+
+async function onVerifyClicked(uploadedFile: File) {
+ file.value = uploadedFile;
+ const fileBuffer = await uploadedFile.arrayBuffer();
+
+ status.value = 'loading';
+ try {
+ const { signatures: parsedSignatures } = verifyPDF(fileBuffer);
+ signatures.value = parsedSignatures;
+ status.value = 'parsed';
+ }
+ catch (e) {
+ signatures.value = [];
+ status.value = 'error';
+ }
+}
+</script>
+
+<template>
+ <div style="flex: 0 0 100%">
+ <div mx-auto max-w-600px>
+ <c-file-upload title="Drag and drop a PDF file here, or click to select a file" accept=".pdf" @file-upload="onVerifyClicked" />
+
+ <c-card v-if="file" mt-4 flex gap-2>
+ <div font-bold>
+ {{ file.name }}
+ </div>
+
+ <div>
+ {{ formatBytes(file.size) }}
+ </div>
+ </c-card>
+
+ <div v-if="status === 'error'">
+ <c-alert mt-4>
+ No signatures found in the provided file.
+ </c-alert>
+ </div>
+ </div>
+ </div>
+
+ <div v-if="status === 'parsed' && signatures.length" style="flex: 0 0 100%" mt-5 flex flex-col gap-4>
+ <div v-for="(signature, index) of signatures" :key="index">
+ <div mb-2 font-bold>
+ Signature {{ index + 1 }} certificates :
+ </div>
+
+ <pdf-signature-details :signature="signature" />
+ </div>
+ </div>
+</template>