加密方式与加密算法的特点分析

加密方式与加密算法的特点分析

采用明文的方式存储用户密码等隐私数据一旦被攻击或泄露将会造成非常重大的安全事故。尤其很多用户会将多个网站的密码设置为同一个密码,这样当某个互联网公司的用户数据被泄露后,这些用户的其他常用社交平台的信息将会被全部泄露。这就是黑客常用的撞库手段来窃取用户的数据,即黑客通过收集互联网已泄露的用户和密码信息,生成对应的字典表,尝试批量登陆其他网站后,得到一系列可以登录的用户。

因此考虑到系统的安全问题,用户的密码绝对不能使用明文的方式来存储。

5.1 常见的加密算法分类

加密算法是信息安全的核心,用于保护数据的机密性和完整性。它们可以分为两大类:对称加密和非对称加密(公钥加密)。

5.1.1 对称加密

对称加密使用相同的密钥进行数据的加密和解密。

例如:小灰想要给小蓝发送一个秘密消息,他希望只有小蓝能够读取这个消息。

步骤如下:

  1. 密钥生成:小灰创建了一个密钥(比如"123")。
  2. 密钥分发:小灰需要安全地把这把密钥交给小蓝。假设他们在一个安全的环境中见面,并且小灰亲自把密钥给了小蓝。
  3. 加密过程:小灰使用这个密钥(123)和一种对称加密算法(如AES)来加密她的消息。
  4. 传输:小灰通过电子邮件或其他方式将加密后的消息发送给小蓝。

对称加密算法具有如下特点:

  • 效率高:由于只需要一个密钥,且大多数对称加密算法(如AES)在硬件上可以非常快速地执行,因此它们通常比非对称加密更快。
  • 密钥管理复杂:安全地分发和存储密钥是一个挑战。如果密钥泄露,那么所有用这个密钥加密的数据都将处于风险之中。
  • 适用于大量数据:适合于需要处理大量数据的情况,因为它的计算成本相对较低。
  • 安全性依赖于密钥保密性:只要密钥保持机密,加密的数据就是安全的。

对称加密的优点是快速、适合大量数据。 缺点是如果密钥在分发过程中被截获,那么整个通信将不再安全。

使用对称加密时,数据库中保存加密后的密文以及秘钥,用户登录时传递明文到后端,后端通过秘钥将数据库中存储的密文还原成明文进行匹配。如果数据库遭受到黑客攻击或泄露只要秘钥没有被泄露那么其他只能获取到一堆的密文,没有秘钥是无法解析这些密文的。

5.1.2 非对称加密

非对称加密,也称为公钥加密,使用一对密钥:一个是公开的公钥,用于加密;另一个是私有的私钥,用于解密。

例如:同样的,小灰想要给小蓝发送一个秘密消息,但他不想冒险在分发密钥时泄露信息。

步骤如下:

  1. 密钥对生成:小蓝生成一对公钥和私钥。公钥是公开的,任何人都可以获得;私钥则由小蓝自己保管,绝不外泄。
  2. 公钥获取:小灰从可靠的来源获取了小蓝的公钥。
  3. 加密过程:小灰使用小蓝的公钥来加密她的消息。
  4. 传输:小灰将加密后的消息发送给小蓝。
  5. 解密过程:小蓝使用他的私钥来解密消息,因为只有他的私钥才能解开用他公钥加密的信息。

非对称加密具有如下特点:

  • 密钥分发简单:公钥可以自由分发给任何人,而无需担心安全性问题,因为只有拥有相应私钥的人才能解密信息。
  • 计算开销大:与对称加密相比,非对称加密算法通常较慢,不适合用于大量数据的加密。
  • 提供额外的安全功能:除了加密外,非对称加密还可以用于数字签名、身份验证等。

5.1.3 哈希算法

在对称加密中,密文可以根据秘钥来还原成明文,如果秘钥一旦泄露,那么获得到了密文就相当于获得到了明文,于是人们在密码学上继续进步,使用hash函数对密码进行加密。hash函数可以把一段明文加密出一个不可逆的密文(hash值),只要输入的明文相同,那么hash函数计算出来的密文也是一致的。

