在PDF添加签名时,支持添加可信时间戳来保证文档的法律效应。本文,将通过C#程序代码介绍如何添加可信时间戳,可通过2种方法来实现。文中附上VB.NET代码,有需可供参考。

一、程序运行环境

  • 编译环境:Visual Studio/.NetFramework 4.8
  • 所需测试文件:PDF、.pfx数字证书及秘钥、PDF类库(spire.pdf.dll 7.5.7)
  • 可信时间戳服务器:URL地址

:VS程序中,在“解决方案资源管理器中”先引用spire.pdf.dll文件,如下图,

这里可以通过Nuget下载该文件。或者在手动下载引用,dll文件在下载后的文件包BIN文件夹下,如本次测试使用的是.NET4.0下面的dll,即spire.pdf_7.5.7\BIN\NET4.0\Spire.Pdf.dll,如图:

二、程序代码

添加签名时,这里可分别通过两个类来实现,即PdfSignature 和 PdfOrdinarySignatureMaker类。下面分别以两个代码示例展示如何签名并添加时间戳。

1. 通过PdfSignature类来签名,添加时间戳

C#

using Spire.Pdf;
using Spire.Pdf.Security;
using System.Drawing; namespace TimeStamp
{
class Program
{
static void Main(string[] args)
{
//加载PDF文档
PdfDocument pdf = new PdfDocument();
pdf.LoadFromFile("sample.pdf"); //获取第2页
PdfPageBase page = pdf.Pages[1]; //加载数字证书(.pfx文件及秘钥)
PdfCertificate cert = new PdfCertificate("test.pfx", "123456"); //加载签名图片
Spire.Pdf.Graphics.PdfImage image = Spire.Pdf.Graphics.PdfImage.FromFile("sign.png"); //添加与图片大小相同的签名到第2页指定坐标位置
PdfSignature signature = new PdfSignature(page.Document, page, cert, "sign1");//添加数字签名
signature.Bounds = new RectangleF(new PointF(400,700), new SizeF(image.Width, image.Height));//设置签名的页面坐标位置、大小与图片相同
signature.SignImageSource = image;
signature.GraphicsMode = Spire.Pdf.Security.GraphicMode.SignImageAndSignDetail;//设置签名为图片模式
signature.SignImageLayout = Spire.Pdf.Security.SignImageLayout.Stretch;
signature.DocumentPermissions = Spire.Pdf.Security.PdfCertificationFlags.AllowFormFill | Spire.Pdf.Security.PdfCertificationFlags.AllowComments;//文档权限 //配置时间戳服务器,添加时间戳
string url = "Your TimeStamp Server URL";
signature.ConfigureTimestamp(url);
//signature.ConfigureTimestamp(url, "Author", "123654");//添加时间戳时设置用户名和密码 //保存文档
pdf.SaveToFile("TimeStamp1.pdf",FileFormat.PDF);
System.Diagnostics.Process.Start("TimeStamp1.pdf");
}
}
}

VB.NET

Imports Spire.Pdf
Imports Spire.Pdf.Security
Imports System.Drawing Namespace TimeStamp
Class Program
Private Shared Sub Main(args As String())
'加载PDF文档
Dim pdf As New PdfDocument()
pdf.LoadFromFile("sample.pdf") '获取第2页
Dim page As PdfPageBase = pdf.Pages(1) '加载数字证书(.pfx文件及秘钥)
Dim cert As New PdfCertificate("test.pfx", "123456") '加载签名图片
Dim image As Spire.Pdf.Graphics.PdfImage = Spire.Pdf.Graphics.PdfImage.FromFile("sign.png") '添加与图片大小相同的签名到第2页指定坐标位置
Dim signature As New PdfSignature(page.Document, page, cert, "sign1") '添加数字签名
signature.Bounds = New RectangleF(New PointF(400, 700), New SizeF(image.Width, image.Height)) '设置签名的页面坐标位置、大小与图片相同
signature.SignImageSource = image
signature.GraphicsMode = Spire.Pdf.Security.GraphicMode.SignImageAndSignDetail '设置签名为图片模式
signature.SignImageLayout = Spire.Pdf.Security.SignImageLayout.Stretch
signature.DocumentPermissions = Spire.Pdf.Security.PdfCertificationFlags.AllowFormFill Or Spire.Pdf.Security.PdfCertificationFlags.AllowComments'文档权限 '配置时间戳服务器,添加时间戳
Dim url As String = "Your TimeStamp Server URL"
signature.ConfigureTimestamp(url)
'signature.ConfigureTimestamp(url, "Author", "123654");//添加时间戳时设置用户名和密码 '保存文档
pdf.SaveToFile("TimeStamp1.pdf", FileFormat.PDF)
System.Diagnostics.Process.Start("TimeStamp1.pdf")
End Sub
End Class
End Namespace

