全网最详尽的加密解密算法相关知识总结,附带Java Demo

密码学的概念及应用

密码学是一个历史悠久的学问,关于密码学的前世今生,大家可以参照这本书

https://crypt.wenwoha.com/preface/index.html

一、什么是密码学

密码学是一种通过使用代码保护信息和通信的方案,因此只有信息的预期对象才能阅读和处理它。密码学是一种重要的安全工具,可用于多种应用,包括:

  • 安全通信。密码学用于保护传输中的数据,例如电子邮件、网页浏览和文件传输。比如https普遍使用的TLS/SSL技术
  • 静态数据。密码学用于保护存储在计算机上的数据,例如密码、财务信息和医疗记录。
  • 数字签名:密码学用于创建数字签名,可用于验证消息或文档的真实性。
  • 不可否认性:密码学可用于提供不可否认性,这意味着发送者不能拒绝发送消息或接收者不能拒绝接收消息。

密码学早在公元前400多年就已经产生,人类使用密码的历史几乎与使用文字的时间一样长。

密码学的发展大致可以分为 3 个阶段:

  1. 1949 年之前的古典密码学阶段;

  2. 1949 年至 1975 年密码学成为科学的分支;

  3. 1976 年以后对称密钥密码算法得到进一步发展,产生了密码学的新方向—公钥密码学。

    1976 年,W.Diffie 和 M.Hellman 在发表的文章“密码学的新方向”中首次公开提出了公钥密码( Public-key Cryptography) 的概念。公钥密码的提出实现了加密密钥和解密密钥之间的独立,解决了对称密码体制中通信双方必须共享密钥的问题,在密码学界具有划时代的意义。

二、对称加密和非对称加密

现有人类社会的密码学应用方式无外乎就是对称加密非对称加密。

对称加密:对称密钥加密使用单个密钥来加密和解密数据。这种类型的密码术相对较快,但它要求发送方和接收方共享密钥。

非对称加密:非对称密钥加密使用两个密钥:公钥和私钥。公钥用于加密数据,私钥用于解密数据。这种类型的加密比对称密钥加密慢,但它不需要在发送方和接收方之间共享密钥。

2.1 市面上常用的对称加密

目前市面上常见的对称加密方式有 DES、3DES、AES、TDEA、Blowfish、RC2、RC4RC5 等。

2.1.1 DES和3DES

数据加密标准 (DES) 和三重 DES (3DES) 都是用于加密数据的分组密码。 DES 的密钥大小为 56 位,而 3DES 的密钥大小为 112 或 168 位。这意味着 3DES 比 DES 更安全,因为破解 3DES 密钥比破解 DES 密钥需要更长的时间。

DES 于 1977 年首次发布,多年来一直是数据加密的标准。然而,随着计算机变得越来越强大,DES 变得更容易被破解。 1999 年,一个 distributed.net 项目能够在 22 小时内破解 DES 密钥。

3DES 是为了应对 DES 日益增加的安全漏洞而开发的。 3DES 的工作原理是使用两个或三个密钥对数据进行三次加密。这使得 3DES 比 DES 安全得多,并且至今仍被认为是安全的。

然而,3DES 也比 DES 慢,因为它需要三个加密操作。这使得 3DES 不太适合速度至关重要的应用程序。

如今,3DES 正在被更新、更安全的分组密码所取代,例如高级加密标准 (AES)。 AES 的密钥大小为 128 位,被认为是当今可用的最安全的分组密码。

2.1.2 AES算法

AES(高级加密标准) 被认为是当今可用的最安全的分组密码,是目前全球使用最广泛的对称加密算法。至今仍然具有霸主地位。

AES诞生自美国政府选择它来替代数据加密标准 (DES)。 AES 是一种块密码,这意味着它以 128 位的块对数据进行加密。 AES 具有三种密钥大小:128、192 和 256 位。密钥大小决定了加密的强度。 128 位密钥被认为是非常安全的,以目前的技术破解是不可行的。 192 位密钥更加安全,而 256 位密钥被认为是牢不可破的。

2.1.3 RC算法

