一、什么是非对称加密算法
加密和解密所用的密钥是不一样的,所以叫“非对称”。 非对称加密算法的这两个密钥,一个称为公钥,一个称为私钥。 所谓公钥和私钥不是绝对的,公钥和私钥只是经过算法运算得到的一对数值,公开的那一个值称为公钥,不公开的称为私钥。 用公钥加密的,可以用私钥解密,反过来也成立。 RSA就是典型的非对称加密算法。 关于RSA算法的解释,最经典的当然是阮一峰老师的博客了: http://www./blog/2013/06/rsa_algorithm_part_one.html http://www./blog/2013/07/rsa_algorithm_part_two.html 想当初我看懂之后还在纸上自己推导了一遍,可惜后来又忘记了,只记得一个欧拉定理。。 二、使用非对称加密算法通信的原理 由于非对称加密算法一般比较慢,因此他一般用于密钥交换。这个交换的密钥就是指对称密钥。 通常,发送方用公钥加密,接收方用私钥解密。假如你是接收方,你可以把公钥公开出去,那其他人想要与你通信时,先用你的公钥把对称密钥加密后传递给你,你再通过私钥解密得到对称密钥。从这以后,双方都有对称密钥了,双方的通信信息就通过这个密钥来加密解密。 知乎上的一个回答说明了同样的过程(https://www.zhihu.com/question/20744215/answer/16056710): Java代码
三、实际例子 3.1 https的通信建立就是用RSA: ![]() 第三步的crt public就是服务端的公钥(传说中的证书,当然证书还会包含其他信息),发给了客户端。 第五步的random key就是对称密钥。第五步完成后,对称密钥就交换成功了。 3.2 http接口远程调用参数的加密 以实际项目中,调用A公司的http接口为例: 假设params是可以在公网上安全传输的值,显然不能是明文,那它是怎么来的呢: 伪代码: Java代码
其中的merchantId=111&sences=222&productId=333&extParams=444就是要传递的参数。 加密方法encrypt分三步:用A公司公钥(A公司的私钥在它们那里,不公开)加密再用base64编码再经过url-encode。 可以推知,A公司的解密过程就是先url-decode再base64解密,最后用它的私钥解密得到消息的明文。 那如何保证消息明文没有被篡改呢? 此时就需要我们调用传参时,同时传递数字签名: 假设上一步算得params="555",则最后在http报文体中传递的就是params=555&sign=888,而这个sign就是数字签名: 先hash再用我们的私钥(我们的公钥会直接给到A公司的开发人员,A公司的公钥也是直接给到我们)加密: Java代码
可以看到,数字签名不是一成不变的,它随着消息的改变而改变。它与我们现实中的个人签名不同,个人签名每次都是签同一个名字。 A公司接收到签名后,用我们的公钥解密得到消息摘要(假设为digestX),然后把之前解密得到的消息明文hash一下,得到digestY,比较这两个值是否相等,则可以知道消息有没有被篡改。 说到这里我们发现,我们需要提前与A公司协定好hash算法(例如sha1)。 那黑客有没有可能同时篡改消息和签名呢?不可以,因为他没有我们的私钥,改不了签名。 在这http调用过程中,总结一句话: 用对方的公钥来加密消息,用我们自己的私钥来签名。 |
|