在这里,我们聚焦数据技能,分享方法论与实战。一线的项目经历,丰富的实践履历,真实的总结体会…滑到文末,可以看到我们的往期内容。
本篇由奇点云后端架构师「心诚」带来:
1. 加密与数据保护

大数据的时期,在日常生活和事情中,我们常常面临着主动或被动地(被)网络个人信息,包括一些敏感信息,如账号密码、身份ID、银行卡号、行为习气等。这些信息又主动或被动地利用在统计、行为剖析、授权审核等方面。虽然可以带来无限便利,但无意间发生的透露等事件会危害个人/公司信息安全,同时带来重大经济丢失。
因此,数据安全的主要性是毋庸置疑的。而数据加密是保障数据安全的主要技能之一。
目前常见的加密算法有:
· 对称加密算法
· 非对称加密算法
· Hash算法
在先容加密算法前,我们先来理解下加密密钥(Encryption Keys):
加密密钥,即加密算法天生的特定字符密钥,用于加密和解密一段信息。这些密钥的利用办法的不同可以进一步解释对称和非对称加密之间的差异。
· 对称加密算法
如下图所示,对称加密最大的特点便是加解密过程利用的密钥是同一个(密钥A),它的安全性很大程度上依赖于密钥的保密程度,一旦密钥透露,攻击者可轻松访问加密过的信息。
虽然有透露密钥的风险,但和非对称加密算法比较,它是相同密钥长度下运算速率较快、打算资源较少的一种加密办法。
目前主流的对称加密算法有DES、AES等。
· 非对称加密算法
相对付对称加密,非对称加密的特点是须要两个密钥,如下图所示,一个公开密钥(Public Key), 一个私有密钥(Private Key)。公钥和私钥是一对的,如果数据利用公钥进行加密,只有对应的私钥才能解密,反之亦然。
由于有公私钥之分,非对称加密可以把公钥公开,私钥自己保存,安全性因此有了很大的提升。
相应也有缺点:加密和解密耗时相对长、速率慢,只适宜对少量数据进行加密。
常用的非对称加密算法有RSA、DSA、DH等。
· Hash算法
Hash算法又称为择要算法、散列算法,可以将任意长度的二进制明文串映射为较短的(常日是相同长度的)二进制串(Hash 值),并且不同的明文很难映射为相同的 Hash 值。
如下图所示(二进制解码后字符):
Hash算法的特殊之处在于它是一种单向算法,即不可逆。
由于此特点,Hash算法常日用在保存不可还原的密码存储,信息/文件完全校验等地方。
常用的Hash算法有MD5、SHA、HMAC、HMAC-MD5等。
1.1
利用哈希(Hash)进行加密
严格意义上Hash并不是一种加密办法,如上所述,只是一种将目标文本转换成具有相同长度的、不可逆的择要,加密(Encryption)却是将目标文本转换成具有不同长度的、可逆的密文。
我们以MD5(Message-Digest Algorithm V5版本)为例,来描述Hash算法的事情过程:
1. 首先对任意大小输入信息(转化成二进制后)进行信息添补(Append Padding Bits),使其位长对512求余的结果即是448,终极的信息位长为:n512+448,n为一个非负整数,n可以是零。
规则为:
a) 在信息的后面添补一个1和无数个0,直到知足上面的条件时才停滞用0对信息的添补。
b) 在这个结果后面附加一个以64位二进制表示的添补前信息长度(单位为Bit),如果二进制表示的添补前信息长度超过64位,则取低64位。
末了的信息长度为 n512+448+64=(n+1)512(单位bit)。
2. 接下来进行初始化MD缓冲区(Initialize MD Buffer)利用保留的4个32bits向量(Word A~D,低字节在前)如下图:
3. 开始循环打算(Process Message in 16-Word Blocks),每512bit作为一组,第一组输入为a=A, b=B, c=C, d=D,对每组数据进行164 的向量运算。详细规则参考:https://www.freesoft.org/CIE/RFC/1321/7.htm
4. 在第3步处理完所有的512bit的分组后,得到一组新的A, B, C, D的值,将这些值按ABCD的顺序级联,输出值即为MD5加密后的Hash值(低字节在前)。
1.2
哈希(Hash)的安全性
只管Hash算法是单向的,不可逆的,不同明文得到的Hash值是不同的,但在一定条件下不同的原始数据,可能会得到相同的 MD5 值,这便是Hash的碰撞征象。
以MD5为例,它之以是运用这么广泛,便是由于它的可靠性——很难有两个不同的输入得到相同的 MD5。不过虽然概率低,但确实还是有:2004 年山东大学的王晓云就破解了 MD5,找到了 Hash 碰撞。(拜会https://eprint.iacr.org/2004/199)
其余一种破解MD5加密的办法是利用彩虹表(预先打算的散列链),一样平常用于规复/破解固定长度的纯文本密码。
这因此空间换韶光的范例实践。相较于每次考试测验都打算Hash的暴力破解处理办法,它所花费的韶光更少,所需储存空间更多。利用加盐值(salt)的办法可以使这种攻击难以实现。根据情形可利用固定或随机盐值来增强密文的破解难度。
1.3
加密算法BCrypt是什么?
BCrypt是一种跨平台的文件加密工具,利用的是布鲁斯·施内尔在1993年发布的 Blowfish 加密算法。它是一种可天生随机盐值的单向Hash加密算法,Hash值中包含了上一步天生的盐值(22个字符)的不可逆加密算法。同一种明文,每次被加密后的密文都不一样,并且不可反向破解天生明文,破解难度非常大。
BCrypt加密后的密文构造如下图所示:
个中密文构造为:$是分割符, 2y是BCrypt加密版本号,10是cost的值,紧随其后的前22位是盐值(salt),末了的字符串便是密码的密文了。
2. BCrypt的安全性
2.1
随机密文
BCrypt也是一种单向Hash加密算法,因此它不可被反向破解天生明文。由于打算中利用了随机盐值,并且在密文中包含了salt值,默认情形下每次天生的密文都是不同的。随机密文带来的好处是:避免了如果两个人或多个人的密码相同,密码加密后保存到数据库会得到相同的结果,以防破解一个就可以知道其他人的密码。
例如:如果名为A的用户可以查看数据库,那么他可以不雅观察到自己的密码和别人的密码加密后的结果都是一样,那么,别人用的和自己便是同一个密码,这样就可以利用别人的身份登录了。
在利用MD5加密的时候,也可以通过加salt值来间接天生不同密文(不是随机密文),条件是利用固定salt值,比如用户名+网站域名。
2.2
韶光本钱
韶光本钱对付防止密文被破解来说有非常主要意义,如果破解一个密文的韶光本钱足够高到一定程度,当采取暴力搜索攻击花费的韶光超过以年来打算的时候,可以认为此加密办法是安全的。
对付BCrypt来说,产生上文所描述的密文构造紧张经历两个步骤:首先,基于期望的cost、salt值和明文(密码)利用一个称为EksBlowfishSetup的方法初始化Blowfish状态(最耗时的步骤),通过cost不同值来大幅提升打算次数;然后,基于24位初始向量“OrpheanBeholderScryDoubt”利用Blowfish算法的ECB模式进行加密。
事情流程如下图所示:
因此真正意义上BCrypt是基于Blowfish密码设计的一种韶光本钱差异较大(根据cost值设定)的Hash函数。详细关于Blowfish算法移步:https://zh.wikipedia.org/wiki/Blowfish
3. BCrypt的实现和运用处景
纵然利用了BCrypt加密算法,也并不能担保密码不会被透露,上文已经提到过BCrypt进行加密的韶光本钱,为了有个整体观点,根据ResearchGate的报告:
可以看到原始密码的长度(bcrypt行)直接影响理解密的韶光,因此为理解决这个长度导致的韶光差异问题,可以利用MD5/HMAC来办理。详细实践办法如下:
bcrypt(HMAC(password, key), 随机salt值) = 密文Hash值
基于此场景,担保了无论用户密码如何繁芜,BCrypt加密后对应的韶光本钱是固定的。
3.1
BCrypt算法实现(JAVA)
BCrypt有很多程序措辞供应了根本的实现,以JAVA为例,jBCrypt是一个开源的Blowfish算法实现,利用它为密码加密非常大略:
// Hash a password for the first timeString hashed = BCrypt.hashpw(password, BCrypt.gensalt());// gensalt's log_rounds parameter determines the complexity// the work factor is 2log_rounds, and the default is 10String hashed = BCrypt.hashpw(password, BCrypt.gensalt(12));// Check that an unencrypted password matches one that has// previously been hashedif (BCrypt.checkpw(candidate, hashed)) System.out.println("It matches");else System.out.println("It does not match");
←左滑阅读
3.2
BCrypt运用(Spring Security)
Spring Security作为企业级运用的主流安全框架,在5.0.0往后移除了对MD5加密的支持(弃用),推举利用BCrypt算法支持类:BCryptPasswordEncoder,他实现了PasswordEncoder接口的encode和matches方法,来进行密码加密和匹配。紧张代码参考:
Encode实现方法:
public String encode(CharSequence rawPassword) { if (rawPassword == null) { throw new IllegalArgumentException("rawPassword cannot be null"); } else { String salt; if (this.random != null) { salt = BCrypt.gensalt(this.version.getVersion(), this.strength, this.random); } else { salt = BCrypt.gensalt(this.version.getVersion(), this.strength); } return BCrypt.hashpw(rawPassword.toString(), salt); }}
←左滑阅读
Matches实现方法:
public boolean matches(CharSequence rawPassword, String encodedPassword) { if (rawPassword == null) { throw new IllegalArgumentException("rawPassword cannot be null"); } else if (encodedPassword != null && encodedPassword.length() != 0) { if (!this.BCrypt_PATTERN.matcher(encodedPassword).matches()) { this.logger.warn("Encoded password does not look like BCrypt"); return false; } else { return BCrypt.checkpw(rawPassword.toString(), encodedPassword); } } else { this.logger.warn("Empty encoded password"); return false; }}
←左滑阅读
4 总结
DT时期,数据保护应成为企业最主要的一个技能环节。以数据智能做事商为例,无论是客户项目或是公司产品,都应利用足够安全的加密办法来保护核心信息资产。
BCrypt加密办法作为主流的单向不可逆Hash算法,其安全性得到了广泛的认可,大家不妨考试测验在项目或产品中利用/升级。
注:本文插图源自网络。