RC 算法是由 Ron Rivest 发明的一系列对称密钥加密算法。 “RC”可以代表 Rivest 的密码,或者更通俗地说,代表 Ron 的密码。尽管它们的名称相似,但这些算法在很大程度上是不相关的。到目前为止已经有六种RC算法:

  • RC1 从未发布。
  • RC2 是 1987 年开发的 64 位分组密码。
  • RC3 在使用之前就坏了。
  • RC4 是一种流密码。
  • RC5 是 1994 年开发的 32/64/128 位分组密码。
  • RC6 是一种主要基于 RC5 的 128 位块密码,是 1997 年开发的 AES 决赛入围者。

RC4 是使用最广泛的 RC 算法。它是一种流密码,这意味着它一次加密一位或一个字节的数据。 RC4 是一种非常快的算法,并且很容易在软件中实现。 RC4 用于各种应用,包括:

  • 安全套接字层 (SSL):SSL 是一种用于在 Internet 上传输数据时对其进行加密的协议。 RC4 通常用作 SSL 中的加密算法。
  • 无线网络:RC4 通常用于加密无线网络中的数据,例如 Wi-Fi 和蓝牙。
  • 文件加密:RC4常用来加密文件,如密码文件、财务文件等。

2.1.4 主要实现

Java原生JDK提供了几乎以上所有的对称加密算法,但是自JDK1.8之后,oracle协议变更,私有包可能无法访问,所以建议使用的实现依然是Bouncycastle

JDK原生提供了Cipher类以支持加解密。

加密AES示例:

// 创建一个密码实体,使用AES Provider
Cipher cipher = Cipher.getInstance("AES");

// 随机生成一个key
SecretKey key = KeyGenerator.getInstance("AES").generateKey();

// 执行加密模式
cipher.init(Cipher.ENCRYPT_MODE, key);

// 得到加密数据
byte[] encryptedData = cipher.doFinal(plaintextData);

解密AES示例:

// 创建一个密码实体,使用AES Provider
Cipher cipher = Cipher.getInstance("AES");

// 随机生成一个key
SecretKey key = KeyGenerator.getInstance("AES").generateKey();

// 执行解密模式
cipher.init(Cipher.DECRYPT_MODE, key);

// 得到解密数据
byte[] decryptedData = cipher.doFinal(encryptedData);

实际使用中,我们使用一个特定字符串来作为key,同时要保障key安全。

2.1.5 Bouncy Castle密码套件

作为当前最流行的密码学Java实现,我们有必要单独介绍一下。

Bouncy Castle 是一个用 Java 编写的免费开源加密库。它提供了广泛的密码算法和工具,包括:

  • 分组密码,例如 AES、DES 和 3DES
  • 流密码,例如 RC4 和 Salsa20
  • 哈希函数,例如 SHA-256 和 SHA-512
  • 数字签名,例如 RSA 和 DSA
  • 密钥交换算法,例如 DH算法和 ECC椭圆曲线算法

当前最新版本为1.74,最后更新于6月12日,请大家一直保持稳定版。

详细的介绍大家可以查阅官方网站:http://www.bouncycastle.org/

我们可以尽情基于jce使用。使用示例:

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.Security;

public class EncryptMessage {

    public static void main(String[] args) throws Exception {
        // 注册bc的算法提供者
        Security.addProvider(new BouncyCastleProvider());

        // 生成128密钥位的密钥
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128);
        SecretKey secretKey = keyGenerator.generateKey();

        // 创建密码对象并设置为加密模式
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        // 加密消息
        byte[] encryptedMessage = cipher.doFinal("Hello, world!".getBytes());
    }
}

2.2 市面上常用的非对称加密

常见的非对称加密算法有:**RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)**等。

现在国际上广泛使用的非对称加密依然是RSA,但是ECC算法因其优越性,正在越来越主流。

2.2.1 RSA加密

RSA 算法是一种迄今为止理论上比较成熟和完善的公钥密码体制,是非对称密码体制的典型代表。在网络、信息安全等许多方面都使用 RSA 算法,特别是 RSA 算法典型应用在通信中的数字签名,可实现对手的身份、不可抵赖性验证。在身份认证、信息安全、电子商务中有着广泛的应用前景。

2.2.1.1 基本原理

RSA 算法由密钥的产生、加密算法和解密算法 3 个部分组成。