hash算法与对称加密算法的本质区别是hash函数不需要秘钥,是单向不可逆的,即及时获取到了使用hash函数加密的密文,也无法通过密文来逆向推导出所对应的明文。如图所示,我们计算14 x 17 x 16 x 89 x78 的值非常好计算,这就像一个加密过程。计算出来的结果为26,435,136,相当于是加密出来的密文,可当我们拥有了密文想要还原成明文是非常困难的。

常见的哈希算法有MD5和SHA,其中SHA是一系列哈希函数的总称,其中存在非常多的分支,如图所示。

  • MD5:是1992年Ronald Rivest设计的一种加密算法,长度为128位(16字节)。MD5已经被认为是不安全的,存在碰撞攻击(即可以找到两个不同的输入产生相同的哈希值)。因此,它不再被推荐用于需要高安全性的应用中,如数字签名、文件完整性验证等。
  • SHA:由美国国家安全局(NSA)设计,并由NIST发布为联邦信息处理标准(FIPS)的一部分。从160位到512位不等,取决于具体的算法版本。SHA-0和SHA-1由于发现了严重的安全漏洞而不再推荐使用。SHA-2被认为相对安全,广泛应用于各种场景。SHA-3作为最新标准,旨在提供更高的安全性并具备抵抗量子计算攻击的能力。
    • SHA-0:发布与1993年,长度为160位,由于发现的安全漏洞,很快就被SHA-1取代,几乎不再使用
    • SHA-1:发布于1995年,长度为160位,虽然比SHA-0更安全,但自2005年起开始出现实际可行的碰撞攻击。现在被认为是不安全的,许多组织已经停止使用SHA-1进行新的证书签发。
    • SHA-2:发布于2001年,包含非常多的变种算法,如SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256,目前广泛使用的版本,被认为相对安全。其中SHA-256和SHA-512最为常用。
    • SHA-3:2015年正式发布,包含非常多的变种算法,标准定义了SHA3-224, SHA3-256, SHA3-384, SHA3-512等。基于Keccak算法,设计来提供更好的性能和安全性,尤其是对于未来可能的量子计算攻击。

使用hash算法后,保存在数据库中不再是用户的明文密码,而是经过hash函数加密之后的密文密码。当用户进行登录时,将用户输入的明文使用与密文相同的hash函数对其加密,再和数据库中存储的密文进行匹配。如果数据库遭受到黑客攻击或泄露,最多也只是将数据库中的密文被泄漏,而通过密文是无法逆向转换为明文的,从而保障了用户的安全。

1)彩虹表攻击

随着密码学的发展,我们逐渐发现hash算法也是有重大弊端的。虽然hash算法是不可逆的,但是可以先将一些常用的密码预先使用hash算法先加密一遍,产生一个查询表,即明文与密文的对应表。采用密文比对密文的方式即可推断出当前密文对应的明文值,这种攻击方式也叫彩虹表攻击

彩虹表是一种预先计算好的数据表,用于反向查找加密的密码。它通过存储一系列哈希值及其对应的明文来工作,从而能够快速地破解用相同哈希算法加密的密码。与暴力破解或字典攻击相比,彩虹表在时间和空间上提供了一种折衷方案。如下图所示。

如下图所示,假设某互联网公司的数据库信息遭到泄露,黑客们也可以通过彩虹表来以匹配密码的方式找到对应的明文:

2)哈希加盐

哈希加密算法通过彩虹表的攻击使得密文被泄露也会存在一定的风险,于是我们开始考虑给明文加“盐”,所谓盐就相当于是一个秘钥,盐也被存储在服务器中。

在用户注册账号时,对该用户生成一个盐值,然后使用明文+盐得出新的明文,之后再进行哈希运算。常见的密码在加上盐之后就变得不再常见,所以这使得如果密文被泄露后通过彩虹表进行攻击将会变得较为困难。另外由于盐的随机性,即使多个用户的密码设置为一致,也不会出现破解了一个用户就破解了所有相同密码的用户。

