Peng's Blog

Peng's Blog

马上订阅 Peng's Blog RSS 更新: https://pengs.top/atom.xml

在命令行中使用自签名证书对PDF进行签名

2024年7月3日 10:22

!! 本文代码已上传Github 使用GPL-3.0协议开源 !!

有天我打开网上的PDF文件时,看到这样一行提示:

此文档已经过数字签名

我大惊,我平时会用GPG对文件进行签名,但得到的也只是一个单独的签名文件。难道,GPG创建的签名可以嵌入PDF?我想起以前在Windows上用PDF Reader时见过“签名”菜单,但是那看起来只是手绘了个图形贴上去,看上去好像也不高级,背后好像也没有特别的算法撑腰。这个“数字签名”却有证书,有颁发日期,到期时间,SHA-256指纹,和签名算法,看起来很专业,就像访问HTTPS站点时的SSL证书。

我决定要给自己的PDF也加上这样的数字签名,最好能有个很有信服力的图章,上面写着“signed by Pengbo”。

我在网上展开搜索,却发现linux下,好像少有这样的进行签名的工具,KDE的PDF查看器Okular有这个功能,但它找不到我的证书(恼

那就只能另寻办法啦。

我在网上搜查到的信息告诉我PDF签名需要S/MIME证书,一般由权威CA颁发,价格在……

等等!我签名自己的文件还要付钱?不可能!

CA创建S/MIME证书总要用一些工具吧,我能不能用这样的工具创建自签名证书

这一工具就是openssl,自己建过网站的人应该对它不陌生,处理HTTPS时多少会碰到。OpenSSL 是一个用于实现安全通信的软件包,它由一组密码学函数库组成。它的主要目标是通过使用公开的密码学算法来保护数据的机密性、完整性和身份验证。它支持对称加密、非对称加密、数字签名、证书管理等功能。

背景知识了解的差不多了,动手吧!

生成

如果你没有openssl这个软件包,请安装它。

首先生成自己的私钥(不知道什么意思的话可以查查非对称加密

1
openssl genrsa -aes128 -out myself.key 2048

-aes128 表示用AES128算法加密私钥,可选的还有-aes192,-aes2562048表示私钥长度,越长越安全,但也越慢,我一般用4096位的。

1
openssl req -new -days 365 -key myself.key -out myself.csr

这个命令创建证书请求,正常情况下,你应该把这个证书请求发送给CA的工作人员,但今天我们要自己签发,这个待会儿再说。

-days 表示证书有效期,我太懒了,这辈子都不想换,疯狂加0,现在过期时间在34世纪。(这辈子用不完了

别学我,这样不太“正规”,我给你的示例,有效期是1年。

你可能会问:有效期只有一年,那一年以后数字签名是不是就不能验证了呢?别怕,后面我们利用时间戳解决这个问题。

1
openssl x509 -in myself.csr -out myself.crt -req -signkey myself.key -days 365

这一步本该由CA做的,可是贫穷提高了我们的计算机水平,我们现在要自己签发。signkey后面就是我们自己的私钥,如果你像让证书看起来更逼真,可以先自建CA,再用自建CA的私钥签发自己的私钥创建的证书请求,你可以在网上找到教程。

-days参数依然是有效期。

这一步后,你得到了一个x509证书,你可以用它来加密,签名,但是,我们用于PDF签名的证书需要是 PKCS#12 格式的,所以再转下格式。

1
openssl pkcs12 -export -out myself.pfx -inkey myself.key -in myself.crt

没什么特别的。

至此,myself.pfx已经可以用于PDF签名了,你可以将这一pfx证书导入Kleopatra(需另外安装),然后打开Okular,在设置>配置后端程序>PDF>签名后端程序选中GnuPG,然后就可以用工具>数字签名了。(当然这是我后来才发现的)

签名

经过艰苦的搜查,我尝试了pdftkpdfsig等工具,都不太行。

最后我找到了pyhanko,一个专门用于签章pdf的python包,先安装它。

可以用pip安装:

1
pip install pyhanko[opentype]

[opentype]表示安装opentype可选项,因为我们要生成可见签章,需要处理字体问题。

然后,上大招:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64...

剩余内容已隐藏

查看完整文章以阅读更多