密钥的产生过程如下:

  1. 产生两个大素数 p 和 q ;
  2. 计算 n = p × q n = p \times q n=p×q,欧拉函数 φ ( n ) = ( p − 1 ) ( q − 1 ) \varphi(n) =(p - 1)(q - 1) φ(n)=(p1)(q1)
  3. 选择整数 e ,使其满足条件:1 < e < φ(n) ,且gcd(e,φ(n)) = 1(注:gcd () 函数计算两个数的最大公约数);
  4. 计算 e 的逆元 d :d∙e ≡ 1 mod φ(n)(注:由于gcd(e,φ(n)) = 1,则 d 一定存在);
  5. 取序对 (e,n) 为公钥,可公开;(d,n) 为私钥,对外保密。

加密算法过程如下:

将要发送的字符串分割为长度为 m < n 的分组,然后对分组 mi 执行加密运算,得到密文

c i ≡ ( m i ) e   m o d   n ci ≡(mi)e \bmod n ci(mi)emodn

解密算法过程如下:

收到密文 ci 后,接收者使用自己的私钥执行解密运算,得到明文

m i ≡ ( c i ) d   m o d   n mi ≡(ci)d \bmod n mi(ci)dmodn

2.2.1.2 应用

在Java端,我们可以用BouncyCastle来支持RSA。

// 生成密钥对
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
KeyPair pair = generator.generateKeyPair();

// 得到公钥
PublicKey publicKey = pair.getPublic();

// 加密消息
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedMessage = cipher.doFinal("Hello, world!".getBytes());

// 获得私钥
PrivateKey privateKey = pair.getPrivate();

// 解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedMessage = cipher.doFinal(Files.readAllBytes(Paths.get("encrypted-message.txt")));

RSA 可用于多种应用,包括:

  • 安全消息传递:RSA 可用于加密和解密消息。
  • 数据加密:RSA可用于加密数据文件。
  • 数字签名:RSA 可用于生成和验证数字签名。
  • 密钥交换:RSA 可用于安全地交换密钥。
  • Web 安全:RSA 可用于实现各种 Web 安全功能,例如 SSL/TLS 和 X.509 证书。

2.2.2 ECC椭圆曲线算法

椭圆曲线加密算法(ECC)是基于椭圆曲线数学的一种非对称密码算法,是建立在基于椭圆曲线的离散对数问题上的密码体制。

随着分解大整数方法的进步以及各方面的完善,RSA 算法渐渐不能满足现状,ECC 算法的需求性逐渐增大。ECC 以其明显的“短密钥”优势得到了广泛应用,并逐渐被确定为许多编码方式的数字签名标准。

当然,ECC 还有许多未解决的问题,不过这种引用了丰富数学理论的算法,也印证了将更多数学有较大可行性理论应用到密码学这一领域中。

2.2.2.1 ECC原理

首先从数学角度阐释算法加密原理,ECC椭圆曲线加密算法数学基础是利用有限域上椭圆曲线离散对数问题(ECDLP)的计算困难性,所谓椭圆曲线是指由韦尔斯特拉方程。其椭圆曲线方程如下:

y 2 + a 1 x y + a 2 y = x 3 + a 3 x 2 + a 4 x + a 5 y^2 + a_1xy + a_2 y = x^3 + a_3x^2 + a_4 x + a_5 y2+a1xy+a2y=x3+a3x2+a4x+a5

2.2.2.2 ECC的应用

ECC的用途跟RSA几乎一致,我们在选择RSA还是ECC主要考究的还是支持场景的广泛性。

ECC 密钥比传统的 RSA 密钥小得多,这使得它们的使用效率更高。 ECC 密钥也被认为比 RSA 密钥更安全,这使得它们成为需要高安全性的应用程序的不错选择,例如网上银行和电子商务。

ECC最主要的用途是加速SSL访问,能够在相同的安全性下很明显提升服务器性能。大多数现代 Web 浏览器和服务器都支持 ECC 证书。但是,有些较旧的浏览器和服务器不支持 ECC 证书。

以下是一些支持 ECC 证书的最流行的浏览器和服务器:

  • 网络浏览器:Chrome、Firefox、Edge、Safari、Opera
  • 服务器:Apache、Nginx、IIS

2.2.3 SSL/TLS及相关技术

为了实现网络安全,所有传输在https协议上的数据都经过了加密处理。

TLS/SSL中使用了非对称加密,对称加密以及HASH算法
在这里插入图片描述

2.2.3.1 DH算法