签名时间戳添加结果:

2. 通过PdfOrdinarySignatureMaker类来签名,添加时间戳

C#

using Spire.Pdf;
using Spire.Pdf.Graphics;
using Spire.Pdf.Interactive.DigitalSignatures;
using System.Drawing;
using System.Security.Cryptography.X509Certificates; namespace TimeStamp2
{
class Program
{
static void Main(string[] args)
{
//加载PDF文档
PdfDocument doc = new PdfDocument();
doc.LoadFromFile("sample.pdf"); //加载pfx数字证书及秘钥
X509Certificate2 x509 = new X509Certificate2("test.pfx", "123456"); //实例化PdfPKCS7Formatter类的对象
PdfPKCS7Formatter formatter = new PdfPKCS7Formatter(x509, false);
formatter.TimestampService = new TSAHttpService("Your TimeStamp Server URL");//配置时间戳服务器 //添加签名
PdfOrdinarySignatureMaker signatureMaker = new PdfOrdinarySignatureMaker(doc, formatter);
IPdfSignatureAppearance signatureAppearance = new PdfCustomSignatureAppearance();
signatureMaker.MakeSignature("sign", doc.Pages[1], 400, 650, 150, 80, signatureAppearance); //保存签名后的PDF文档
doc.SaveToFile("TimeStamp2.pdf", FileFormat.PDF);
System.Diagnostics.Process.Start("TimeStamp2.pdf"); }
public class PdfCustomSignatureAppearance : IPdfSignatureAppearance
{
public void Generate(PdfCanvas canvas)
{
PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("Arial", 12), true);
canvas.DrawString("SIGNED! A CLASS.\n By Tom Smith", font, PdfBrushes.Red, new PointF(0, 0));
}
}
}
}

VB.NET

Imports Spire.Pdf
Imports Spire.Pdf.Graphics
Imports Spire.Pdf.Interactive.DigitalSignatures
Imports System.Drawing
Imports System.Security.Cryptography.X509Certificates Namespace TimeStamp2
Class Program
Private Shared Sub Main(args As String())
'加载PDF文档
Dim doc As New PdfDocument()
doc.LoadFromFile("sample.pdf") '加载pfx数字证书及秘钥
Dim x509 As New X509Certificate2("test.pfx", "123456") '实例化PdfPKCS7Formatter类的对象
Dim formatter As New PdfPKCS7Formatter(x509, False)
formatter.TimestampService = New TSAHttpService("Your TimeStamp Server URL")
'配置时间戳服务器 '添加签名
Dim signatureMaker As New PdfOrdinarySignatureMaker(doc, formatter)
Dim signatureAppearance As IPdfSignatureAppearance = New PdfCustomSignatureAppearance()
signatureMaker.MakeSignature("sign", doc.Pages(1), 400, 650, 150, 80, _
signatureAppearance) '保存签名后的PDF文档
doc.SaveToFile("TimeStamp2.pdf", FileFormat.PDF)
System.Diagnostics.Process.Start("TimeStamp2.pdf") End Sub
Public Class PdfCustomSignatureAppearance
Implements IPdfSignatureAppearance
Public Sub Generate(canvas As PdfCanvas)
Dim font As New PdfTrueTypeFont(New Font("Arial", 12), True)
canvas.DrawString("SIGNED! A CLASS." & vbLf & " By Tom Smith", font, PdfBrushes.Red, New PointF(0, 0))
End Sub
End Class
End Class
End Namespace

签名时间戳添加结果:

以上是本文关于如何在C#程序中给PDF签名添加时间戳的方法。

内容原创,如需转载请务必注明出处!

