zoukankan      html  css  js  c++  java
  • 那些年我们一起守护的“密”

    0×00 前言

    “互联网+”使得各类信息高度数字化,社会生产、人类生活无不与各类信息网络相关,当越来越多的经济利益与数字信息关联后,暗地里便会有“黑手”不惜使用各类方式伸向这些信息,来达到不可告人的目的。加密技术也因此迅猛发展,广泛应用,守护信息安全。本文讨论数字加密技术的基本原理、分类、应用以及一些思考,内容较为朴实,请大牛酌情观看。

    0×01 加密技术基础

    Q:为什么要加密?

    A:宝宝还不能有点秘密了?信息数字化后便形成数字信息,由于大部分信息都具有一定的知悉范围,而不希望面向所有人开放,便会利用一些技术来进行数据保护,加密技术便是一种。根据信息对象的状态,加密技术大致分为针对存储介质中静态数据的加密,和针对传输数据的加密。

    Q:加密技术有哪些重要元素?

    A:算法和密钥。如果把密文比作一道门,则算法就是开关门的动作,而密钥就是钥匙。算法、明文空间、密文空间和密钥空间组成一个完整的密码系统。

    Q:加密技术的特性

    A:保密性 – 只有信息知悉范围内才可获取信息的明文,其他人无法知悉。

    认证性 – 确认信息发送者的身份或信息来源的可靠性。

    完整性 – 信息传输过程中保持一致,不被篡改。

    不可抵赖性 – 发送者不能否认已发送的信息。

    Q:怎样才算一个合格的加密算法?

    A:如果攻击者不能够从密文中计算出关于明文的任何信息,就说该加密方案是安全的。但是考虑到信息的私密性带有一定的时效,可以在此定义中加入时间因素,即在已知算法和密文后,在任何攻击者所能担负的最大计算资源的情况下,仍然在信息有效期内不能计算出关于明文的任何信息,便可认为该算法是安全的。

    0×02 加密技术分类

    A)按设计理念划分

    现代密码学和古典密码学

    古典密码归根结底主要有两种,即置换和代换。主要依靠人工计算和非常简单的机械 ,并且是用人的主观意识设计和使用的,安全性不高但算法简单而艺术 。

    现代密码学主要依赖于计算机,以数学、物理等学科为基础理论,构成客观的密码形式,安全性高于传统密码但算法复杂。

    B)按算法的公开性划分

    基于算法保密的加密技术和基于密钥保密的加密技术

    如果密文的保密性是基于保持算法的秘密,这种算法称为受限制的算法。例如古典密码中的代换便是一个典型,这类算法虽然在之前占据主流,但在现代密码前,已经不能很好的适应互联网社会的需求。由于现在加密场景越发复杂,用户规模庞大,人员流动频繁,这就使得算法的私密性难以控制,一旦有人离开这个组织或者泄露算法,就需要其他用户更换算法,这种运行成本非常高。另外,算法的不公开一定程度上也是安全隐患,相反公开算法后经过更多群体的论证测试以证实算法的安全性。

    现代密码学普遍采用基于密钥保护的加密技术,算法完全公开,这也为相关标准的制定和大规模的使用奠定基础。

    C)按密钥类型划分

    对称加密算法和非对称加密算法

    对称加密算法在加密和解密过程中采用相同的密钥,非对称加密算法则在加密和解密过程中采用不同的密钥。

    图片1.png

    D)单向加密

    一般加密技术是为了保护信息的秘密性,在解密时需要恢复信息原貌,而单项加密顾名思义就是只能加密不能解密,只允许单项转换,又称散列加密技术。散列加密一般用于摘要信息的形成,即无论原文信息多长,都可以用该算法生成固定长度的摘要信息。一个合格的散列加密算法一般具有如下特性:散列结果不可逆,从结果无法推出任何部分的原始信息;原始信息的任何差异都会导致散列结果的巨大差异(雪崩效应);找不出具有相同结果的原始信息。单向加密一般用于消息摘要的生成,密钥加密等。

    0×03 对称加密

    对称加密是指加密和解密过程中使用相同密钥的加密算法,因这种加密技术的安全性完全依赖于密钥的秘密性,所以也称为秘密密钥算法或单密钥算法。常见的对称加密算法有:DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK、AES等。

    按照加密单元大小和加密机制,对称加密可分为分组密码和序列密码。

    分组密码算法以固定的分组长度作为基本的处理单元,将明文进行分组加密处理。通过阅读DES算法的相关实现,可以看到算法通过密钥的复杂置换后,与分组明文再次进行置换和运算,来实现加密,主要采用混淆原则和扩散原则来提升破解难度、抵抗分析。

    分组密码按照工作模式可分为:

    A)电子密码本模式ECB(electronic codebook mode)

    ECB模式下,明文被划分为N份,每份单独与密钥进行加密形成对应的N份密文,最后拼接起来形成最终的完整密文。从加密过程可判断,每份明文在加密过程中是独立的,之间没有任何关联和影响。

    1.png

    从ECB的工作原理可以看出,如果明文数据在等分后,两块数据相同则会产生相同的加密数据块,这会辅助攻击者快速判断加密算法的工作模式,而将攻击资源聚集在破解某一块数据即可,一旦成功则意味着全文破解,大大提升了攻击效率。为了解决这一缺陷,设计者提出了更多的分组密码工作模式,这些模式下各组数据的加密过程彼此产生关联,尽最大可能混淆数据。

    B)密码分组链接模式CBC(cipher block chaining Triple)

    CBC工作模式下,每块数据在加密前均需要与前块数据的加密结果异或,而第一块数据加密前与初始化向量异或,这样会使得数据的加密结果受上次加密结果影响,彼此产生关联,避免相同数据块加密结果相同的现象。

    2.png

    C)密码反馈模式CFB(Cipher FeedBack)

    CFB模式与CBC模式相近,密钥和明文的位置进行颠倒,先让密钥与初始化向量进行加密处理,然后与明文异或得到密文块,而后密文块参与下一块的计算。

    3.png

    D)输出反馈模式OFB(Output Feedbaek)

    OFB与CFB非常相似,不同点在于参与下一组计算的并非是前一组的密文,而是前一组的密钥加密结果。

    4.png

    E)计数器模式CTR(counter mode)

    上面的几种工作模式都存在一个共性:数据块彼此之间关联,当前块的解密依赖前面的密文块,因此不能随机访问任意加密块。这样会使得用户为了获取其中一点数据而不得不解密所有数据,当数据量大时效率较低。

    CTR模式与OFB相似,OFB中的密钥流是逐级反馈的,而CRT密钥流的产生之间是没有关联的,而是通过递增一个加密计数器以产生连续的随机数流。CRT模式由于加密和解密可以并行,所以适合用于多处理器的硬件上。

    5.png

    与分组密码相对应的便是序列密码,又称流密码,是指利用密钥通过复杂的密码算法产生大量的伪随机位流,对明文数据流进行加密。在进行解密时,用同样的密钥和算法产生相同的伪随机位流,用以还原明文数据流。目前,公开的序列密码算法主要有RC4、SEAL等。 

    6.png

    序列密码以一个元素(一个字母或一个比特)作为基本的处理单元,具有转换速度快、低错误传播的优点,硬件实现简单;但加密结果混淆度低、且数据的小幅度变化敏感性低,即插入修改较少的数据,加密结果不会发生大幅变化,这样会给攻击者提供较多分析素材。

    小结:对称加密算法的特点是算法公开,计算量小, 加解密速度快、效率高。但加解密双方都需要知道相同密钥才可完成加解密,又因网络信道通常易被监听而不可信,所以对称加密很不适合应用在网络通信中。另外,为了通信的安全性,密钥需要确保唯一,每对用户需使用其他人均不知的密钥, 这会使得整个通信网络拥有的密钥数量呈几何级数增长,密钥管理成为用户的负担。 假设一个通信网络中有N个用户,用户A发送信息给B和用户B发送信息给A使用的密钥不同,则整个网络构成N阶完全图,整个网络的密钥总数为N(N-1),每一个用户持有密钥数为2(N-1),由于成本较高, 对称加密算法难以在分布式网络系统上使用。

    0×04 非对称加密

    由于对称加密的密钥管理压力,难以适应大规模、高频率的网络通信加密,网络通信更需要一种“按需申请”的动态管理加密方案,即需要时再申请密钥,而非事前预制所有密钥,这样会大大减轻密钥过多的管理压力,非对称加密便是一种很好的解决方案。正是这种解决方案较好解决了分布式网络传输的加密问题,才使得互联网金融、电商、支付等迅猛发展。

    非对称加密的密钥系统由公钥和私钥组成,其中一个是对外公开的,所有人都可以获得,称为公钥;而与之相对应的称为私钥,只有密钥的生成者才能拥有。信息使用公钥加密后,只有对应的私钥才能进行解密,且从公钥不能推出私钥,所以能确保在不安全链路上传输的安全性。

    以著名的RSA非对称算法为例,其用到了数论中的三个基本定理:费马小定理、欧拉定理和中国剩余定理,和一个古典难题:大整数分解问题, 而RSA的安全性也正是基于大整数的分解极其困难。

    算数基本定理:任何大于1的整数都可以分解成素数乘积的形式,并且,如果不计分解式中素数的次序,该分解式是唯一的。

    下图是分解大素数的时间参考表

    7.png

    从这个表中便可以看出破解RSA的难度之大。

    非对称加密技术还有一个重要的应用场景,便是身份或信息的认证。在这种场景中,各个用户的身份信息都广为人知,且各自的公钥也面向所有用户公布,私钥只有自己掌握,用户将自己的身份信息用自己的私钥加密,这样接收者在收到相关信息后只需要使用对应用户的公钥进行解密对比即可确定对方身份。这种方法同样可以用来确定消息的来源认证。

    Q:如果传输链路遭受MITM攻击,伪造了公钥怎么办?

    A:上面的方案确实存在伪造公钥的风险。这则需要第三方保证公钥的合法性,这便是CA(Certificate Authority)证书中心。CA用自己的私钥对用户发布的公钥和身份信息进行加密,得出数字证书。用户在发布信息时,需要带上数字证书。接收者先用CA给的公钥解出信息所有者的公钥,这样可以保证信息所有者的公钥是真正的公钥,然后就能通过该公钥证明身份信息是否真实了。

    Q:如何确保CA公钥的真实性?

    A:CA公钥的真实性由PKI来确保。X.509标准中,为了区别于权限管理基础设施(Privilege Management Infrastructure,简称PMI),将PKI定义为支持公开密钥管理并能支持认证、加密、完整性和可追究性服务的基础设施。PKI 中证书的信用是一级一级背书的,即讲究“血脉”继承。企业或开发者需要拥有自己的证书时,需要向相关证书机构提出申请,让其颁发属于该认证机构证书信任链上的证书。Windows 系统会内置世界上几个大的根证书机构的证书,这就意味着证书一级一级往上查,便可以找到这几家根证书机构,从而确保证书的合法性。下图是google的证书链。

    8.png

    0×05 摘要算法

    摘要算法主要使用单向加密函数,可以将任意长度的数据,通过运算 得到一个固定长度的结果,可用于实现数据签名、数据完整性校验等功能,由于其不可逆性,也可用做敏感信息的加密。数据摘要算法也被称为哈希(Hash)算法、散列算法。

    摘要算法具有两大特性:

    1、唯一性:输入不同时,输出结果必然不同;

    2、不可逆性:无法通过摘要算法从结果推导出原文。

    A)利用摘要算法确保信息一致性

    在网络中传输时,可能会遇到遭受攻击的数据篡改、部分数据信息丢失等问题,为对传输的数据进行真实性、完整性校验,可在发送前利用摘要算法计算出原文的摘要,将其与原文一同发送,接受者在收到信息后,再次计算摘要进行比对,即可知道数据有没有被篡改或者是豆完整接收。其实这一解决方案早就应用在各种协议的校验中,例如IP校验和、UDP/TCP校验和等。

    著名的MD5和SHA等均属于摘要算法,这类算法的核心便是其中的HASH函数,这类函数一般需具备以下几个属性:

    a.输入的数据没有长度限制;

    b.输出的摘要信息均为固定长度;

    c.算法方便高效;

    d.难以从指定摘要推出一个原文;

    e.难以找到两个不同的报文具有相同摘要。

    B)利用摘要算法进行加密存储

    密码这类重要数据作为用户认证的重要凭证,通常不以明文形式存储,否则一旦被脱库则“一览无余”。开发者通常会选择摘要算法对密码进行单项加密后存储,这样即使脱库也不会使明文密码泄露。

    Q:明文密码HASH后再存储真的安全吗?

    A

    9.png

    理论上,单向加密算法是不可逆的,但是随着存储成本的降低,例如上图网站所示的云破解型网站曾出不穷,大家可以发现一些长度较长的复杂密码并不能还原,这也说明这类网站背后的运行机制实际是查表,后台存储了诸多常用字串的HASH结果,即预先计算好结果,当收到用户的查询请求时只需要查表即可完成。

    除了这种云字典的方式外,彩虹表攻击也同样有效。彩虹表是一个用于加密散列函数逆运算的预先计算好的表, 常用于破解加密过的密码散列,属于以空间换时间的典型实践, 与字典攻击相比,使用更少的储存空间和更多的计算性能。

    Q:如何应对“云破解”?

    A:为了加固MD5的安全性,应对此类事先准备好的庞大hash值字典,可在hash计算过程中加入盐值(salt),从而大大削弱字典的影响。盐值是一组随机生成的字符串,根据要求长度均不固定,相同的明文加入不同盐值产生的密文也不一样。

    原有的md5:密文 = md5(明文)

    加盐的md5:密文 = md5(明文 + 盐值)

    根据算法我们可知,如果原始MD5表为300 G,则没增加一种盐值,表就增加300G,假设加盐值的 可能性有1万个,则要想对加盐后的md5进行有效破解,就需要准备10000*300G(约3PB) ,这已经大大提升了表攻击的难度。

    Q:如何选择盐值?

    A:在选择盐值时,应该避免下面的情形。

    a)重复使用盐值

    一些开发者为了图省事,程序中使用固定盐值,这会使得加盐失去意义,因为相同的密码在使用相同盐值进行hash后,结果依旧相等。攻击者在准备预计算的字典时,将这个固定盐值带入则可形成新的有效字典。所以在加盐时,每次计算都应重新生成新的盐值。

    b)盐值长度过短

    盐值长度过短意味着盐值的所有可能取得值较少,攻击者便可以针对所有可能性的盐值进行预计算,形成常见密码在各个盐值下的字典。所以一般建议盐值的长度等于hash输出的结果长度。

    c)多次进行hash

    许多人认为,多次进行hash会增强安全性,会提升时间成本。其实这种尝试自己设计加密算法的行为并不见得会更加安全。例如下列这些算法,安全性均基于算法的保密性,其实这些自己设计的简易多重hash算法很容易通过各种手段分析出来,从而按照该算法制作字典。

    md5(sha1(password))

    sha1(sha1(password))

    md5(sha1(md5(md5(password) + sha1(password)) + md5(password)))

    0×06 混合加密

    前面介绍的对称加密因密钥管理问题,而不能直接用在分布式网络中,那我们可以直接使用非对称算法来解决这一问题吗?答案是否定的。我们先来看一下非对称算法RSA在密钥初始化阶段的耗时。

    10.png

    注:该图并非连续曲线,只是为了便于观察趋势而绘制为连续曲线。

    从时间上看,当密钥长度为16、32、64、128比特时,初始化时间均<1s,而其后的增长便成指数倍增长,当长度达到2048bit时,耗时更是长达近6分钟。

    经过测试,我们更是可以看出非对称加密算法在加解密过程中的时间效率也不如对称加密。对称加密算法在加解密过程中均表现优异,尽管非对称加密算法在加密时速度也非常快,但是在解密时便显得十分耗时,例如RSA加密1M大小的文件只需要数秒,而解密时耗时高达5分钟之久。这种解密效率显然不能胜任网络传输中的高实时性要求。

    在结合对称加密和非对称加密算法的优势后,可使用两者混合使用的方案来解决这一问题,即使用对称加密算法加密传输的数据,使用非对称算法加密传输对称加密的密钥。

    具体过程如下:

    ①发送者和接收者相互进行身份的认证;

    ②接收者:使用非对称加密算法生成一对密钥,将公钥发送给发送者;

    ③发送者:生成对称加密密钥,使用该密钥对数据进行对称加密;

    ④发送者:接收②发送的公钥,使用该公钥对③中的对称密钥进行加密;

    ⑤发送者:发送③④的加密结果给接收者;

    ⑥接收者:接收⑤发送的数据,使用私钥解密出对称密钥,然后利用该对称密钥对数据进行解密。

    0×07 编码OR加密

    经常会听到小伙伴这样说:使用base64加密一下。严格来说,base64并非是一种加密算法而是一种编码算法。

    Q:编码和加密有何区别?

    A:加密是使用特殊的算法对原始数据进行改变形成密文,使得非法用户即使获得密文也无法推出原文。而编码是希望别人解码的,是为了适应某种特定场景,而转换数据格式。Base64主要应用在网络传输中,因为1个字节的取值范围为0-255,但是并非这256个值都是可见字符,所以base64是为了解决网络传输中将不可见字符转换为可见字符的问题,具体算法请自行谷歌。

    Q:base64编码后的结果已经看不懂了,难道不算加密?

    A:的确,base64编码后的结果与原文有较大差别,但是这并不意味着就是安全的。看不懂只意味着数据可读性变差,毕竟base64算法是一种公开的标准算法,所以只要使用该算法对结果进行解码即可恢复原文,所以根本不具备加密算法的特性。由于base64在编码时是依据特定的编码表对字符进行映射编码,有小伙伴说,可以自己更改一下置换表就可以实现加密效果了。确实如此,自定义的置换表只有授权用户知晓,则非授权者无法对内容进行解密,可以达到加密效果,但是这种加密类似与古典加密的代换算法,安全性并不高,不建议使用。

    0×08加密技术的脆弱点

    看了这么多加密算法,最后我们一起来看看加密技术在各种使用场景下的脆弱点。

    A)脆弱的密钥

    密钥就相当与钥匙,一旦丢失,不管你的门修的如何结实,也会功亏一篑。同样在加密算法中,密钥的保存也同样重要。在一些大片中,会看到一些公司将私钥存放在重重铁门背后,将其安防等级设为最高级别。在平时曝光的一些安全事件中,也不乏可以看到由于开发者的错误,导致私钥泄露,而给公司造成重大损失的案例。

    同样,在很多本地加密软件中,不巧当的逻辑设计也给攻击者给予可趁之机。一些加密软件会将密钥存储下载,以便验证输入的密码是否正确,这样的做法很容易通过逆向的方法来获取到真实的密钥。而更多的软件则是采取笔者第一篇文章中所逆向的加密软件的方法,将一段特殊标记进行加密追加在加密文件中,当输入密码后先解密这段特殊标记,通过对比这段标记来判定密码是否正确,以此决定要不要继续解密原文。其实这种做法依旧无法抵抗暴破。

    当时有一位读者就给出了很好的建议,可以不适用这个标记来判断密码是否正确,完全不在加密文件中存储任何有关密钥的信息,只要用户输入密钥就拿这个密钥进行解密,这样只有正确的密钥才能解密出正确的结果。这确实是一个安全性非常高的方案,但是用户体验有些差,对于一个健忘症来说简直是个灾难;另外如果文件非常大,解密耗时很长,结果解密了1个多小时后,一看番号不对,想死的心都有了。

    B)伪随机数

    上面是密钥的安全保管问题,如果密钥是可计算或可预测的,那么一样不安全。一般开发者均使用random函数来生成随机数,严格来说这是“伪随机数”,在种子固定的情况下,输出的数值序列均相同,因为这是通过软件方法使用算法产生随机数,一般使用线形同余法:随机数列符合X[n+1] = (A*X[n] + B) mod N, X[0] = seed,其中seed为种子,A、B、N为整数。

    由公式可以看出系数A和B的公因数越大,该数列的周期越小,而且最大周期 = N。

    在对c语言rand()函数周期进行测试后,得出如下结果:

    当对比数目为1时,即第一个数重复出现的位置为96113;当对比数目为2时,重复出现位置为745064332;当对比数目为3和大于3时,重复位置为2147483648。也就是从第2147483648个数开始数列开始重复,即周期为2147483647,N=2147483647,而该值为int型的最大值2的31次方-1。由此看来在已知语言平台,已知种子的情况下,是可以获取伪随机数的。开发者一般均习惯使用时间作为种子,这更是把种子的范围进一步缩小,为攻击者带来便利。在一些安全性较高的应用场景中,会引入硬件来产生随机数,例如采集噪声、光照等来生成真正的随机数。

    写在最后

    本文仅是从宏观层面大体介绍了加密技术的目的、算法分类和应用场景等,而加密技术所涉及的密码学、认证技术等知识更是庞杂,有兴趣的小伙伴可以深入研究。

  • 相关阅读:
    导出表格,导出表格为excel,导出表格带样式,怎么导出表格数据为excel并且带样式呢
    webpack打包文件 可以npm cdn使用
    Webpack的externals的使用
    如何在微信小程序中使用iconfont
    如何发布和取消发布 NPM 包?
    js中数组对象去重的方法
    小程序列表性能优化
    wepy全局拦截器
    js中prototype与__proto__的关系详解
    JavaScript中本地对象、内置对象和宿主对象
  • 原文地址:https://www.cnblogs.com/h2zZhou/p/6667369.html
Copyright © 2011-2022 走看看