zoukankan      html  css  js  c++  java
  • 加密/解密/签名/证书-原理介绍

    引言

    在一些比较重要的应用场景中,通过网络传递数据需要进行加密以保证安全。本文将简单地介绍了加密解密的一些概念,以及相关的数字签名、证书。

    加密和解密

    说到加密,可能大家最熟悉的就是MD5了。MD5实际上只是一种散列运算,或者可以称为单向的加密,即是说无法根据密文(加密后的数据),推导出明文(原数据)。而我们下面要说明的,是在加密后可以进行解密、还原数据的。对于欲进行加密的对象,有的人称为消息,有的人称为数据,有的人称为信息,为了避免混淆,在本文后面部分,我统一将其称为消息。那么加密是什么呢?加密是通过对消息进行编码,建立一种安全的交流方式,使得只有你和你所期望的接收者能够理解。

    那么怎么样才能叫安全呢?消息在接收方和发送方进行安全传递,一般要满足下面三个要点:

    1. 消息的发送方能够确定消息只有预期的接收方可以解密(不保证第三方无法获得,但保证第三方无法解密)。
    2. 消息的接收方可以确定消息是由谁发送的(消息的接收方可以确定消息的发送方)。
    3. 消息的接收方可以确定消息在途中没有被篡改过(必须确认消息的完整性)。

    加密通常分为两种方式:对称加密和非对称加密,接下来我们先看看对称加密。

    对称加密

    对称加密的思路非常简单,就是含有一个称为密钥的东西,在消息发送前使用密钥对消息进行加密,在对方收到消息之后,使用相同的密钥进行解密。根据密钥来产生加密后的消息(密文)的这一加工过程,由加密算法来完成加密算法通常是公开的。它的流程如下:

    1. 发送方使用密钥对消息进行加密。
    2. 接收方使用同样的密钥对消息进行解密。

    可以使用下面一副图来表示:

    对称加密存在这样两个问题:

    1. 虽然可以通过密钥来保证消息安全地进行传递,但是如何确保密钥安全地进行传递?因为发送者和接收者总有一次初始的通信,用来传递密钥,此时的安全如何保证?
    2. 接收者虽然可以根据密钥来解密消息,但因为存在上面的问题,消息有可能是由第三方(非法获得密钥)发来的,而接收方无法辨别。

    为了解决上面两个问题,就需要介绍一下非对称加密。

    非对称加密

    非对称加密的接收者和发送者都持有两个密钥,一个是对外公开的,称为公钥,一个是自行保管的,称为私钥。非对称加密的规则是由某人A的公钥加密的消息,只能由A的私钥进行解密;由A的私钥加密的消息只能由A的公钥解密。此时我们可以得出接收方、发送方有两个公钥两个私钥一共四个密钥,我们先看看两种简单的方式,这两种方式都是只使用两个密钥。

    第一种模式只使用接收方的公钥和私钥,称为加密模式。

    加密模式

    在加密模式中,由消息的接收方发布公钥,持有私钥。比如发送方要发送消息“hello,jimmy”到接收方,它的步骤是:

    1. 发送方使用接收者的公钥进行加密消息,然后发送。
    2. 接收方使用自己的私钥对消息进行解密。

    可以使用下面一幅图来描述:

    在这种模式下,如果第三方截获了发送者发出的消息,因为他没有接收者的私钥,所以这个消息对他来说毫无意义。可见,它能够满足本文最开始提出的消息安全传递的要点一:消息的发送方能够确定消息只有预期的接收方可以解密(不保证第三方无法获得,但保证第三方无法解密)

    除此以外,因为接收方的公钥是公开的,任何人都可以使用这个公钥来加密消息并发往接收者,而接收者无法对消息进行判别,无法知道是由谁发送来的。所以,它不满足我们开始提出的消息安全传递的要点二:消息的接收方可以确定消息是由谁发送的(消息的接收方可以确定消息的发送方)。

    这个问题可以在下面的认证模式中得到解决。

    认证模式

    在认证模式中,由消息的发送方发布公钥,持有私钥。比如发送者要发送消息“Welcome to Tracefact.net”到接收者,它的步骤是:

    1. 发送者使用自己的私钥对消息进行加密,然后发送。
    2. 接收者使用发送者的公钥对消息进行解密。

    可以用下面一副图来表述:

    在这种模式下,假如发送方叫做Ken,接收方叫做Matthew,因为Matthew只能使用Ken的公钥对消息进行解密,而无法使用Molly、Sandy或者任何其他人公钥对消息进行解密,所以他一定能够确定消息是由Ken发送来的。因此,这个模式满足了前面提出的消息安全传递的要点二。

    与此同时,因为Ken的公钥是公开的,任何截获了该消息的第三方都能够使用Ken的公钥来对消息进行解密,换言之,消息现在是不安全的。因此,与加密模式正好相反,它无法满足前面提出的消息安全传递的要点一。

    而不管是采用加密模式还是认证模式,都没有解决加密解密中的要点三:接收方必须能够确认消息没有被改动过。为了解决这个问题,又引入了数字签名。

    数字签名

    基本实现

    数字签名实际上就是上面非对称加密时的认证模式,只不过做了一点点的改进,加入了散列算法。大家比较熟悉的散列算法可能就是MD5了,很多开源论坛都采用了这个算法。散列算法有三个特点:一是不可逆的,由结果无法推算出原数据;二是原数据哪怕是一丁点儿的变化,都会使散列值产生巨大的变化;三是不论多么大或者多么少的数据,总会产生固定长度的散列值(常见的为32位64位)。产生的散列值通常称为消息的摘要(digest)。

    那么如何通过引入散列函数来保证数据的完整性呢?也就是接收方能够确认消息确实是由发送方发来的,而没有在中途被修改过。具体的过程如下:

    1. 发送方将想要进行传递的消息进行一个散列运算,得到消息摘要。
    2. 发送方使用自己的私钥对摘要进行加密,将消息和加密后的摘要发送给接收方。
    3. 接收方使用发送方的公钥对消息和消息摘要进行解密(确认了发送方)。
    4. 接收方对收到的消息进行散列运算,得到一个消息摘要。
    5. 接收方将上一步获得的消息摘要与发送方发来的消息摘要进行对比。如果相同,说明消息没有被改动过;如果不同,说明消息已经被篡改。

    这个过程可以用下面的一副图来表述:

    我们可以看出,数字签名通过引入散列算法,将非对称加密的认证模式又加强了一步,确保了消息的完整性。除此以外,注意到上面的非对称加密算法,只是对消息摘要进行了加密,而没有对消息本身进行加密。非对称加密是一个非常耗时的操作,由于只对消息摘要加密,使得运算量大幅减少,所以这样能够显著地提高程序的执行速度。同时,它依然没有确保消息不被第三方截获到,不仅如此,因为此时消息是以明文进行传递,第三方甚至不需要发送方的公钥,就可以直接查看消息。

    为了解决这样的问题,只需要将非对称加密的认证模式、加密模式以及消息摘要进行一个结合就可以了,这也就是下面的高级模式。

    高级实现

    由于这个过程比上面稍微复杂了一些,我们将其分为发送方和接收方两部分来看。先看看发送方需要执行的步骤:

    1. 将消息进行散列运算,得到消息摘要。
    2. 使用自己的私钥对消息摘要加密(认证模式:确保了接收方能够确认自己)。
    3. 使用接收方的公钥对消息进行加密(加密模式:确保了消息只能由期望的接收方解密)。
    4. 发送消息和消息摘要。

    接下来我们看一下接收方所执行的步骤:

    1. 使用发送方的公钥对消息摘要进行解密(确认了消息是由谁发送的)。
    2. 使用自己的私钥对消息进行解密(安全地获得了实际应获得的信息)。
    3. 将消息进行散列运算,获得消息摘要。
    4. 将上一步获得的消息摘要 和 第一步解密的消息摘要进行对比(确认了消息是否被篡改)。

    可以看到,通过上面这种方式,使用了接收方、发送方全部的四个密钥,再配合使用消息摘要,使得前面提出的安全传递的所有三个条件全都满足了。那么是不是这种方法就是最好的呢?不是的,因为我们已经说过了,非对称加密是一种很耗时的操作,所以这个方案是很低效的。实际上,我们可以通过它来解决对称加密中的密钥传递问题,如果你已经忘记了可以翻到前面再看一看,也就是说,我们可以使用这里的高级实现方式来进行对称加密中密钥的传递,对于之后实际的数据传递,采用对称加密方式来完成,因为此时已经是安全的了。

    证书机制

    与数字签名相关的一个概念就是证书机制了,证书是用来做什么呢?在上面的各种模式中,我们一直使用了这样一个假设,就是接收方或者发送方所持有的、对方的公钥总是正确的(确实是对方公布的)。而实际上除非对方手把手将公钥交给我们,否则如果不采取措施,双方在网络中传递公钥时,一样有可能被篡改。那么怎样解决这个问题呢?这时就需要证书机制了:可以引入一个公正的第三方,当某一方想要发布公钥时,它将自身的身份信息及公钥提交给这个第三方,第三方对其身份进行证实,如果没有问题,则将其信息和公钥打包成为证书(Certificate)。而这个公正的第三方,就是常说的证书颁发机构(Certificate Authority)。当我们需要获取公钥时,只需要获得其证书,然后从中提取出公钥就可以了。

  • 相关阅读:
    107、Java中String类之判断开头或结尾
    106、Java中String类之使用contains()方法判断子字符串是否存在
    105、Java中String类之利用indexOf()方法判断子字符串是否存在
    104、Java中String类之使用indexOf()等功能查找
    103、Java中String类之compareTo()方法
    102、Java中String类之相等判断(忽略大小写)
    101、Java中String类之判断是否由数字组成
    100、Java中String类之字符串转为大写
    099、Java中String类之字符数组与字符串的转换
    098、Java中String类之charAt()方法
  • 原文地址:https://www.cnblogs.com/yaosuc/p/4729117.html
Copyright © 2011-2022 走看看