C# 给PDF签名时添加时间戳的2种方法(附VB.NET代码)的更多相关文章

  1. Java 给PDF签名时添加可信时间戳

    一.程序运行环境 编译环境:IntelliJ IDEA 所需测试文件:PDF..pfx数字证书及密钥.PDF Jar包(Free Spire.PDF for Java).签名图片(.png格式) 可信 ...

  2. Linux添加系统调用的两种方法

    前言 系统调用的基本原理 系统调用其实就是函数调用,只不过调用的是内核态的函数,但是我们知道,用户态是不能随意调用内核态的函数的,所以采用软中断的方式从用户态陷入到内核态.在内核中通过软中断0X80, ...

  3. Apache shiro集群实现 (八) web集群时session同步的3种方法

    Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...

  4. 给Repeater控件里添加序号的5种方法

    Repeater是我们经常用的一个显示数据集的数据控件,经常我们希望在数据前显示数据的序号,那么我们该怎么为Repeater控件添加序号呢?下面编辑为大家介绍几种常用的为Repeater控件添加序号的 ...

  5. mysql 中添加索引的三种方法

    原文:http://www.andyqian.com/2016/04/06/database/mysqleindex/ 在mysql中有多种索引,有普通索引,全文索引,唯一索引,多列索引,小伙伴们可以 ...

  6. delphi TreeView 从数据库添加节点的四种方法

    方法一:delphi中递归算法构建treeView 过程:通过读取数据库中table1的数据,来构建一颗树.table1有两个字段:ID,preID,即当前结点标志和父结点标志.所以整个树的表示为父母 ...

  7. Cocos Creator 为Button添加事件的两种方法

    Button添加事件 Button 目前只支持 Click 事件,即当用户点击并释放 Button 时才会触发相应的回调函数.通过脚本代码添加回调方法一这种方法添加的事件回调和使用编辑器添加的事件回调 ...

  8. 【转】web集群时session同步的3种方法

    转载请注明作者:海底苍鹰地址:http://blog.51yip.com/server/922.html 在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问 ...

  9. web集群时session同步的3种方法[转]

    在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,一个登录用户,一会是登录状态,一会又不是 ...

随机推荐

  1. RabbitMQ 入门 (Go) - 3. 模拟传感器,生成数据并发布

    现在,我们需要模拟传感器,生成数据,并发布到 RabbitMQ. 建立传感器项目 在 GOPATH src 下建立文件夹 sensors,使用 go mod init 初始化,并创建 main.go. ...

  2. Redis系列-存储篇list主要操作命令

    Redis系列-存储篇list主要操作命令小结 在总结list之前,先要弄明白几个跟list相关的概念: 列表:一个从左到右的队列,个人理解更类似于一个栈,常规模式下,先进列表的元素,后出. 表头元素 ...

  3. 结对编程-stage_2

    教学班 罗杰.任建班周五3.4节 gitlab项目地址 Here it is. 成员 周远航(3004) 李辰洋(3477) 结对编程体验 经过了上一阶段的磨合,第二阶段我们的配合更加流畅,也熟悉了对 ...

  4. JMeter5.4.1源码IDEA构建&二次开发(实战)

    JMeter5.4.1源码IDEA构建&二次开发(实战) 目录 JMeter5.4.1源码IDEA构建&二次开发(实战) 1.下载源码 2.导入IDEA 2.1 先设置Gradle目录 ...

  5. 通过Dapr实现一个简单的基于.net的微服务电商系统(二)——通讯框架讲解

    首先感谢张队@geffzhang公众号转发了上一篇文章,希望广大.neter多多推广dapr,让云原生更快更好的在.net这片土地上落地生根. 目录:一.通过Dapr实现一个简单的基于.net的微服务 ...

  6. 使用Vue-TreeSelect组件实现公司-部门-人员级联下拉列表的处理

    最近在改造原有Bootstrap开发框架,增加一个Vue&Element前端的时候,发现需要处理一个级联更新的过程,就是选择公司,然后更新部门,选择部门,或者人员列表,选择作为主管的一个实现, ...

  7. 1.稀疏数组_java实现

    稀疏数组 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组. 稀疏数组的处理方法是: 记录数组一共有几行几列,有多少个不同的值 把具有不同值的元素行列及值记录在一个小规 ...

  8. Mediapipe 在RK3399PRO上的初探(二)(自定义Calculator)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  9. ASP.NET Core扩展库之Http请求模拟

    如今,完全独立的业务应用几乎不存在,不管是在企业内部微服务之间的调用,还是与外部第三方服务的调用,Http的API交互是常见的场景,这些实际情况给我们的开发带来了比较大的挑战,一是第三方服务可能会牵制 ...

  10. 【cypress】5. 测试本地web应用

    在之前的cypress介绍里曾提到过,cypress虽然也可以测试部署好的应用,但是它最大的能力还是发挥在测试本地应用上. 本章主要内容就是关于如何测试本地web应用的概述: cypress与后台应用 ...