哈希加盐工作流程如下图所示。

加盐之后的新的明文加密出来之后的密文变得复杂,不过仍然可以通过彩虹表进行破解。但是即使黑客们通过彩虹表的方式破解之后也只是得到了该用户的明文+盐的值,并无法推断用户的明文。如下图所示。

Tips:通过哈希加盐我们不难发现,如果破解了用户的盐,那么通过彩虹表攻击再获取到用户的“明文”(该明文为“实际明文”+“盐”),此时就可以破解出用户真正的明文,因此用户的盐是非常重要的,不能被泄露。

但哈希加盐并发绝对安全,我们只需要换一种攻击思路则会发现哈希加盐也是存在安全隐患的。因为同样的明文+同样的盐得出来的新的明文是一样的,而一样的明文通过哈希算法算出来的密文也都是一样的,基于这个思路我们依旧可以通过彩虹表的方式来同时破解盐和明文。如图所示。

彩虹表这种攻击方式的存在以及随着计算机硬件的发展,每秒执行数十亿次 HASH计算己经变得轻轻松松,产生彩虹表的时间成本也随之下降,这意味着即使给密码加密加盐也不再安全。

5.1.4 秘钥延伸哈希算法

哈希加盐也无法抵御暴力破解,借助先进的GPU和专门硬件,1秒可以计算数10亿哈希。为了降低破解的效率,可以使用秘钥延伸 (key stretching)。

秘钥延伸除了提供原始密码和盐,这些算法还允许指定成本参数,也叫成本因子。成本因子越大消耗的时间或空间就越大。成本因子的出现对普通用户并不会造成太大影响,例如原本等待0.1微秒,现在等待0.1毫秒。但是对于黑客来说计算彩虹表的成本增加了数万倍,并且成本参数可以任意调整,随着芯片的发展、计算机算力的增长,只需要把成本参数的值相应提高就可以抵御黑客的攻击。

成本因子(cost factor)决定了哈希函数内部的迭代次数。每次迭代都会对密码进行一系列复杂的计算,以增加生成最终哈希值所需的时间。这种迭代过程使得即使使用强大的计算资源,攻击者也难以在合理的时间内完成大量密码的尝试。

通过秘钥延伸哈希算法计算出来的哈希值通常格式为: $2a$[cost]$[salt][hash],例如:

$2a$10$Z5go9.4goUTHgsvMpCjlpeqnH4tVOMpVIBsNJHIQJms/CeRIF4G2u

其中:

  • 2a:标识符,表示使用的是BCrypt算法。
  • [cost]:10,工作因子,表示哈希计算的迭代次数,通常是 4 到 31 之间的整数。
  • [salt]:Z5go9.4goUTHgsvMpCjlpe,随机生成的盐值,长度为 22 个字符。
  • [hash]:qnH4tVOMpVIBsNJHIQJms/CeRIF4G2u,实际的哈希值,长度为 31 个字符。

成本因子的迭代过程主要包括以下步骤:

  1. 初始化:生成一个随机盐值,将密码和盐值组合在一起。
  2. 主循环:主循环会执行 2^成本因子 次迭代。在每次迭代中,会对当前的数据块进行多次变换和混合操作,这些操作包括位移、异或、加法等。
  3. 最终输出:经过所有迭代后,得到最终的哈希值。最终的哈希值包含了标识符、成本因子、盐值和实际的哈希结果。

秘钥延伸哈希算法如下图所示。

当使用验证一个明文密码是否与存储的哈希值相匹配时,我们可以通过解析存储在数据库中的密文,该密文中包含盐值和其他参数(如工作因子),然后使用这些参数重新计算明文得出密文。如果重新计算得到的哈希值与存储的哈希值相同,则说明密码匹配;否则,密码不匹配,如下图所示。

秘钥延伸的核心是让哈希变慢,增加计算哈希值所需的时间或空间,这样即使使用GPU或专门硬件破解也变的非常耗时(但不影响正常用户登陆体验)。常见的秘钥延伸算法有BCrypt、Scrypt、Argon2、PBKDF2等,并且在 Spring Security 框架中对这些算法都做了实现。

  • BCrypt(BCryptPasswordEncoder):

