目录
1.数字签名
1.1 概念
数字签名,就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。--摘自百度百科。其实本质上是为了解决消息验证的无法引入第三方公正缺陷问题而创造的一种方式,它用到的技术非常简单:
信息发送者利用非对称加密私钥来对数据哈希值进行加密,然后将公钥公布,这样一来所有获得公钥的人都能够证明信息发送者真的发送了这条数据。这样不论是信息发送者对原始数据作出了修改,还是不承认这条数据发送,持有公钥的人们都能够轻而易举的识别出信息发送者的毁约操作;而同时不论信息遭到怎样的窃取篡夺,因为持有公钥的人们总是能够轻而易举识别出篡改后的信息哈希值与原信息的哈希值不同,进而保护了信息发送者信息数据的安全。可以说数字签名的出现直接解决了消息验证当中无法引入第三方公正的缺陷问题。
1.2 原理
由于数据发送方使用的是私钥加密,所以所有持有对应公钥的人都能够对这个数据进行解密进而进行签名校验。但是由于使用公钥解密出来的数据仍然是加密数据,必须使用对应的特殊key来解密才能真正得到明文内容,而这个特殊key是只有Frank和Alex拥有的。所以其他人尽管能够下载到Frank的公钥进行签名签证的第三方证明人,能够看到签名中的原始数据密文,但是仍旧无法真正看到密文背后真正的内容。
此时,既然每个人都能持有公钥,那么就意味着Frank私自对原始数据作出任何修改都会导致数字签名变更。此时每一位持有公钥的用户对数字签名进行再次验证就会失败,所以Amy此时充当了Alex的证明人。从另一方面来说如果Alex毁约不承认Frank曾经对其发送过数据或者数据曾经被篡改,那么Amy此时依然可以充当Frank的证明人,因为Frank的确发送了数据,所以Amy的再次验证是能够成功的。这就是数字签名第三方公正的原理。
1.3 实现
经过刚才的原理分析,我们能够显然发现go语言中如果想要实现数字签名就必须实现非对称加密的密钥对的分发功能。非对称加密方式常见有两种:一种就是大名鼎鼎的RSA算法(我之前的文章中提到过),而另一种则是椭圆曲线(虽然很少听到但非常犀利,第二代人民币就是用这种方式加密的)。比较让人头大的地方在于:
- go语言只提供了RSA算法的非对称加密接口,而没有提供椭圆曲线的非对称加密接口!
- 然而go语言却同时提供了RSA算法的数字签名接口,和椭圆曲线的数字签名接口。
这就意味着我们尽管在进行非对称加密操作的时候不能使用go语言一睹椭圆曲线的风采,但是可以直接调用现成的接口来进行椭圆曲线的数字签名功能。这不得不说是一次来自大佬的深深的鄙视(估计是怕公开给我们我们也不会...),所以本篇只讨论RSA数字签名。
2.go语言实现RSA数字签名
2.1 数字签名【签名-核验】流程
2.1.1 使用rsa包生成密钥对
- 使用rsa包内的GenerateKey函数来生成密钥对,其中公钥数据保存在私钥数据中
- 使用x509包内的Marshal方法,将密钥信息序列化为ASN.1标准的DER编码字串(公钥私钥的Marshal方法不同)
- 使用pem包内的数据模型构建pem.Block数据块
- 使用pem包内的Encode方法将pem.Block数据块写入本地文件
2.1.2 使用私钥对信息进行数字签名
- 使用os.Open打开私钥文件后,使用Read读取文件内容存入缓冲区