当前位置: 首页 > 知识库问答 >
问题:

从时间戳服务器丢失时间戳的签名pdf

谢财
2023-03-14

我尝试使用外部Web服务对pdf进行数字签名。此Web服务包含用户证书,用户可以使用他们的凭据和一次性密码生成的代码访问该证书。

旁注:web服务应该期望pdf摘要(哈希),但奇怪的是,它却接受整个文件。

无论如何,实现如下:

using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;

// OTP = One Time Password code
public void SignPdf(string username, string password, string otp)
{
    byte[] file = GetFileFromPath("D:\test.pdf");
    var fieldName = "signatureField";
    string tempFilePath = "D:\test1temp.pdf");

    using (var pdfReader = new PdfReader(file))
    {
        using (var signedPdf = new FileStream(tempFilePath, FileMode.Create))
        {
            using (var pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '\0', null, true);
            {
                // Prepare signature
                PdfDate date = new PdfDate();
                var fullSignDate = date.GetW3CDate();
                var signDate = fullSignDate.Substring(0, fullSignDate.IndexOf("T"));
                var signTime = fullSignDate.Substring(fullSignDate.IndexOf("T") + 1);
                var signatureAppearance = pdfStamper.SignatureAppearance;
                signatureAppearance.SetVisibleSignature(fieldName);
                signatureAppearance.Layer2Text=($"Digitally signed by: Test User");

                // Get font
                signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;
                signatureAppearance.CryptoDictionary = GetPdfSignature(signatureAppearance);
                signatureAppearance.PreClose(new Dictionary<PdfName, int> { [PdfName.CONTENTS] = 8192 * 2 + 2 });

                // Get file content as base64 string
                var ms = new MemoryStream();
                signatureAppearance.GetRangeStream().CopyTo(ms);
                fileAsBase64 = ms.ToArray();

                // Sign hash (the "hash" is the whole document)
                signature = GetSignedHash(Convert.ToBase64String(fileAsBase64), username, password, otp);

                if (signature != null)
                {
                    EmbedSignatureToPdf(signatureAppearance, signatureWithTimeStamp);
                    success = true;
                }
            }
        }
    }
}

private static PdfDictionary GetPdfSignature(PdfSignatureAppearance sa)
{
    return new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED)
    {
        Reason = sa.Reason,
        Location = sa.Location,
        SignatureCreator = sa.SignatureCreator,
        Contact = sa.Contact,
        Date = new PdfDate(sa.SignDate)
    };
}

private byte[] GetSignedHash(string hash, string username, string password, string otp)
{
    // Call external web service and get a the signed hash
}

private void EmbedSignatureToPdf(PdfSignatureAppearance signatureAppearance, byte[] signature)
{
    var array = new byte[8192];
    Array.Copy(signature, 0, array, 0, signature.Length);
    var pdfDictionary = new PdfDictionary();
    pdfDictionary.Put(PdfName.CONTENTS, new PdfString(array).SetHexWriting(true));
    signatureAppearance.Close(pdfDictionary);
}

pdf已成功签名,但使用Adobe Reader并检查签名字段时,似乎缺少可信时间戳,如图所示:

看起来,来自远程服务的响应是一个签名对象,我只需要将其嵌入到PDF文件中。

我的问题是:由于我收到的签名不包含来自时间戳服务器的时间戳,我是否可以在此时嵌入这样的时间戳,或者远程 Web 服务应该在将签名发送给我之前添加它?

谢谢大家!

共有1个答案

唐运诚
2023-03-14

由于我收到的签名不包含来自时间戳服务器的时间戳,我是否可以在此时嵌入这样的时间戳,或者远程web服务是否应该在将签名发送给我之前添加时间戳?

这样的时间戳作为未签名的属性被添加到签名容器中。因为它们是未签名的,所以签名容器中未签名的属性可以在应用签名后被改变,例如,可以添加额外的属性。

因此,您自己尤其可以向从您的服务中检索到的签名容器添加时间戳。

但是,根据您签名的性质,您可能需要增加在pdf中创建的占位符的大小,以便为额外的时间戳提供足够的空间。

 类似资料:
  • 我知道这是一个非常常见的问题,但我觉得我找到的答案并没有真正解决问题。我将概述我的具体用例,并对来自其他SO答案和网络的信息进行总结。 对于我正在编写的服务,数据库条目被创建并存储在移动设备和我们的网站上,需要以两种方式同步。我们目前的目标是Android和iOS,它们都使用sqlite作为关系数据库。服务器端是使用Django和MySQL在Python中实现的,但将来可能会有其他解决方案取代它。

  • 我在使用可信时间戳创建Bouncy Castle的有效CMS签名时遇到了问题。签名创建工作正常(我想将签名包含到PDF文件中),签名是有效的。但是在我将可信时间戳包含到签名的无符号属性表后,签名仍然有效,但是读者报告签名包括嵌入的时间戳,但它是无效的。这让我相信,哈希I时间戳不是正确的,但我似乎无法弄清楚它的问题。 签署代码: 代码: : 谢谢你的帮助! 示例文件: 签名PDF 未签名的PDF 用

  • 我有一个Flink程序,它接受两个流,即数据/传感器读数流和警报规则流。我正在广播规则流,并将其连接到数据流以生成动态警报。ProcessingTime的一切都很好,但EventTime却不行。我已经分配了时间戳 > 当两个流(即带有时间戳的流)同时出现时,如何使用“EventTime”生成警报 我是否也必须为我的规则流分配时间戳和水印? 因为我的规则流只有在有任何添加/修改时才会有记录。是否有任

  • 本文向大家介绍sqlite时间戳转时间语句(时间转时间戳),包括了sqlite时间戳转时间语句(时间转时间戳)的使用技巧和注意事项,需要的朋友参考一下 下面是具体的实现代码:

  • 程序的一个通常需求是计算从Unix起始时间开始到某个时刻的秒数,毫秒数,微秒数等。 我们来看看Go里面是怎么做的。 package main import "fmt" import "time" func main() { // 使用Unix和UnixNano来分别获取从Unix起始时间 // 到现在所经过的秒数和微秒数 now := time.Now() secs

  • 我正在尝试使用Joda在一个简单的Java程序中获取UTC时间戳: 程序输出如下: 毫秒值是正确的UTC时间(即用时区确认)第二个值是时区。 我需要的是UTC值不变为(即独立于TZ),用于数据库写入。这可能吗? 我知道是本地日期(GMT-4),是UTC(GMT-0)。日期的输出值如下: 我尝试了所有组合,试图将的UTC值作为java.sql.TimeStamp: 用于测试的打印输出: 第一行是正确