在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. C++ 虚函数的内部实现

    C++ 虚函数的内部实现 虚函数看起来是个玄之又玄的东西,但其实特别简单!了解了虚函数的内部实现,关于虚函数的各种问题都不在话下啦! 1. 知识储备 阅读这篇文章,你需要事先了解以下几个概念: 什么是 ...

  2. 前端 | JS Promise:axios 请求结果后面的 .then() 是什么意思?

    Promise 是JS中一种处理异步操作的机制,在现在的前端代码中使用频率很高.Promise 这个词可能有点眼生,但你肯定见过 axios.get(...).then(res => {...} ...

  3. Python | random 模块:Python 中如何生成随机数和随机抽样?

    random 是平时开发过程中常用的一个模块,该模块实现了各种分布的伪随机数生成器,以及和随机数相关的各种实用函数.基本函数 random() 在区间 [0.0, 1.0) 内均匀生成随机浮点数,是模 ...

  4. 一文带大家彻底搞懂Hystrix!

    前言? Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种实现,用 ...

  5. 使用Vscode 开发调试 C/C++ 项目

    需要安装的扩展 C/C++ 如果是远程 Linux上开发还需要安装 Remote Development 创建工作目录后,代码远程克隆... 省略.. 创建项目配置文件,主要的作用是代码智能提示,错误 ...

  6. 【洛谷】P1294 高手去散步

    题目背景 高手最近谈恋爱了.不过是单相思."即使是单相思,也是完整的爱情",高手从未放弃对它的追求.今天,这个阳光明媚的早晨,太阳从西边缓缓升起.于是它找到高手,希望在晨读开始之前 ...

  7. Python基础(二十):面向对象“类”第三课——类成员

    知识点: 类属性与实例属性: 类方法与实例方法: 静态方法: 类属性与实例属性 类属性与实例属性的区别 属性的绑定不同 类属性与当前类相关(绑定的是当前类),与当前类创建的任何对象无关: 实例属性与当 ...

  8. oo第四单元总结及总课程回顾

    一.第四单元架构设计 1.第一次作业 第一次作业要求实现的只有对类图的分析.为了直观地搭建出一个类图,我新建了Manager类来处理UmlElement以及搭建树.但由于未能做好时间管理,因此第一次作 ...

  9. Vue3 封装第三方组件(一)做一个合格的传声筒

    各种UI库的功能都是非常强大的,尤其对于我这种不会 css 的人来说,就更是帮了大忙了. 只是嘛,如果再封装一下的话,那么用起来就会更方便了. 那么如何封装呢? 封装三要素 -- 属性.插槽.事件.方 ...

  10. TLS Poison - When TLS Hack you

    0x00 前言 本次学习的是2020 Blackhat 的一篇文章When TLS Hacks you,简单来说,作者提出了一种新的SSRF攻击思路:利用DNS重绑定和TLS协议的会话恢复进行攻击.具 ...