数字签名是如何工作的

本文介绍了PKI体系结构及代码签名的过程,包括确保代码完整性和安全性的方式,以及如何通过证书机构验证发布者的公钥。

以前我也做过 pki related task, 也明白签名还有 ssl, certificate 这些技术,

 

但是,对于具体的逻辑,还不是太明白,

近日在看jvm 安全性的章节的时候,看到了通俗,浅显的描述,

 

然后,理解了整个体系,

我想,以后如果有人向我问的话,我应该也是可以解释明白的,对吧,

那就说明我真的理解了,对自己探究的一个奖赏。:)

 

真实需求

首先,我们从一个需求说起,

比如,一个人写了一些applet code, 我们称呼他,发布者,

然后,其他一些人,需要使用和在浏览器运行applet,

那些人,怎么能信任这个applet, 并且运行,而不是担心安全而拒绝呢,

 

1, 如何保证完整性

 

首先,我们要保证发布的jar 是完整的,而不是被别人篡改的,

那么我们就,在jar 中包含两部分,

一个是 source class, 还有基于source class 产生的一个散列,比如md5, etc.

那样,下载的人,一比较 jar 和散列值,就能保持完整性了。

 

比如一些例子,

 

apache tomcat下载网站,提供下载,同时提供校验的 asc 和 md5.

 

2, 如何防止篡改

 

别人可能将 jar 内容和 散列一起改掉,再发送给用户。

 

怎么办呢,

将 散列值,用发布者的私钥,加密,然后发布出去自己的公钥,这样别人

就可以根据得到的公钥,来判断是否是没有更改。

 

解决上面两个问题的图,如下,

 

签名过程

 

首先有一段代码,需要打包成 jar,同时,你要有一个公钥/私钥对, 

通过 java, jarsigner, 数字签名,具体就是对 jar 内容,产生散列,

将散列,用私钥加密

然后,将 jar 内容和加密过的散列一起发送

 

验证过程

接收到jar 和加密的散列,和得到的发布者的公钥,

先用公钥解压散列,和通过jar生成的散列比较,

如果相同,就通过验证。

 

3, 如何安全,正确发布自己的公钥

 

但是,现在有了新问题,

用户怎么能得到发布者的公钥,而且保证没有被改过, 就是伪造?

假设有个 hack, 将 jar 包改了,用一个新的公钥/私钥对加密,并把新的公钥伪装成最初的发布者的,那怎么办?

 

这就引入了,pki 体系结构,

 

这时,就需要成立一些证书机构,

发布者,提交自己的公钥,并且自己的一些信息,比如地址,电话,公司名称,

然后,这些证书机构用自己的私钥来加密,

将发布者的公钥,发布成签名证书,附上,经过认证的发布者的一些信息。

 

然后,用户,就可以download 那个证书,

并和证书机构自己的证书,来做验证。

 

体系结构

 

就是这样一个信任机制,

当然,有一些顶级的证书机构,

他们的私钥,是保存在很安全的保险机构的,

如果他们签的证书,出了问题,他们是要负赔偿责任的。

 

一级一级机构,

这个和我们现实中的,是一个原理,

 

 

现实系统的参考

 

正如一位名人说的,任何虚拟系统的设计,都有其现实的参考, 

这个也不例外,也就是,所说的隐喻。

 

比如我们一个人,从老家到北京,

那么要开一个介绍信,

那么北京那边为什么可以信任呢,

 

因为,北京那边信任,那个人所在的省级机构,那个省级机构信任地区,县,和地方机构,

一级一级信任,就得到了这个信任链,

 

 

这就是,pki 体系结构的现实参考。:)

 

未完待续,

 

参考深入 JVM 虚拟机第二版,3.7 代码签名和认证。

 

数字签名工作流程主要包含签名生成和签名验证两个阶段: ### 签名生成阶段 1. **生成密钥对**:使用非对称加密算法(如 RSA、ECC 等)生成一对密钥,即私钥和公钥。私钥由签名者秘密保存,公钥则可以公开。 2. **计算消息摘要**:对要签名的消息使用哈希函数(如 SHA - 256)计算出消息的摘要。哈希函数会将任意长度的消息转换为固定长度的摘要,不同的消息通常会产生不同的摘要。 3. **使用私钥加密摘要**:签名者使用自己的私钥对计算得到的消息摘要进行加密加密后的结果就是数字签名。 以下是一个使用 Python 的`cryptography`库生成数字签名的示例代码: ```python from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import rsa, padding from cryptography.hazmat.primitives import hashes # 生成私钥 private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend() ) # 获取公钥 public_key = private_key.public_key() # 待签名的消息 message = b"Hello, World!" # 计算消息摘要并签名 signature = private_key.sign( message, padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256() ) ``` ### 签名验证阶段 1. **接收消息和签名**:接收者收到消息和对应的数字签名。 2. **计算消息摘要**:接收者使用与签名者相同的哈希函数对收到的消息计算摘要。 3. **使用公钥解密签名**:接收者使用签名者的公钥对数字签名进行解密,得到签名者计算的消息摘要。 4. **比较摘要**:将自己计算的消息摘要与解密得到的消息摘要进行比较,如果两者相同,则签名验证通过,说明消息在传输过程中未被篡改,且确实是由持有对应私钥的签名者发出的;否则,签名验证失败。 以下是验证数字签名的示例代码: ```python try: public_key.verify( signature, message, padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256() ) print("签名验证成功") except: print("签名验证失败") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值