上一章,所提到的单向散列函数基本能保证双方通信的安全性。但还是存在局限性,由于Alice和Bob端都掌握着共享密钥,那么对于第三方而言,无法确定被加密的包含散列值的密文到底是谁发送的。这种场景发生于Alice和Bob既需要保证双发通信的安全性而Alice和Bob端互相不可信任的状态下。
举上篇文章中的一个例子,软件开发商将散列值公布在官网上,用户下载软件后,通过官网知晓散列值然后进行比较,确认软件没有被篡改。那么如何保证用户浏览的网页没有被第三方篡改了呢?那么就需要使用到数字签名。
数字签名
之前所提到的使用单向散列函数的应用场景中,Alice和Bob共同拥有相同的密钥,使用密钥对通信的数据进行加解密,这种方式成为对称加密。但在数字签名中的加密方式为非对称加密,即公钥密码体制。
在公钥密码体制中,公钥用来对数据进行加密,私钥用来对数据进行解密,二者存在严谨的数学关系,使用公钥进行加密的密文,只能由该公钥配对的私钥进行解密。所以一般的应用场景是将公钥公布,而私钥由个人掌握。发送者利用公钥对数据进行加密后,将密文发送出去。接收者利用私钥进行解密。因为非对称密钥,第三方无法根据公钥推算出私钥,应此保证了数据不会泄露。
而在数字签名中恰好相反,使用私钥进行加密,该只能由该私钥配对的公钥进行解密。通常发送数据的用户持有私钥,而将公钥公布。Alice和Bob拥有不同的密钥。Alice使用私钥对数据进行加密后发送(相当于生成签名),Bob接收后通过公钥进行解密(验证签名)。由于公钥对外公开,应此可以任何人都能确定被加密消息只能是由持有私密钥的Alice发送的。
在实际运用中,例如软件开发商将散列值进行私钥加密后的密文和公钥及其解密算法公布在网上。用户下载好软件后,通过公钥对散列值进行解密就可以知晓软件是否被篡改。至于如何确保公钥不被第三方篡改,则必须交由公钥基础设施处理,例如VerSign公司,关于这点之后再提。
数字签名的使用
当Alice使用数字签名方式发送数据给Bob时:
1:Alice生成一对公钥和私钥,将公钥公之于众。
2:利用单向散列函数生成数据的散列值,将数据包含散列值发送给Bob。
3:Bob利用私钥进行解密,验证数据是否和散列值相同。
4:由于该加密的数据只能通过私钥加密,应此只要私钥保密,那么数据发送者只能是Alice。
公钥密钥体制推荐算法-RSA
RSA作为使用最为广泛的公钥密码算法,其加解密方式为:
RSA加密:密文=明文EmodN。明文的E次方除以N求余数等于密文。
RSA解密:明文=密文DmodN。密文的D次方除以N求余数等于明文。
其中公钥为E和N。私钥为D和N。其中N相同。(从公式上看很美妙)
其中E、N、D怎么来我就不叙述了,感兴趣可以直接查阅资料。
公私钥的生成可以利用openssl,其加解密函数也很简单:
void encrypt(char*p,unsigned key,unsigned mod){ //加密
char tmp=*p;
for(unsigned i=2;i<=key;i++){
tmp=(tmp*tmp)%mod;
}
*p=tmp;
}
void decrypt(char*p,unsigned key,unsigned mod){ //解密
char tmp=*p;
for(unsigned i=2;i<=key;i++){
tmp=(tmp*tmp)%mod;
}
*p=tmp;
}
目前RSA算法,公私钥初始时质数很大情况下,按照寻常办法难以攻破(建议使用1024比特的密钥)。但一旦发现对大整数进行质因数分解的高效算法,RSA就可以被暴力破解。目前流传唯一可以攻破RSA算法的是利用量子计算机的并行性使用秀尔算法进行破解。目前量子计算机已实现,但现在谁会用它来破解你的密钥呢。到了量子计算机普及的那年,差不多可以更换成量子通讯技术也成熟了。(目前量子通讯有的卖,问天量子公司了解下)。