一、为什么要签名校验
在一般对外的http接口加签的目的是防止数据被串改!
举个例子,A正在某银行网站给B转账,转入卡号和金额输入完成后生成请求报文,然后加密报文传送给银行后台。银行收到请求后,解密得到明文,然后解析得到B的卡号和转账金额等信息,继续走后续转账流程。
如果传输使用对称加密算法(最常用的),客户端和服务端都是用同一个对称密钥,那么这个对称密钥就存在泄露的可能性。一旦泄露,攻击者X可以截获正常的报文,解密后替换卡号和金额,然后重新用同一个密钥加密被篡改的报文,发送给银行。银行解密后得到的是攻击者X的卡号,然后A的钱就到了X的账户了。
二、签名校验原理
1、散列(Hash)
Hash,一般翻译做"散列",也直接音译为"哈希",就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值。常用的散列函数是SHA1和MD5。哈希是单向的,不可通过散列值得到原文(不可逆)。
不同的内容做散列计算,计算出的散列值为相同的概率几乎等于0;
哈希主要用在:文件校验、数字签名、快速查找等。
例如,文件校验:
2、对称加密
需要对加密和解密使用相同密钥的加密算法。由于其速度快,对称性加密通常在消息发送方需要加密大量数据时使用。但是管理密钥不方便,要求共享密钥。如果N个人相互之间都要用对称加密进行通讯,则每个人维护的密钥是N-1个。
目前流行的对称加密算法有AES、DES、3DES、Blowfish、RC2、RC4、RC5等等。
3、非对称加密
与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。非对称加密算法的优点是密钥管理很方便,缺点是速度慢。
通常来讲,公钥是每个人都能得到的,私钥是只有自己持有;
A与B之间进行通信,安全的方式:
(1)A给B发送消息,使用B的公钥进行加密,然后发给B,只有B用私钥才能解密成明文;
(2)B给A发送消息,使用A的公钥进行加密,然后发给A,只有A用私钥才能解密成明文;
A获取B的公钥,必须是安全的方式;B获取A的公钥,也必须是安全的方式;
4、数字签名
现实生活中,我们用签名来证明某个东西是与签名者相关的,是不可否认的,不可伪造的;
在虚拟世界里,我们有数字签名来帮助证明某个文档是你创建的,或者是你认可的。数字签名所用的技术是散列和非对称加密。
基于前面非对称加密的介绍,对签名的信息进行散列计算,用私钥对这个散列值进行加密;这样就得到一个签名。
当用户B比对散列值3与散列值2是否相同,如果相同则认为是A签名的,否则不是。
三、正确的做法
签名,其实就是给报文做个摘要(哈希)。而且相同的签名算法得到的摘要是相同的,比如MD5,SHA1等。简单的加签并不能真正的防篡改,因为攻击者可以篡改后,自己生成新的签名。服务端验签还是可以通过的。所以加签一定要包含一些特殊的私有的东西,比如个人私钥。
摘录一段签名的具体做法
首先是环境:
发消息方A、接受消息方B、一个需要发送的消息段[merNo=001,user=zhangm,pwd=abc123,check=6387]、证书生成工具tools.jar
过程:
1、使用工具生成根证书,用户证书。
a. 填写工具配置信息。tools会根据消息交互双方的信息+密码生成两个证书,其中双方的信息不重要,重要的是密码。即:保存密码。
b. tools会生成一个密钥库,密钥库的密码是上一步设置的密码。然后tools还会生成一个密钥对,即公钥和私钥。然后将公钥和私钥存放到密钥库中。最后tools会生成两个证书文件:根证书【可以得到公钥和私钥】、用户证书【可以得到公钥】。
c. 得到我们想要的东西:根证书、用户证书、密码。其中根证书与密码是一起的,因为从根证书中得到私钥是需要密码的。【注:公钥与私钥其实就是两个字符串】
2、管理证书
a. A保存根证书与密码,B保存用户证书。
3、发送消息
a. A通过消息[merNo=001,user=zhangm,pwd=abc123,check=6387]形成摘要,摘要的形成方式自行选择,一般来讲是通过整个消息段做摘要。这里提供一个摘要形成方式:对三个消息字段的值进行一个自定义的排序,形成一个摘要,比如:摘要字段[abc123001zhangm6378],这是一种比较简单的摘要形成方式。复杂一点的有先对整个消息通过加密算法进行加密形成加密消息作为摘要。
b. A通过根证书与密码得到公钥和私钥
c. A通过公钥和私钥对摘要字段进行签名,形成签名字段。说白了,就是对上一步形成的摘要[abc123001zhangm6378]通过公钥和私钥形成一个加密的串。假设签名字段【加密串】为:w8y98hf。【实际会很长】。
d. A重新组装消息。将签名字段放到消息体中。[merNo=001,user=zhangm,pwd=abc123,check=6387,sign=w8y98hf]
e. A发送消息
4、接收消息
a. B接收消息
b. B根据merNo号去匹配对应的用户证书,然后从证书中拿到公钥。
c. B通过与A协定好的方式,通过消息字段生成摘要[abc123001zhangm6378]
d. B通过摘要字段[abc123001zhangm6378],公钥,签名字段sign=w8y98hf,去做验证是否正确。