BCrypt在设计上就考虑了慢速哈希的需求,通过可调的工作因子(迭代次数)来增加计算时间。另外BCrypt算法中内置了盐值机制,开发者不需要额外维护盐,确保即使相同的密码也会产生不同的哈希值。

BCrypt被广泛用于密码存储,提供了一种简单而有效的方式来保护用户密码。

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class BCryptWorkFactorExample {
    public static void main(String[] args) {
        // 明文密码
        String plainTextPassword = "123456";

        // 测试不同的成本因子
        int[] costFactors = {4, 7, 10, 13, 16};

        // 循环测试不同成本因子的加密效率
        for (int costFactor : costFactors) {
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(costFactor);

            // 记录开始时间
            long startTime = System.currentTimeMillis();

            // 加密密码
            String hashedPassword = encoder.encode(plainTextPassword);

            // 记录结束时间
            long endTime = System.currentTimeMillis();

            // 计算耗时
            long duration = endTime - startTime;

            System.out.println("成本因子: " + costFactor);
            System.out.println("密文: " + hashedPassword);
            System.out.println("消耗时间:" + duration);
            System.out.println();
        }
    }
}

输出信息:

成本因子: 4
密文: $2a$04$dcWBQEUTK0ik/7.6DGBpFu3go7yTj3hEURwKfTwZw.4daG1911ZdC
消耗时间:48

成本因子: 7
密文: $2a$07$hJ8e7BboCkK.KiTVE60ux.43Kg6o3UC9pN7608BUBbIsrSY0FjfAa
消耗时间:11

成本因子: 10
密文: $2a$10$1A8rxstuoUi7aTcGfNYAwuAa3IUWYgahsY7Bz8oLHmcdv5OqqWIYi
消耗时间:61

成本因子: 13
密文: $2a$13$lwNptmGf/W5SqIRZIlC/GOTRSPzy7/Iv0F7xnCCMiLB5qZiDESvL.
消耗时间:486

成本因子: 16
密文: $2a$16$V8NzBrZefxP54vgtx.C0rejqHmnWvfb11WbFiK.iB9SVMvCYpbN2O
消耗时间:3850
  • Scrypt(SCryptPasswordEncoder):

Scrypt不仅依赖于CPU计算能力,同时需要大量内存,使得攻击者难以通过并行化硬件进行有效的暴力破解。另外Scrypt支持配置多个参数,包括工作因子(N)、内存块大小(r)和并行因子(p),从而灵活地调整计算复杂度。相对于其他算法,Scrypt在内存消耗上更为显著,这有助于抵御大规模的分布式攻击。

Scrypt非常适用于需要额外内存硬性(memory-hardness)的场景,例如加密货币挖矿(如莱特币)和某些安全敏感的应用程序。

  • Argon2(Argon2PasswordEncoder):

Argon2结合了CPU时间和内存使用量,提供了良好的安全性同时保持了性能平衡。支持三种模式:Argon2d(侧重数据独立性)、Argon2i(侧重抵御旁路攻击)和Argon2id(结合前两者优点)。Argon2参数可调性强,可以设置迭代次数、内存占用量和平行处理线程数。Argon2被认为是目前最先进的密码哈希函数之一,广泛推荐用于新系统的设计中。

Argon2适合对安全性和灵活性都有高要求的应用,尤其是那些希望采用最新标准来提升安全性的场合。

  • PBKDF2(Pbkdf2PasswordEncoder):

PBKDF2基于一个伪随机函数(通常是HMAC)来生成密钥。允许通过指定迭代次数来控制计算强度,从而增加从弱密码派生强密钥所需的时间。PBKDF2没有内置的内存硬性特性,因此相对于Scrypt和Argon2来说,在对抗专门针对它的硬件攻击方面较弱。

PBKDF2常用于密钥派生功能,尤其是在需要与现有系统兼容的情况下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

緑水長流*z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值