Diffie–Hellman key exchange,缩写为DH, 是一种安全协议,用于双方在一个不安全的通信网络上建立一个共享的秘钥,有了共享秘钥以后,就可以使用这个密钥加密交互消息。由于通信双方最终使用的密钥相同,所以可以认为该协议目标是创建一个对称密钥(对称密钥和非对称密钥可自行学习)。该协议也称迪菲-赫尔曼密钥协商,名字以发明人的名字命名,符合惯例,无其他特殊意义。

在这里插入图片描述

迪菲-赫尔曼密钥交换本身是一个匿名(无认证)的密钥交换协议,它却是很多认证协议的基础,并且被用来提供传输层安全协议的短暂模式中的前向安全性。

DH协议是SSL实现密钥交换的核心算法,它能保证密钥在传输过程中安全可靠。

2.2.3.2 SSL和TLS协议

SSL(Secure Socket Layer,安全套接字层):1994年为 Netscape 所研发,SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持。

TLS(Transport Layer Security,传输层安全):其前身是 SSL。

它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)由网景公司开发,1999年从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL3.0和TLS1.0由于存在安全漏洞,已经很少被使用到。TLS 1.3 改动很大,极大提升了安全性和访问速度,目前所有现代浏览器均已很好的支持。

但是目前使用最广泛的还是TLS 1.1、TLS 1.2。

2.3 我国的标准加密协议

国密即国家密码局认定的国产密码算法。主要有 SM1、SM2、SM3、SM4。密钥长度和分组长度均为 128 位。SM1 为对称加密,SM2 为非对称加密,SM3 消息摘要,SM4 分组密码算法。

SM2国密二算法基于椭圆曲线ECC算法,性能要优于RSA,所以,在常规加密业务中,我们经常会考虑是使用SM2算法替代RSA算法,保证内容交换的高效。

目前国内很多开源组件都完整实现了国密算法,从Java到JavaScript再到C++,大家可以根据需要选择符合我国国情的加密算法,增加产品的安全性。

对于国密的详细实现原理以及java应用,大家感兴趣可以参考以下帖子:

https://crypt.wenwoha.com/china/index.html

三、单向散列函数(算法)

本章节的范畴其实已经不属于加密了,但鉴于大家经常会混淆这些概念,所以特地做一下强调。

单向散列函数,又称单向Hash函数、杂凑函数,就是把任意长度的输入消息串变化成固定长的输出串且由输出串难以得到输入串的一种函数。这个输出串称为该消息的散列值。一般用于产生消息摘要,密钥加密等。

目前最常用的算法是MD5,其次是SHA、SHA-2、SHA-3等。

注意,单向散列函数不属于加密,因为它不可逆,也就是不可解密,但是日然属于密码学的范畴,人类用它来进行数据安全的保障。

3.1 MD5算法

MD5是RSA数据安全公司开发的一种单向散列算法,它被广泛使用,可以用来把不同长度的数据块进行暗码运算成一个128位的数值。不同的值产生的结果不一样。

3.1.1 MD5实现

就java语言来说,JDK封装了MD5算法的基础支持,此外还有许多第三方库也实现了该算法。使用最广泛的实现是 MessageDigest 类,它在 java.security 包中定义。

import java.security.MessageDigest;

public class MD5 {

    public static void main(String[] args) throws Exception {
        // 创建一个消息摘要对象
        MessageDigest digest = MessageDigest.getInstance("MD5");

        // 将要计算的文本转换为字节数组
        byte[] data = "Hello, world!".getBytes();

        // 更新消息摘要对象内的数据体
        digest.update(data);

        // 计算得到摘要结果
        byte[] digestValue = digest.digest();

        // 将摘要结果转换为32位的hex数字文本
        String hexString = new String(digestValue, "UTF-8");
        
        // 将输出 97c992559122e4d1f4a42fd7a2fdb848
        System.out.println(hexString);
    }
}

我们一般会以字符串作为输入输出端,所以大多数时候都是简单封装一个工具类即可。

此外,在JavaScript中,有很多成熟的库已经支持了md5,如md5js

3.1.2 MD5 用途

一致性验证

MD5的典型应用是对一段文本信息产生信息摘要,以防止被篡改。常常在某些软件下载站点的某软件信息中看到其MD5值,它的作用就在于我们可以在下载该软件后,对下载回来的文件用专门的软件(如Windows MD5 Check等)做一次MD5校验,以确保我们获得的文件与该站点提供的文件为同一文件。

数字证书

如果有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。

安全访问认证

