You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过iTextSharp在PDF签名时显示证书主题与颁发者信息

How to Display Certificate Subject & Issuer on PDF Signature with iTextSharp

Hey there! Great job getting the basic digital signature working with iTextSharp. Let's adjust your code to show certificate details like subject name and issuer directly on the signed PDF. Here's how to do it step by step:

1. Extract Clean Certificate Details First

The raw Subject and Issuer properties from your X509Certificate2 are Distinguished Name (DN) strings (like CN=John Doe, OU=IT, O=Company). We'll add a helper method to extract the common name (CN) for a cleaner, more user-friendly display:

private static string GetCommonNameFromDN(string distinguishedName)
{
    foreach (string segment in distinguishedName.Split(','))
    {
        string trimmedSegment = segment.Trim();
        if (trimmedSegment.StartsWith("CN=", StringComparison.OrdinalIgnoreCase))
        {
            return trimmedSegment.Substring(3);
        }
    }
    // Fallback to full DN if CN isn't found
    return distinguishedName;
}

2. Customize the Signature Appearance Layer

iTextSharp's PdfSignatureAppearance has editable layers—Layer 2 is where you can add custom text and graphics. We'll use this layer to inject our certificate details.

Update your signature appearance setup section with this code:

PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = Properties.Settings.Default.DigitalSignReason;
appearance.Location = Properties.Settings.Default.DigitalSignLocation;
appearance.Contact = Properties.Settings.Default.DigitalSignContact;

if (Properties.Settings.Default.DigitalSignAppearance == 1) {
    appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(20, 10, 170, 60), 1, "Signed");
}

// --- Add these lines to display certificate info ---
// Get the customizable layer (Layer 2)
PdfTemplate signatureLayer = appearance.GetLayer(2);

// Set up a readable font for the text
BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
Font textFont = new Font(baseFont, 8);

// Build the certificate info text (customize this format as needed)
string subjectCN = GetCommonNameFromDN(cert.Subject);
string issuerCN = GetCommonNameFromDN(cert.Issuer);
string signatureText = $"签名者: {subjectCN}\n颁发机构: {issuerCN}\n原因: {appearance.Reason}\n位置: {appearance.Location}";

// Add the text to the layer (adjust X/Y to fit your signature rectangle)
ColumnText.ShowTextAligned(
    signatureLayer,
    Element.ALIGN_LEFT,
    new Phrase(signatureText, textFont),
    15, // X position inside the signature box
    15, // Y position inside the signature box
    0
);

// Tell iText to use our custom layer instead of default text
appearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.CUSTOM;
// --- End of custom certificate info code ---

// Also, switch to SHA-256 (SHA-1 is no longer cryptographically secure)
IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA-256");
MakeSignature.SignDetached(appearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);

Key Notes:

  • Coordinates: The X/Y values in ShowTextAligned are relative to your signature rectangle (the one you defined with new Rectangle(20, 10, 170, 60)). Tweak them to ensure your text fits neatly without overflow.
  • Text Flexibility: You can expand signatureText to include more certificate details (like validity dates) by pulling properties directly from the cert object (e.g., cert.NotBefore.ToString("yyyy-MM-dd")).
  • Security Upgrade: I replaced SHA-1 with SHA-256 because SHA-1 is now considered insecure. Most modern systems require SHA-2 or higher for valid digital signatures.

Modified Full Sign Method

Here's your complete Sign method with all changes integrated:

public static X509Certificate2 cert; //Sign with certificate selection in the windows certificate store
public static void Sign(string pdfFile, string outPdfFile){
    Program.WriteLog("Signing Digital Certificate");
    string IssuerName = null;
    X509Store store = new X509Store(StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly);
    IssuerName = Properties.Settings.Default.IssuerName;
    if (IssuerName.Length > 0)
        cert = store.Certificates.Find(X509FindType.FindByIssuerName, IssuerName, false)[0];
    if (cert == null) {
        //manually chose the certificate in the store
        X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(store.Certificates, null, null, X509SelectionFlag.SingleSelection);
        if (sel.Count > 0)
            cert = sel[0];
        else {
            Console.WriteLine("Certificate not found");
            return;
        }
    }
    PdfReader reader = new PdfReader(pdfFile); // source pdf file
    FileStream os = new FileStream(outPdfFile, FileMode.Create); //the output pdf file
    PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
    stamper.SetEncryption(PdfWriter.STRENGTH128BITS, "", null, PdfWriter.AllowCopy | PdfWriter.AllowPrinting);
    try {
        Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser();
        Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] { cp.ReadCertificate(cert.RawData) };
        // Use SHA-256 for secure signing
        IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA-256");
        PdfSignatureAppearance appearance = stamper.SignatureAppearance;
        //here set signatureAppearance at your will
        appearance.Reason = Properties.Settings.Default.DigitalSignReason;
        appearance.Location = Properties.Settings.Default.DigitalSignLocation;
        appearance.Contact = Properties.Settings.Default.DigitalSignContact;
        if (Properties.Settings.Default.DigitalSignAppearance == 1) {
            appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(20, 10, 170, 60), 1, "Signed");
        }

        // Customize signature layer to show certificate details
        PdfTemplate signatureLayer = appearance.GetLayer(2);
        BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
        Font textFont = new Font(baseFont, 8);
        
        string subjectCN = GetCommonNameFromDN(cert.Subject);
        string issuerCN = GetCommonNameFromDN(cert.Issuer);
        string signatureText = $"签名者: {subjectCN}\n颁发机构: {issuerCN}\n原因: {appearance.Reason}\n位置: {appearance.Location}";
        
        ColumnText.ShowTextAligned(
            signatureLayer,
            Element.ALIGN_LEFT,
            new Phrase(signatureText, textFont),
            15,
            15,
            0
        );
        
        appearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.CUSTOM;

        MakeSignature.SignDetached(appearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);
    }catch(Exception e){
        Console.WriteLine(e.Message, 1);
        File.Delete(outPdfFile);
    } finally {
        if (reader != null) reader.Close();
        if (stamper != null) stamper.Close();
        if (os != null) os.Close();
    }
}

private static string GetCommonNameFromDN(string distinguishedName)
{
    foreach (string segment in distinguishedName.Split(','))
    {
        string trimmedSegment = segment.Trim();
        if (trimmedSegment.StartsWith("CN=", StringComparison.OrdinalIgnoreCase))
        {
            return trimmedSegment.Substring(3);
        }
    }
    return distinguishedName;
}

内容的提问来源于stack exchange,提问作者Timothy Yu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:54:44