vbuch / node-signpdf

Simple signing of PDFs in node.
MIT License
730 stars 178 forks source link

Unable to sign using a p12 certificate - Error: Only 8, 16, 24, or 32 bits supported: 320 #233

Closed arenoir closed 8 months ago

arenoir commented 8 months ago

Describe the bug and the expected behaviour Unable to sign pdf using a self signed p12 certificate in node v20.9.0

Is it a bug in signing or in the helpers? It appears that @signpdf/signer-p12/dist/P12Signer.js is not able to use certificates greater than 32 bit?

To Reproduce Generate a DER encoded p12 certificate.

Attempt to sign pdf using @signpdf/signpdf, @signpdf/signer-p12, @signpdf/placeholder-pdf-lib using node v20.9.0

import { SignPdf } from '@signpdf/signpdf';
import { P12Signer } from '@signpdf/signer-p12';
import { pdflibAddPlaceholder } from '@signpdf/placeholder-pdf-lib'
import { SUBFILTER_ETSI_CADES_DETACHED } from '@signpdf/utils';
import { readFileSync } from 'fs'

const SIGNATURE_CERTIFICATE_PATH = process.env.SIGNATURE_CERTIFICATE_PATH || 'wp.der'
const CERTIFICATE = readFileSync(SIGNATURE_CERTIFICATE_PATH, 'utf8'); // This was the issue. DO NOT use utf8 encoding for reading binary files.

export async function sign(pdfDoc, signatureData) {
  pdflibAddPlaceholder({
    pdfDoc: pdfDoc,
    reason: signatureData.reason,
    contactInfo: signatureData.contactInfo,
    name: signatureData.name,
    location: signatureData.location,
    subFilter: SUBFILTER_ETSI_CADES_DETACHED,
  });

  const pdfBuffer = await pdfDoc.save()
  const signPDF = new SignPdf();

  return await signPDF.sign(pdfBuffer, signer);
}

signPDF.sign throws the following error

Error: Only 8, 16, 24, or 32 bits supported: 320
    at _checkBitsParam (/Workspace/pdf-server/node_modules/node-forge/lib/util.js:152:11)
    at util.ByteStringBuffer.getInt (/Workspace/pdf-server/node_modules/node-forge/lib/util.js:541:3)
    at _getValueLength (/Workspace/pdf-server/node_modules/node-forge/lib/asn1.js:396:20)
    at _fromDer (/Workspace/pdf-server/node_modules/node-forge/lib/asn1.js:498:16)
    at asn1.fromDer (/Workspace/pdf-server/node_modules/node-forge/lib/asn1.js:458:15)
    at P12Signer.sign (/Workspace/pdf-server/node_modules/@signpdf/signer-p12/dist/P12Signer.js:43:45)
    at SignPdf.sign (/Workspace/pdf-server/node_modules/@signpdf/signpdf/dist/signpdf.js:72:30)
    at sign (file:///Workspace/pdf-server/src/lib/pdf-lib/signature.js:38:24)
    at async default (file:///Workspace/pdf-server/src/lib/html-to-pdf-generator.js:37:15)
    at async StyleGuideRoute.render (file:///Workspace/pdf-server/src/routes/-base/route.js:169:34)

I am guessing there is something wrong with the certificate? Are there any guides on generating a valid p12 certificate?

arenoir commented 8 months ago

Forcing the encoding while reading the p12 certificate was the issue. The binary p12 bundle now works and does not need to be encoded to DER encoding.

const CERTIFICATE = readFileSync(SIGNATURE_CERTIFICATE_PATH, 'utf8');
const CERTIFICATE = readFileSync(SIGNATURE_CERTIFICATE_PATH);