Custom Remote Signing

Hello
I have some problem with custom signing in Reactjs and Nodejs. After signing, I see the notify ‘The digest is incorrect’.Anyone that could help? Thank you!
Frontend

const signDocumentWithOTP = async () => {
        const { PDFNet, documentViewer } = instance.Core
        const doc = await documentViewer.getDocument().getPDFDoc()

        // Get signature field for signing
        const field = await doc.getField(fieldName)
        const signatureField = await PDFNet.DigitalSignatureField.createFromField(field)

        // Create a digital signature dictionary inside the digital signature field
        await signatureField.createSigDictForCustomSigning(
            'Adobe.PPKLite',
            PDFNet.DigitalSignatureField.SubFilterType.e_adbe_pkcs7_detached,
            7500,
        )
        
        const currentTime = new PDFNet.Date()
        await currentTime.setCurrentTime()  
        await signatureField.setSigDictTimeOfSigning(currentTime)
        
        await doc.saveMemoryBuffer(PDFNet.SDFDoc.SaveOptions.e_incremental)
        
        const pdf_digest = await signatureField.calculateDigest(PDFNet.DigestAlgorithm.Type.e_SHA256)

        const signedAttrs = await PDFNet.DigitalSignatureField.generateCMSSignedAttributes(pdf_digest)
        console.log(signedAttrs)

        // Get certificate
        const res = await fetch('http://localhost:8000/sign/signData', {
            method: 'POST',
            body: JSON.stringify({email: user.email, data: signedAttrs}),
            headers: {
                "Accept": "application/json",
                "Content-Type": "application/json"
            }
        }).then(res => res.json()).then(async (res) => {
            if(res.success) {
                console.log(res.signature)
                const signature_value = new Uint8Array(Object.values(res.signature))
                const cert = base642arr(res.certificate);
                
                const signer_cert = await PDFNet.X509Certificate.createFromBuffer(cert)
                const chain_cert = [signer_cert]

                const digest_algorithm_oid = await PDFNet.ObjectIdentifier.createFromDigestAlgorithm(PDFNet.DigestAlgorithm.Type.e_SHA256)
                const signature_algorithm_oid = await PDFNet.ObjectIdentifier.createFromIntArray([1,2,840,113549,1,1])
                const cms_signature = await PDFNet.DigitalSignatureField.generateCMSSignature(
                    signer_cert, 
                    chain_cert,
                    digest_algorithm_oid, 
                    signature_algorithm_oid, 
                    signature_value, 
                    signedAttrs
                )
                await doc.saveCustomSignatureBuffer(cms_signature, signatureField)
            }
        })
    }
  • Backend
exports.signData = async (req, res, next) => {
    try {
        const {email, data} = req.body;
        const p12FilePath = './files/' + email + '.p12'
        const p12Asn1 = forge.asn1.fromDer(fs.readFileSync(p12FilePath, 'binary'));
        const p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, 'ejbca');

        let certificate;
        let certificates = []
        for (const safeContents of p12.safeContents) {
            for (const safeBag of safeContents.safeBags) {
                if (safeBag.type === forge.pki.oids.certBag) {
                    certificates.push(safeBag.cert);
                }
            }
        }
        const privateKey = fs.readFileSync('./files/privatekey.key')
        const publicKey = forge.pki.setRsaPublicKey(privateKey.n, privateKey.e);

        // Get certificate
        certificate = certificates[0];
        const derBytes = forge.asn1.toDer(forge.pki.certificateToAsn1(certificate)).getBytes();
        const base64Cert = forge.util.encode64(derBytes);

        // Sign data
        const uint8Array = new Uint8Array(Object.values(data));
        const signature = crypto.sign("SHA256", uint8Array, privateKey);
        const signature_value = new Uint8Array(signature)
        console.log(typeof signature_value, signature_value)

        res.json({success: true, signature: signature_value, certificate: base64Cert});
    } catch (error) {
        console.error(error);
        res.status(500).json({success: false, message: 'Server Error'});
    }
}

Hi Hyu,

I will need some additional information to assist you. Since we are working with certificates I do suggest you open a support ticket as I will need either the certificate data that is returned by the signData function to test. I do understand that you may not be able to share the certificate or share that data, would it be possible for you to create a dummy certificate that I can test with?

Can you try the following for creating the object identifier for the signature_algorithm_oid by passing in the following:
1.2.840.113549.1.1’.split(‘.’).map(o=>parseInt(o))

Please send me the following:

  1. Input file(s)
  2. Generated output file(s)
  3. Screenshots showing the output, and clearly indicating what you expected to get instead, and also clearly indicating the application/browser being used to view.
  4. Your certificate data, or a dummy certificate I can test. (I do suggest you do not post your actual certificate here but open a support ticket for this if needed.)

You can open a support ticket with us here:
https://support.apryse.com/support/tickets/new