在Unix系统中用户的密码是以MD5(或其它类似的算法)经Hash运算后存储在文件系统中。当用户登录的时候,系统把用户输入的密码进行MD5 Hash运算,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。

3.2 SHA算法以及它的改版

安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。

且若输入的消息不同,它们对应到不同字符串的机率很高。SHA家族算法分别是SHA-0;SHA-1;SHA-224、SHA-256、SHA-384,SHA-512和SHA3。

SHA-224、SHA-256、SHA-384,SHA-512有时并称为SHA-2, SHA3是第三代安全散列算法(Secure Hash Algorithm 3),之前名为Keccak 算法,在硬件实做上面,这个算法比起其他算法明显的快上很多,目前 SHA-0,SHA-1 已被破解。

3.2.1 主要用途

我们常用SHA-256来生成散列密钥,这也是”中间定律“在密码学中的极致体现,除此之外,SHA 算法的主要目的是提供一种安全的方法来验证数据的真实性和完整性。 SHA 算法用于各种应用,包括:

  • 数字签名:SHA 算法用于创建数字签名,可用于验证消息或文档的真实性。
  • 数据完整性验证:SHA 算法可用于通过将数据的哈希值与已知哈希值进行比较来验证数据的完整性。
  • 密码哈希:可以使用SHA算法对密码进行哈希处理,使攻击者更难破解密码。
  • 文件验证:SHA 算法可用于通过将文件的哈希值与已知哈希值进行比较来验证文件的完整性。

3.2.2 核心实现

和MD5类似,java的MessageDigest类也提供了内置的SHA算法实现。以下是用java实现一个SHA-256算法的示例。

import java.security.MessageDigest;

public class SHA {

    public static void main(String[] args) throws Exception {
        // 创建一个消息摘要对象
        MessageDigest digest = MessageDigest.getInstance("SHA-256");

        // 将要计算的文本转换为字节数组
        byte[] data = "Hello, world!".getBytes();

        // 更新消息摘要对象内的数据体
        digest.update(data);

        // 计算得到摘要结果
        byte[] digestValue = digest.digest();

        // 将摘要结果转换为64位的hex数字文本
        String hexString = new String(digestValue, "UTF-8");

        // 将输出 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
        System.out.println(hexString);
    }
}

除了 MessageDigest 类之外,还有其他几个 Java 的 SHA 算法的实现,包括:

  • BouncyCastle
  • Apache Commons Codec Apache Commons
  • Google Guava

这些实现提供了额外的特性,例如支持不同的散列算法和为数据流生成 SHA 散列。

Java 的 SHA 算法使用最广泛的实现是 MessageDigest 类。它是最基本、最直接的实现,包含在标准 Java 发行版中。

四、数据裸编码

裸编码在计算机中是一个非常常用的数据处理方式。从定义上来讲,所有按照一定规则,在不丢失二进制数据完整性,能在编码后求得原数据的方式,都叫做数据裸编码。

在实际应用中,我们见得最多的就是HEX编码和Base64编码。

4.1 HEX编码

HEX编码其实属于一种裸编码,目标是将二进制数组byte[]转为人类可读字符串的常用算法。

它的原理非常简单。

十六进制编码的原理是将二进制数据的每个字节转换成两个十六进制数字。十六进制数字是数字 0 到 9 和字母 A 到 F。每个十六进制数字可以表示 4 位二进制数据。所以,两个十六进制数可以表示8位二进制数据,相当于一个字节。

例如,二进制数据 10101010 将被编码为十六进制数字 A2。第一个十六进制数字 A 代表四位 1010。第二个十六进制数字 2 代表四位 1010。

4.2 Base64编码

Base64 是一种将二进制数据表示为可打印字符串的方法。它通常用于通过旨在传输文本的协议(例如 HTTP 和 SMTP)传输二进制数据。

Base64 编码的工作原理是将每组三个字节的二进制数据转换为四个字符的文本。这些字符选自一组 64 个字符,其中包括数字 0-9、字母 A-Z 以及字符 + 和 /。

例如,二进制数据 10101010 将被编码为字符 A2。前两个字符 A 和 2 代表二进制数据的前两个字节。第三个字符+,代表二进制数据的第三个字节。第四个字符 / 是一个填充字符,添加它是为了使编码数据成为四个字符的倍数。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小爬的老粉丝

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

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

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

打赏作者

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

抵扣说明:

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

余额充值