Hello,
I’m applying a digital signature to a PDF document but the resulting file is not compliant with government requirements.
The signature itself is valid but it lacks 2 requirements to be legally binding:
- the hash algorithm for the document contents should be at least SHA256, now it is SHA1 (see “DigestMethod” at https://archive.org/details/iso-32000-2-2020-sponsored/ISO_32000-2-2020_sponsored/page/545/mode/2up)
- SHA256 is required as per PDF 2.0 spec
- this post seems to raise the same issue but it is related to the java version:
PDFJAVA-43333
- the signer info attribute “contentType” (https://datatracker.ietf.org/doc/html/draft-ietf-sidr-res-certs-14#page-37) is either invalid or missing (I’m not sure which is the case)
This is a sample of the C# (.net 4.x) code used:
bool isFirstInvocation = true;
pdfFileSignature.Sign(
page: 1,
visible: false,
annotRect: System.Drawing.Rectangle.Empty,
sig: new ExternalSignature(publicCertX509)
{
CustomSignHash = (digestHash /*<= THIS HASH IS SHA1 */) =>
{
if (isFirstInvocation) // The function is called 2 times
{
// What is the first hash?
// - LTV should hash the whole document, not multiple ranges
// - will this hash always be the first one, could a new parameter
// be added to the function to avoid future problems?
isFirstInvocation = !isFirstInvocation;
return new byte[0];
}
return EXTERNA_PROVIDER.RawSignSHA256withRSA(digestHash);
},
TimestampSettings = new TimestampSettings(
tsaUrl,
$"{tsaUserName}:{tsaPassword}",
DigestHashAlgorithm.Sha256
)
}
);
Am I doing something wrong?
Thanks in advance.
@usernameisalreadyinuse
We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.
Issue ID(s): PDFNET-58018
You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.
Hi, @usernameisalreadyinuse!
Recently, the ability to specify a digest algorithm for ExternalSignature was added.
You can use the ExternalSignature class for an external signing service. ExternalSignature creates PKCS7 and PKCS7 detached signatures.
You can pass the desired hashing algorithm to the ExternalSignature constructor. Note that non-detached signatures can only use SHA1.
It will be chosen automatically if you do not explicitly specify the hashing algorithm. For non-detached signatures, it will be SHA1; for detached, it will be SHA-256 for an RSA key. For an ECDSA key, the hash size depends on the key size.
The ExternalSignature constructor also accepts a key certificate (it can be in Base64 format). You can pass a certificate containing a private key and a certificate containing only a public key.
In either case, the signature will be performed externally in the CustomSignHash delegate code, but the external algorithm must create a signature corresponding to the key of the passed certificate.
The certificate is needed to correctly generate the signed document.
ECDSA signature does not support SHA-11.
var inputPdf = "";
var outputPdf = "";
using (var sign = new PdfFileSignature())
{
sign.BindPdf(inputPdf);
X509Certificate2 signerCert = GetPublicCertificate();
var signature = new ExternalSignature(signerCert, DigestHashAlgorithm.Sha256);
SignHash customSignHash = delegate(byte[] signableHash, DigestHashAlgorithm digestHashAlgorithm)
{
return CallExternalSignatureService(signableHash, digestHashAlgorithm);
};
signature.CustomSignHash = customSignHash;
sign.Sign(1, "reason", "cont", "loc", false, new System.Drawing.Rectangle(0, 0, 500, 500), signature);
sign.Save(outputPdf);
}