mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-08-10 00:41:37 +08:00
Compare commits
10 Commits
b4c823dc04
...
4a924c7d89
Author | SHA1 | Date | |
---|---|---|---|
|
4a924c7d89 | ||
|
8ddd8f4d22 | ||
|
9c79111db7 | ||
|
6fd0ce9fbf | ||
|
79ee37eb29 | ||
|
4f35a6b2e2 | ||
|
43145485af | ||
|
2f262ab8a5 | ||
|
9458aa9909 | ||
|
0f708e691a |
@ -52,7 +52,7 @@ star: 2
|
|||||||
|
|
||||||
免费赠送多本优质 PDF 面试手册。
|
免费赠送多本优质 PDF 面试手册。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### 优质精华主题沉淀
|
### 优质精华主题沉淀
|
||||||
|
|
||||||
@ -125,9 +125,11 @@ star: 2
|
|||||||
|
|
||||||
## 如何加入?
|
## 如何加入?
|
||||||
|
|
||||||
**方式一(不推荐)**:扫描下面的二维码原价加入(续费半价不到)。
|
**方式一(不推荐)**:扫描下面的 10 元优惠卷直接加入(续费半价不到)。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
使用这种方式进入的话,建议你也添加一下我的个人微信(**备注“星球”**即可),方便后续交流沟通。
|
||||||
|
|
||||||
**方式二(推荐)**:添加我的个人微信(**javaguide1024**)领取一个 **30** 元的星球专属优惠券(续费半价不到)。
|
**方式二(推荐)**:添加我的个人微信(**javaguide1024**)领取一个 **30** 元的星球专属优惠券(续费半价不到)。
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ tag:
|
|||||||
|
|
||||||
### 4.2. 重要知识点总结
|
### 4.2. 重要知识点总结
|
||||||
|
|
||||||
1. **TCP/IP 协议中的网络层向上只提供简单灵活的,无连接的,尽最大努力交付的数据报服务。网络层不提供服务质量的承诺,不保证分组交付的时限所传送的分组可能出错,丢失,重复和失序。进程之间通信的可靠性由运输层负责**
|
1. **TCP/IP 协议中的网络层向上只提供简单灵活的,无连接的,尽最大努力交付的数据报服务。网络层不提供服务质量的承诺,不保证分组交付的时限,所传送的分组可能出错、丢失、重复和失序。进程之间通信的可靠性由运输层负责**
|
||||||
2. 在互联网的交付有两种,一是在本网络直接交付不用经过路由器,另一种是和其他网络的间接交付,至少经过一个路由器,但最后一次一定是直接交付
|
2. 在互联网的交付有两种,一是在本网络直接交付不用经过路由器,另一种是和其他网络的间接交付,至少经过一个路由器,但最后一次一定是直接交付
|
||||||
3. 分类的 IP 地址由网络号字段(指明网络)和主机号字段(指明主机)组成。网络号字段最前面的类别指明 IP 地址的类别。IP 地址是一种分等级的地址结构。IP 地址管理机构分配 IP 地址时只分配网络号,主机号由得到该网络号的单位自行分配。路由器根据目的主机所连接的网络号来转发分组。一个路由器至少连接到两个网络,所以一个路由器至少应当有两个不同的 IP 地址
|
3. 分类的 IP 地址由网络号字段(指明网络)和主机号字段(指明主机)组成。网络号字段最前面的类别指明 IP 地址的类别。IP 地址是一种分等级的地址结构。IP 地址管理机构分配 IP 地址时只分配网络号,主机号由得到该网络号的单位自行分配。路由器根据目的主机所连接的网络号来转发分组。一个路由器至少连接到两个网络,所以一个路由器至少应当有两个不同的 IP 地址
|
||||||
4. IP 数据报分为首部和数据两部分。首部的前一部分是固定长度,共 20 字节,是所有 IP 数据包必须具有的(源地址,目的地址,总长度等重要地段都固定在首部)。一些长度可变的可选字段固定在首部的后面。IP 首部中的生存时间给出了 IP 数据报在互联网中所能经过的最大路由器数。可防止 IP 数据报在互联网中无限制的兜圈子。
|
4. IP 数据报分为首部和数据两部分。首部的前一部分是固定长度,共 20 字节,是所有 IP 数据包必须具有的(源地址,目的地址,总长度等重要地段都固定在首部)。一些长度可变的可选字段固定在首部的后面。IP 首部中的生存时间给出了 IP 数据报在互联网中所能经过的最大路由器数。可防止 IP 数据报在互联网中无限制的兜圈子。
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
@ -79,9 +79,9 @@ B 为帮助 A 能顺利连接,需要**分配内核资源**维护半开连接
|
|||||||
|
|
||||||
**恶意用户可通过三种不同方式发起 SYN Flood 攻击**:
|
**恶意用户可通过三种不同方式发起 SYN Flood 攻击**:
|
||||||
|
|
||||||
1. **直接攻击:**不伪造 IP 地址的 SYN 洪水攻击称为直接攻击。在此类攻击中,攻击者完全不屏蔽其 IP 地址。由于攻击者使用具有真实 IP 地址的单一源设备发起攻击,因此很容易发现并清理攻击者。为使目标机器呈现半开状态,黑客将阻止个人机器对服务器的 SYN-ACK 数据包做出响应。为此,通常采用以下两种方式实现:部署防火墙规则,阻止除 SYN 数据包以外的各类传出数据包;或者,对传入的所有 SYN-ACK 数据包进行过滤,防止其到达恶意用户机器。实际上,这种方法很少使用(即便使用过也不多见),因为此类攻击相当容易缓解 – 只需阻止每个恶意系统的 IP 地址。哪怕攻击者使用僵尸网络(如 [Mirai 僵尸网络](https://www.cloudflare.com/learning/ddos/glossary/mirai-botnet/)),通常也不会刻意屏蔽受感染设备的 IP。
|
1. **直接攻击:** 不伪造 IP 地址的 SYN 洪水攻击称为直接攻击。在此类攻击中,攻击者完全不屏蔽其 IP 地址。由于攻击者使用具有真实 IP 地址的单一源设备发起攻击,因此很容易发现并清理攻击者。为使目标机器呈现半开状态,黑客将阻止个人机器对服务器的 SYN-ACK 数据包做出响应。为此,通常采用以下两种方式实现:部署防火墙规则,阻止除 SYN 数据包以外的各类传出数据包;或者,对传入的所有 SYN-ACK 数据包进行过滤,防止其到达恶意用户机器。实际上,这种方法很少使用(即便使用过也不多见),因为此类攻击相当容易缓解 – 只需阻止每个恶意系统的 IP 地址。哪怕攻击者使用僵尸网络(如 [Mirai 僵尸网络](https://www.cloudflare.com/learning/ddos/glossary/mirai-botnet/)),通常也不会刻意屏蔽受感染设备的 IP。
|
||||||
2. **欺骗攻击:**恶意用户还可以伪造其发送的各个 SYN 数据包的 IP 地址,以便阻止缓解措施并加大身份暴露难度。虽然数据包可能经过伪装,但还是可以通过这些数据包追根溯源。此类检测工作很难开展,但并非不可实现;特别是,如果 Internet 服务提供商 (ISP) 愿意提供帮助,则更容易实现。
|
2. **欺骗攻击:** 恶意用户还可以伪造其发送的各个 SYN 数据包的 IP 地址,以便阻止缓解措施并加大身份暴露难度。虽然数据包可能经过伪装,但还是可以通过这些数据包追根溯源。此类检测工作很难开展,但并非不可实现;特别是,如果 Internet 服务提供商 (ISP) 愿意提供帮助,则更容易实现。
|
||||||
3. **分布式攻击(DDoS):**如果使用僵尸网络发起攻击,则追溯攻击源头的可能性很低。随着混淆级别的攀升,攻击者可能还会命令每台分布式设备伪造其发送数据包的 IP 地址。哪怕攻击者使用僵尸网络(如 Mirai 僵尸网络),通常也不会刻意屏蔽受感染设备的 IP。
|
3. **分布式攻击(DDoS):** 如果使用僵尸网络发起攻击,则追溯攻击源头的可能性很低。随着混淆级别的攀升,攻击者可能还会命令每台分布式设备伪造其发送数据包的 IP 地址。哪怕攻击者使用僵尸网络(如 Mirai 僵尸网络),通常也不会刻意屏蔽受感染设备的 IP。
|
||||||
|
|
||||||
### 如何缓解 SYN Flood?
|
### 如何缓解 SYN Flood?
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ DNS Flood 对传统上基于放大的攻击方法做出了改变。借助轻易
|
|||||||
|
|
||||||
> 建立 TCP 连接
|
> 建立 TCP 连接
|
||||||
|
|
||||||
可以使用 netcat 工具来建立 TCP 连接,这个工很多操作系统都预装了。打开第一个终端窗口,运行以下命令:
|
可以使用 netcat 工具来建立 TCP 连接,这个工具很多操作系统都预装了。打开第一个终端窗口,运行以下命令:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ nc -nvl 8000
|
$ nc -nvl 8000
|
||||||
|
@ -95,7 +95,7 @@ OSI 七层模型虽然失败了,但是却提供了很多不错的理论基础
|
|||||||
|
|
||||||
**网络层常见协议**:
|
**网络层常见协议**:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- **IP(Internet Protocol,网际协议)**:TCP/IP 协议中最重要的协议之一,主要作用是定义数据包的格式、对数据包进行路由和寻址,以便它们可以跨网络传播并到达正确的目的地。目前 IP 协议主要分为两种,一种是过去的 IPv4,另一种是较新的 IPv6,目前这两种协议都在使用,但后者已经被提议来取代前者。
|
- **IP(Internet Protocol,网际协议)**:TCP/IP 协议中最重要的协议之一,主要作用是定义数据包的格式、对数据包进行路由和寻址,以便它们可以跨网络传播并到达正确的目的地。目前 IP 协议主要分为两种,一种是过去的 IPv4,另一种是较新的 IPv6,目前这两种协议都在使用,但后者已经被提议来取代前者。
|
||||||
- **ARP(Address Resolution Protocol,地址解析协议)**:ARP 协议解决的是网络层地址和链路层地址之间的转换问题。因为一个 IP 数据报在物理上传输的过程中,总是需要知道下一跳(物理上的下一个目的地)该去往何处,但 IP 地址属于逻辑地址,而 MAC 地址才是物理地址,ARP 协议解决了 IP 地址转 MAC 地址的一些问题。
|
- **ARP(Address Resolution Protocol,地址解析协议)**:ARP 协议解决的是网络层地址和链路层地址之间的转换问题。因为一个 IP 数据报在物理上传输的过程中,总是需要知道下一跳(物理上的下一个目的地)该去往何处,但 IP 地址属于逻辑地址,而 MAC 地址才是物理地址,ARP 协议解决了 IP 地址转 MAC 地址的一些问题。
|
||||||
|
@ -88,7 +88,7 @@ tag:
|
|||||||
|
|
||||||
#### 网络层有哪些常见的协议?
|
#### 网络层有哪些常见的协议?
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- **IP(Internet Protocol,网际协议)**:TCP/IP 协议中最重要的协议之一,属于网络层的协议,主要作用是定义数据包的格式、对数据包进行路由和寻址,以便它们可以跨网络传播并到达正确的目的地。目前 IP 协议主要分为两种,一种是过去的 IPv4,另一种是较新的 IPv6,目前这两种协议都在使用,但后者已经被提议来取代前者。
|
- **IP(Internet Protocol,网际协议)**:TCP/IP 协议中最重要的协议之一,属于网络层的协议,主要作用是定义数据包的格式、对数据包进行路由和寻址,以便它们可以跨网络传播并到达正确的目的地。目前 IP 协议主要分为两种,一种是过去的 IPv4,另一种是较新的 IPv6,目前这两种协议都在使用,但后者已经被提议来取代前者。
|
||||||
- **ARP(Address Resolution Protocol,地址解析协议)**:ARP 协议解决的是网络层地址和链路层地址之间的转换问题。因为一个 IP 数据报在物理上传输的过程中,总是需要知道下一跳(物理上的下一个目的地)该去往何处,但 IP 地址属于逻辑地址,而 MAC 地址才是物理地址,ARP 协议解决了 IP 地址转 MAC 地址的一些问题。
|
- **ARP(Address Resolution Protocol,地址解析协议)**:ARP 协议解决的是网络层地址和链路层地址之间的转换问题。因为一个 IP 数据报在物理上传输的过程中,总是需要知道下一跳(物理上的下一个目的地)该去往何处,但 IP 地址属于逻辑地址,而 MAC 地址才是物理地址,ARP 协议解决了 IP 地址转 MAC 地址的一些问题。
|
||||||
|
@ -101,7 +101,7 @@ inode 是 Linux/Unix 文件系统的基础。那 inode 到是什么?有什么作
|
|||||||
**2、软链接(Symbolic Link 或 Symlink)**
|
**2、软链接(Symbolic Link 或 Symlink)**
|
||||||
|
|
||||||
- 软链接和源文件的 inode 节点号不同,而是指向一个文件路径。
|
- 软链接和源文件的 inode 节点号不同,而是指向一个文件路径。
|
||||||
- 源文件删除后,硬链接依然存在,但是指向的是一个无效的文件路径。
|
- 源文件删除后,软链接依然存在,但是指向的是一个无效的文件路径。
|
||||||
- 软连接类似于 Windows 系统中的快捷方式。
|
- 软连接类似于 Windows 系统中的快捷方式。
|
||||||
- 不同于硬链接,可以对目录或者不存在的文件创建软链接,并且,软链接可以跨越文件系统。
|
- 不同于硬链接,可以对目录或者不存在的文件创建软链接,并且,软链接可以跨越文件系统。
|
||||||
- `ln -s` 命令用于创建软链接。
|
- `ln -s` 命令用于创建软链接。
|
||||||
|
@ -33,7 +33,7 @@ head:
|
|||||||
内存碎片是由内存的申请和释放产生的,通常分为下面两种:
|
内存碎片是由内存的申请和释放产生的,通常分为下面两种:
|
||||||
|
|
||||||
- **内部内存碎片(Internal Memory Fragmentation,简称为内存碎片)**:已经分配给进程使用但未被使用的内存。导致内部内存碎片的主要原因是,当采用固定比例比如 2 的幂次方进行内存分配时,进程所分配的内存可能会比其实际所需要的大。举个例子,一个进程只需要 65 字节的内存,但为其分配了 128(2^7) 大小的内存,那 63 字节的内存就成为了内部内存碎片。
|
- **内部内存碎片(Internal Memory Fragmentation,简称为内存碎片)**:已经分配给进程使用但未被使用的内存。导致内部内存碎片的主要原因是,当采用固定比例比如 2 的幂次方进行内存分配时,进程所分配的内存可能会比其实际所需要的大。举个例子,一个进程只需要 65 字节的内存,但为其分配了 128(2^7) 大小的内存,那 63 字节的内存就成为了内部内存碎片。
|
||||||
- **外部内存碎片(External Memory Fragmentation,简称为外部碎片)**:由于未分配的连续内存区域太小,以至于不能满足任意进程所需要的内存分配请求,这些小片段且不连续的内存空间被称为外部碎片。也就是说,外部内存碎片指的是那些并为分配给进程但又不能使用的内存。我们后面介绍的分段机制就会导致外部内存碎片。
|
- **外部内存碎片(External Memory Fragmentation,简称为外部碎片)**:由于未分配的连续内存区域太小,以至于不能满足任意进程所需要的内存分配请求,这些小片段且不连续的内存空间被称为外部碎片。也就是说,外部内存碎片指的是那些并未分配给进程但又不能使用的内存。我们后面介绍的分段机制就会导致外部内存碎片。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -203,7 +203,7 @@ MMU 将虚拟地址翻译为物理地址的主要机制有 3 种:
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
页表中还存有诸如访问标志(标识该页面有没有被访问过)、页类型(该段的类型,例如代码段、数据段等)等信息。
|
页表中还存有诸如访问标志(标识该页面有没有被访问过)、脏数据标识位等信息。
|
||||||
|
|
||||||
**通过虚拟页号一定要找到对应的物理页号吗?找到了物理页号得到最终的物理地址后对应的物理页一定存在吗?**
|
**通过虚拟页号一定要找到对应的物理页号吗?找到了物理页号得到最终的物理地址后对应的物理页一定存在吗?**
|
||||||
|
|
||||||
@ -362,7 +362,7 @@ LRU 算法是实际使用中应用的比较多,也被认为是最接近 OPT
|
|||||||
**2、软链接(Symbolic Link 或 Symlink)**
|
**2、软链接(Symbolic Link 或 Symlink)**
|
||||||
|
|
||||||
- 软链接和源文件的 inode 节点号不同,而是指向一个文件路径。
|
- 软链接和源文件的 inode 节点号不同,而是指向一个文件路径。
|
||||||
- 源文件删除后,硬链接依然存在,但是指向的是一个无效的文件路径。
|
- 源文件删除后,软链接依然存在,但是指向的是一个无效的文件路径。
|
||||||
- 软连接类似于 Windows 系统中的快捷方式。
|
- 软连接类似于 Windows 系统中的快捷方式。
|
||||||
- 不同于硬链接,可以对目录或者不存在的文件创建软链接,并且,软链接可以跨越文件系统。
|
- 不同于硬链接,可以对目录或者不存在的文件创建软链接,并且,软链接可以跨越文件系统。
|
||||||
- `ln -s` 命令用于创建软链接。
|
- `ln -s` 命令用于创建软链接。
|
||||||
|
@ -110,21 +110,21 @@ echo "helloworld!"
|
|||||||
|
|
||||||
字符串是 shell 编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号。这点和 Java 中有所不同。
|
字符串是 shell 编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号。这点和 Java 中有所不同。
|
||||||
|
|
||||||
在单引号中所有的特殊符号,如$和反引号都没有特殊含义。在双引号中,除了"$","\"和反引号,其他的字符没有特殊含义。
|
在单引号中所有的特殊符号,如$和反引号都没有特殊含义。在双引号中,除了"$"、"\\"、反引号和感叹号(需开启 `history expansion`),其他的字符没有特殊含义。
|
||||||
|
|
||||||
**单引号字符串:**
|
**单引号字符串:**
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
name='SnailClimb'
|
name='SnailClimb'
|
||||||
hello='Hello, I am '$name'!'
|
hello='Hello, I am $name!'
|
||||||
echo $hello
|
echo $hello
|
||||||
```
|
```
|
||||||
|
|
||||||
输出内容:
|
输出内容:
|
||||||
|
|
||||||
```
|
```
|
||||||
Hello, I am '$name'!
|
Hello, I am $name!
|
||||||
```
|
```
|
||||||
|
|
||||||
**双引号字符串:**
|
**双引号字符串:**
|
||||||
@ -132,7 +132,7 @@ Hello, I am '$name'!
|
|||||||
```shell
|
```shell
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
name='SnailClimb'
|
name='SnailClimb'
|
||||||
hello="Hello, I am "$name"!"
|
hello="Hello, I am $name!"
|
||||||
echo $hello
|
echo $hello
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ tag:
|
|||||||
```
|
```
|
||||||
|
|
||||||
- **heap size** 表示要初始化内存的具体大小。
|
- **heap size** 表示要初始化内存的具体大小。
|
||||||
- **unit** 表示要初始化内存的单位。单位为**_“ g”_** (GB)、**_“ m”_**(MB)、**_“ k”_**(KB)。
|
- **unit** 表示要初始化内存的单位。单位为 **_“ g”_** (GB)、**_“ m”_**(MB)、**_“ k”_**(KB)。
|
||||||
|
|
||||||
举个栗子 🌰,如果我们要为 JVM 分配最小 2 GB 和最大 5 GB 的堆内存大小,我们的参数应该这样来写:
|
举个栗子 🌰,如果我们要为 JVM 分配最小 2 GB 和最大 5 GB 的堆内存大小,我们的参数应该这样来写:
|
||||||
|
|
||||||
|
@ -18,9 +18,11 @@
|
|||||||
|
|
||||||
## 如何加入?
|
## 如何加入?
|
||||||
|
|
||||||
**方式一(不推荐)**:扫描下面的二维码原价加入(续费半价不到)。
|
**方式一(不推荐)**:扫描下面的 10 元优惠卷直接加入(续费半价不到)。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
使用这种方式进入的话,建议你也添加一下我的个人微信(**备注“星球”**即可),方便后续交流沟通。
|
||||||
|
|
||||||
**方式二(推荐)**:添加我的个人微信(**javaguide1024**)领取一个 **30** 元的星球专属优惠券(续费半价不到)。
|
**方式二(推荐)**:添加我的个人微信(**javaguide1024**)领取一个 **30** 元的星球专属优惠券(续费半价不到)。
|
||||||
|
|
||||||
|
@ -14,9 +14,11 @@
|
|||||||
|
|
||||||
## 如何加入?
|
## 如何加入?
|
||||||
|
|
||||||
**方式一(不推荐)**:扫描下面的二维码原价加入(续费半价不到)。
|
**方式一(不推荐)**:扫描下面的 10 元优惠卷直接加入(续费半价不到)。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
使用这种方式进入的话,建议你也添加一下我的个人微信(**备注“星球”**即可),方便后续交流沟通。
|
||||||
|
|
||||||
**方式二(推荐)**:添加我的个人微信(**javaguide1024**)领取一个 **30** 元的星球专属优惠券(续费半价不到)。
|
**方式二(推荐)**:添加我的个人微信(**javaguide1024**)领取一个 **30** 元的星球专属优惠券(续费半价不到)。
|
||||||
|
|
||||||
|
342
docs/system-design/security/encryption-algorithms.md
Normal file
342
docs/system-design/security/encryption-algorithms.md
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
加密算法是一种用数学方法对数据进行变换的技术,目的是保护数据的安全性和完整性,防止被未经授权的人读取或修改。加密算法可以分为三大类:对称加密算法、非对称加密算法和哈希算法(也叫摘要算法)。
|
||||||
|
|
||||||
|
日常开发中常见的需要用到的加密算法的场景:
|
||||||
|
|
||||||
|
1. 保存在数据库中的密码需要加盐之后使用哈希算法(比如 BCrypt)进行加密。
|
||||||
|
2. 保存在数据库中的银行卡号、身份号这类敏感数据需要使用对称加密算法(比如 AES)保存。
|
||||||
|
3. 网络传输的敏感数据比如银行卡号、身份号需要用 HTTPS + 非对称加密算法(如 RSA)来保证传输数据的安全性。
|
||||||
|
4. ......
|
||||||
|
|
||||||
|
## 哈希算法
|
||||||
|
|
||||||
|
哈希算法也叫哈希函数、散列函数或摘要算法,它的作用是对任意长度的数据生成一个固定长度的唯一标识,也叫哈希值、散列值或消息摘要(后文统称为哈希值)。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
哈希值的作用是可以用来验证数据的完整性和一致性。
|
||||||
|
|
||||||
|
举两个实际的例子:
|
||||||
|
|
||||||
|
- 我们下载一个文件时,可以通过比较文件的哈希值和官方提供的哈希值是否一致,来判断文件是否被篡改或损坏;
|
||||||
|
- 保存密码到数据库时使用哈希算法进行加密,可以通过比较用户输入密码的哈希值和数据库保存的哈希值是否一致,来判断密码是否正确。
|
||||||
|
|
||||||
|
这种算法的特点是不可逆:
|
||||||
|
|
||||||
|
- 不能从哈希值还原出原始数据。
|
||||||
|
- 原始数据的任何改变都会导致哈希值的巨大变化。
|
||||||
|
|
||||||
|
哈希算法主要下面几类:
|
||||||
|
|
||||||
|
- MD(Message Digest,消息摘要算法):比如 MD5。
|
||||||
|
- SHA(Secure Hash Algorithm,安全哈希算法):比如 SHA-1、SHA-256。
|
||||||
|
- MAC(Message Authentication Code,消息认证码算法):比如 HMAC(Hash Message Authentication Code)。
|
||||||
|
- 其他:国密算法(SM3)、密码哈希算法(Bcrypt)。
|
||||||
|
- ......
|
||||||
|
|
||||||
|
国密算法常见的如 SM2、SM3、SM4,其中 SM2 为非对称加密算法,SM4 为对称加密算法,SM3 为哈希算法(安全性及效率和 SHA-256 相当,但更适合国内的应用环境)。
|
||||||
|
|
||||||
|
哈希算法一般是不需要密钥的,但也存在部分特殊哈希算法需要密钥。例如,MAC 算法就是一种基于密钥的哈希算法,它在哈希算法的基础上增加了一个密钥,使得只有知道密钥的人才能验证数据的完整性和来源。
|
||||||
|
|
||||||
|
### MD
|
||||||
|
|
||||||
|
MD 算法有多个版本,包括 MD2、MD4、MD5 等,其中 MD5 是最常用的版本,它可以生成一个 128 位(16 字节)的哈希值。从安全性上说:MD5 > MD4 > MD2。除了这些版本,还有一些基于 MD4 或 MD5 改进的算法,如 RIPEMD、HAVAL 等。
|
||||||
|
|
||||||
|
即使是最安全 MD 算法 MD5 也存在被破解的风险,攻击者可以通过暴力破解或彩虹表攻击等方式,找到与原始数据相同的哈希值,从而破解数据。
|
||||||
|
|
||||||
|
为了增加破解难度,通常可以选择加盐。盐(Salt)在密码学中,是指通过在密码任意固定位置插入特定的字符串,让哈希后的结果和使用原始密码的哈希结果不相符,这种过程称之为“加盐”。
|
||||||
|
|
||||||
|
加盐之后就安全了吗?并不一定,这只是增加了破解难度,不代表无法破解。而且,MD5 算法本身就存在弱碰撞(Collision)问题,即多个不同的输入产生相同的 MD5 值。
|
||||||
|
|
||||||
|
因此,MD 算法已经不被推荐使用,建议使用更安全的哈希算法比如 SHA-2、Bcrypt。
|
||||||
|
|
||||||
|
Java 提供了对 MD 算法系列的支持,包括 MD2、MD5。
|
||||||
|
|
||||||
|
MD5 代码示例(未加盐):
|
||||||
|
|
||||||
|
```java
|
||||||
|
String originalString = "Java学习 + 面试指南:javaguide.cn";
|
||||||
|
// 创建MD5摘要对象
|
||||||
|
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
|
||||||
|
messageDigest.update(originalString.getBytes(StandardCharsets.UTF_8));
|
||||||
|
// 计算哈希值
|
||||||
|
byte[] result = messageDigest.digest();
|
||||||
|
// 将哈希值转换为十六进制字符串
|
||||||
|
String hexString = new HexBinaryAdapter().marshal(result);
|
||||||
|
System.out.println("Original String: " + originalString);
|
||||||
|
System.out.println("SHA-256 Hash: " + hexString.toLowerCase());
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Original String: Java学习 + 面试指南:javaguide.cn
|
||||||
|
SHA-256 Hash: fb246796f5b1b60d4d0268c817c608fa
|
||||||
|
```
|
||||||
|
|
||||||
|
### SHA
|
||||||
|
|
||||||
|
SHA(Secure Hash Algorithm)系列算法是一组密码哈希函数,用于将任意长度的数据映射为固定长度的哈希值。SHA 系列算法由美国国家安全局(NSA)于 1993 年设计,目前共有 SHA-1、SHA-2、SHA-3 三种版本。
|
||||||
|
|
||||||
|
SHA-1 算法将任意长度的数据映射为 160 位的哈希值。然而,SHA-1 算法存在一些严重的缺陷,比如安全性低,容易受到碰撞攻击和长度扩展攻击。因此,SHA-1 算法已经不再被推荐使用。 SHA-2 家族(如 SHA-256、SHA-384、SHA-512 等)和 SHA-3 系列是 SHA-1 算法的替代方案,它们都提供了更高的安全性和更长的哈希值长度。
|
||||||
|
|
||||||
|
SHA-2 家族是在 SHA-1 算法的基础上改进而来的,它们采用了更复杂的运算过程和更多的轮次,使得攻击者更难以通过预计算或巧合找到碰撞。
|
||||||
|
|
||||||
|
为了寻找一种更安全和更先进的密码哈希函数,美国国家标准与技术研究院(National Institute of Standards and Technology,简称 NIST)在 2007 年公开征集 SHA-3 的候选算法。NIST 一共收到了 64 个算法方案,经过多轮的评估和筛选,最终在 2012 年宣布 Keccak 算法胜出,成为 SHA-3 的标准算法(SHA-3 与 SHA-2 算法没有直接的关系)。 Keccak 算法具有与 MD 和 SHA-1/2 完全不同的设计思路,即海绵结构(Sponge Construction),使得传统攻击方法无法直接应用于 SHA-3 的攻击中(能够抵抗目前已知的所有攻击方式包括碰撞攻击、长度扩展攻击、差分攻击等)。
|
||||||
|
|
||||||
|
由于 SHA-2 算法还没有出现重大的安全漏洞,而且在软件中的效率更高,所以大多数人还是倾向于使用 SHA-2 算法。
|
||||||
|
|
||||||
|
相比 MD5 算法,SHA-2 算法之所以更强,主要有两个原因:
|
||||||
|
|
||||||
|
- 哈希值长度更长:例如 SHA-256 算法的哈希值长度为 256 位,而 MD5 算法的哈希值长度为 128 位,这就提高了攻击者暴力破解或者彩虹表攻击的难度。
|
||||||
|
- 更强的碰撞抗性:SHA 算法采用了更复杂的运算过程和更多的轮次,使得攻击者更难以通过预计算或巧合找到碰撞。目前还没有找到任何两个不同的数据,它们的 SHA-256 哈希值相同。
|
||||||
|
|
||||||
|
当然,SHA-2 也不是绝对安全的,也有被暴力破解或者彩虹表攻击的风险,所以,在实际的应用中,加盐还是必不可少的。
|
||||||
|
|
||||||
|
Java 提供了对 SHA 算法系列的支持,包括 SHA-1、SHA-256、SHA-384 和 SHA-512。
|
||||||
|
|
||||||
|
SHA-256 代码示例(未加盐):
|
||||||
|
|
||||||
|
```java
|
||||||
|
String originalString = "Java学习 + 面试指南:javaguide.cn";
|
||||||
|
// 创建SHA-256摘要对象
|
||||||
|
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
|
||||||
|
messageDigest.update(originalString.getBytes());
|
||||||
|
// 计算哈希值
|
||||||
|
byte[] result = messageDigest.digest();
|
||||||
|
// 将哈希值转换为十六进制字符串
|
||||||
|
String hexString = new HexBinaryAdapter().marshal(result);
|
||||||
|
System.out.println("Original String: " + originalString);
|
||||||
|
System.out.println("SHA-256 Hash: " + hexString.toLowerCase());
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Original String: Java学习 + 面试指南:javaguide.cn
|
||||||
|
SHA-256 Hash: 184eb7e1d7fb002444098c9bde3403c6f6722c93ecfac242c0e35cd9ed3b41cd
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bcrypt
|
||||||
|
|
||||||
|
Bcrypt 算法是一种基于 Blowfish 加密算法的密码哈希函数,专门为密码加密而设计,安全性高。
|
||||||
|
|
||||||
|
由于 Bcrypt 采用了 salt(盐) 和 cost(成本) 两种机制,它可以有效地防止彩虹表攻击和暴力破解攻击,从而保证密码的安全性。salt 是一个随机生成的字符串,用于和密码混合,增加密码的复杂度和唯一性。cost 是一个数值参数,用于控制 Bcrypt 算法的迭代次数,增加密码哈希的计算时间和资源消耗。
|
||||||
|
|
||||||
|
Bcrypt 算法可以根据实际情况进行调整加密的复杂度,可以设置不同的 cost 值和 salt 值,从而满足不同的安全需求,灵活性很高。
|
||||||
|
|
||||||
|
Java 应用程序的安全框架 Spring Security 支持多种密码编码器,其中 `BCryptPasswordEncoder` 是官方推荐的一种,它使用 BCrypt 算法对用户的密码进行加密存储。
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder(){
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 对称加密
|
||||||
|
|
||||||
|
对称加密算法是指加密和解密使用同一个密钥的算法,也叫共享密钥加密算法。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
常见的对称加密算法有 DES、3DES、AES 等。
|
||||||
|
|
||||||
|
### DES 和 3DES
|
||||||
|
|
||||||
|
DES(Data Encryption Standard)使用 64 位的密钥(有效秘钥长度为 56 位,8 位奇偶校验位)和 64 位的明文进行加密。
|
||||||
|
|
||||||
|
虽然 DES 一次只能加密 64 位,但我们只需要把明文划分成 64 位一组的块,就可以实现任意长度明文的加密。如果明文长度不是 64 位的倍数,必须进行填充,常用的模式有 PKCS5Padding, PKCS7Padding, NOPADDING。
|
||||||
|
|
||||||
|
DES 加密算法的基本思想是将 64 位的明文分成两半,然后对每一半进行多轮的变换,最后再合并成 64 位的密文。这些变换包括置换、异或、选择、移位等操作,每一轮都使用了一个子密钥,而这些子密钥都是由同一个 56 位的主密钥生成的。DES 加密算法总共进行了 16 轮变换,最后再进行一次逆置换,得到最终的密文。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这是一个经典的对称加密算法,但也有明显的缺陷,即 56 位的密钥安全性不足,已被证实可以在短时间内破解。
|
||||||
|
|
||||||
|
为了提高 DES 算法的安全性,人们提出了一些变种或者替代方案,例如 3DES(Triple DES)。
|
||||||
|
|
||||||
|
3DES(Triple DES)是 DES 向 AES 过渡的加密算法,它使用 2 个或者 3 个 56 位的密钥对数据进行三次加密。3DES 相当于是对每个数据块应用三次 DES 的对称加密算法。
|
||||||
|
|
||||||
|
为了兼容普通的 DES,3DES 并没有直接使用 加密->加密->加密 的方式,而是采用了加密->解密->加密 的方式。当三种密钥均相同时,前两步相互抵消,相当于仅实现了一次加密,因此可实现对普通 DES 加密算法的兼容。3DES 比 DES 更为安全,但其处理速度不高。
|
||||||
|
|
||||||
|
### AES
|
||||||
|
|
||||||
|
AES(Advanced Encryption Standard)算法是一种更先进的对称密钥加密算法,它使用 128 位、192 位或 256 位的密钥对数据进行加密或解密,密钥越长,安全性越高。
|
||||||
|
|
||||||
|
AES 也是一种分组(或者叫块)密码,分组长度只能是 128 位,也就是说,每个分组为 16 个字节。AES 加密算法有多种工作模式(mode of operation),如:ECB、CBC、OFB、CFB、CTR、XTS、OCB、GCM(目前使用最广泛的模式)。不同的模式参数和加密流程不同,但是核心仍然是 AES 算法。
|
||||||
|
|
||||||
|
和 DES 类似,对于不是 128 位倍数的明文需要进行填充,常用的填充模式有 PKCS5Padding, PKCS7Padding, NOPADDING。不过,AES-GCM 是流加密算法,所以对应的填充模式为 NoPadding,即无需填充。
|
||||||
|
|
||||||
|
AES 的速度比 3DES 快,而且更安全。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
基于 Java 实现 AES 算法代码示例:
|
||||||
|
|
||||||
|
```java
|
||||||
|
private static final String AES_ALGORITHM = "AES";
|
||||||
|
// AES密钥
|
||||||
|
private static final String AES_SECRET_KEY = "4128D9CDAC7E2F82951CBAF7FDFE675B";
|
||||||
|
// AES加密模式为GCM,填充方式为NoPadding
|
||||||
|
// AES-GCM 是流加密(Stream cipher)算法,所以对应的填充模式为 NoPadding,即无需填充。
|
||||||
|
private static final String AES_TRANSFORMATION = "AES/GCM/NoPadding";
|
||||||
|
// 加密器
|
||||||
|
private static Cipher encryptionCipher;
|
||||||
|
// 解密器
|
||||||
|
private static Cipher decryptionCipher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 完成一些初始化工作
|
||||||
|
*/
|
||||||
|
public static void init() throws Exception {
|
||||||
|
// 将AES密钥转换为SecretKeySpec对象
|
||||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(AES_SECRET_KEY.getBytes(), AES_ALGORITHM);
|
||||||
|
// 使用指定的AES加密模式和填充方式获取对应的加密器并初始化
|
||||||
|
encryptionCipher = Cipher.getInstance(AES_TRANSFORMATION);
|
||||||
|
encryptionCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
|
||||||
|
// 使用指定的AES加密模式和填充方式获取对应的解密器并初始化
|
||||||
|
decryptionCipher = Cipher.getInstance(AES_TRANSFORMATION);
|
||||||
|
decryptionCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new GCMParameterSpec(128, encryptionCipher.getIV()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
*/
|
||||||
|
public static String encrypt(String data) throws Exception {
|
||||||
|
byte[] dataInBytes = data.getBytes();
|
||||||
|
// 加密数据
|
||||||
|
byte[] encryptedBytes = encryptionCipher.doFinal(dataInBytes);
|
||||||
|
return Base64.getEncoder().encodeToString(encryptedBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密
|
||||||
|
*/
|
||||||
|
public static String decrypt(String encryptedData) throws Exception {
|
||||||
|
byte[] dataInBytes = Base64.getDecoder().decode(encryptedData);
|
||||||
|
// 解密数据
|
||||||
|
byte[] decryptedBytes = decryptionCipher.doFinal(dataInBytes);
|
||||||
|
return new String(decryptedBytes, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
String originalString = "Java学习 + 面试指南:javaguide.cn";
|
||||||
|
init();
|
||||||
|
String encryptedData = encrypt(originalString);
|
||||||
|
String decryptedData = decrypt(encryptedData);
|
||||||
|
System.out.println("Original String: " + originalString);
|
||||||
|
System.out.println("AES Encrypted Data : " + encryptedData);
|
||||||
|
System.out.println("AES Decrypted Data : " + decryptedData);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Original String: Java学习 + 面试指南:javaguide.cn
|
||||||
|
AES Encrypted Data : E1qTkK91suBqToag7WCyoFP9uK5hR1nSfM6p+oBlYj71bFiIVnk5TsQRT+zpjv8stha7oyKi3jQ=
|
||||||
|
AES Decrypted Data : Java学习 + 面试指南:javaguide.cn
|
||||||
|
```
|
||||||
|
|
||||||
|
## 非对称加密
|
||||||
|
|
||||||
|
非对称加密算法是指加密和解密使用不同的密钥的算法,也叫公开密钥加密算法。这两个密钥互不相同,一个称为公钥,另一个称为私钥。公钥可以公开给任何人使用,私钥则要保密。
|
||||||
|
|
||||||
|
如果用公钥加密数据,只能用对应的私钥解密(加密);如果用私钥加密数据,只能用对应的公钥解密(签名)。这样就可以实现数据的安全传输和身份认证。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
常见的非对称加密算法有 RSA、DSA、ECC 等。
|
||||||
|
|
||||||
|
### RSA
|
||||||
|
|
||||||
|
RSA(Rivest–Shamir–Adleman algorithm)算法是一种基于大数分解的困难性的非对称加密算法,它需要选择两个大素数作为私钥的一部分,然后计算出它们的乘积作为公钥的一部分(寻求两个大素数比较简单,而将它们的乘积进行因式分解却极其困难)。RSA 算法原理的详细介绍,可以参考这篇文章:[你真的了解 RSA 加密算法吗? - 小傅哥](https://www.cnblogs.com/xiaofuge/p/16954187.html)。
|
||||||
|
|
||||||
|
RSA 算法的安全性依赖于大数分解的难度,目前已经有 512 位和 768 位的 RSA 公钥被成功分解,因此建议使用 2048 位或以上的密钥长度。
|
||||||
|
|
||||||
|
RSA 算法的优点是简单易用,可以用于数据加密和数字签名;缺点是运算速度慢,不适合大量数据的加密。
|
||||||
|
|
||||||
|
RSA 算法是是目前应用最广泛的非对称加密算法,像 SSL/TLS、SSH 等协议中就用到了 RSA 算法。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
基于 Java 实现 RSA 算法代码示例:
|
||||||
|
|
||||||
|
```java
|
||||||
|
private static final String RSA_ALGORITHM = "RSA";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成RSA密钥对
|
||||||
|
*/
|
||||||
|
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
|
||||||
|
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
|
||||||
|
// 密钥大小为2048位
|
||||||
|
keyPairGenerator.initialize(2048);
|
||||||
|
return keyPairGenerator.generateKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用公钥加密数据
|
||||||
|
*/
|
||||||
|
public static String encrypt(String data, PublicKey publicKey) throws Exception {
|
||||||
|
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||||
|
byte[] encryptedData = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return Base64.getEncoder().encodeToString(encryptedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用私钥解密数据
|
||||||
|
*/
|
||||||
|
public static String decrypt(String encryptedData, PrivateKey privateKey) throws Exception {
|
||||||
|
byte[] decodedData = Base64.getDecoder().decode(encryptedData);
|
||||||
|
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||||
|
byte[] decryptedData = cipher.doFinal(decodedData);
|
||||||
|
return new String(decryptedData, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
KeyPair keyPair = generateKeyPair();
|
||||||
|
PublicKey publicKey = keyPair.getPublic();
|
||||||
|
PrivateKey privateKey = keyPair.getPrivate();
|
||||||
|
String originalString = "Java学习 + 面试指南:javaguide.cn";
|
||||||
|
String encryptedData = encrypt(originalString, publicKey);
|
||||||
|
String decryptedData = decrypt(encryptedData, privateKey);
|
||||||
|
System.out.println("Original String: " + originalString);
|
||||||
|
System.out.println("RSA Encrypted Data : " + encryptedData);
|
||||||
|
System.out.println("RSA Decrypted Data : " + decryptedData);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Original String: Java学习 + 面试指南:javaguide.cn
|
||||||
|
RSA Encrypted Data : T9ey/CEPUAhZm4UJjuVNIg8RPd1fQ32S9w6+rvOKxmuMumkJY2daFfWuCn8A73Mk5bL6TigOJI0GHfKOt/W2x968qLM3pBGCcPX17n4pR43f32IIIz9iPdgF/INOqDxP5ZAtCDvTiuzcSgDHXqiBSK5TDjtj7xoGjfudYAXICa8pWitnqDgJYoo2J0F8mKzxoi8D8eLE455MEx8ZT1s7FUD/z7/H8CfShLRbO9zq/zFI06TXn123ufg+F4lDaq/5jaIxGVEUB/NFeX4N6OZCFHtAV32mw71BYUadzI9TgvkkUr1rSKmQ0icNhnRdKedJokGUh8g9QQ768KERu92Ibg==
|
||||||
|
RSA Decrypted Data : Java学习 + 面试指南:javaguide.cn
|
||||||
|
```
|
||||||
|
|
||||||
|
### DSA
|
||||||
|
|
||||||
|
DSA(Digital Signature Algorithm)算法是一种基于离散对数的困难性的非对称加密算法,它需要选择一个素数 q 和一个 q 的倍数 p 作为私钥的一部分,然后计算出一个模 p 的原根 g 和一个模 q 的整数 y 作为公钥的一部分。DSA 算法的安全性依赖于离散对数的难度,目前已经有 1024 位的 DSA 公钥被成功破解,因此建议使用 2048 位或以上的密钥长度。
|
||||||
|
|
||||||
|
DSA 算法的优点是数字签名速度快,适合生成数字证书;缺点是不能用于数据加密,且签名过程需要随机数。
|
||||||
|
|
||||||
|
DSA 算法签名过程:
|
||||||
|
|
||||||
|
1. 使用消息摘要算法对要发送的数据进行加密,生成一个信息摘要,也就是一个短的、唯一的、不可逆的数据表示。
|
||||||
|
2. 发送方用自己的 DSA 私钥对信息摘要再进行加密,形成一个数字签名,也就是一个可以证明数据来源和完整性的数据附加。
|
||||||
|
3. 将原始数据和数字签名一起通过互联网传送给接收方。
|
||||||
|
4. 接收方用发送方的公钥对数字签名进行解密,得到信息摘要。同时,接收方也用消息摘要算法对收到的原始数据进行加密,得到另一个信息摘要。接收方将两个信息摘要进行比较,如果两者一致,则说明在传送过程中数据没有被篡改或损坏;否则,则说明数据已经失去了安全性和保密性。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
这篇文章介绍了三种加密算法:哈希算法、对称加密算法和非对称加密算法。哈希算法是一种用数学方法对数据生成一个固定长度的唯一标识的技术,可以用来验证数据的完整性和一致性,常见的哈希算法有 MD、SHA、MAC 等。对称加密算法是一种加密和解密使用同一个密钥的算法,可以用来保护数据的安全性和保密性,常见的对称加密算法有 DES、3DES、AES 等。非对称加密算法是一种加密和解密使用不同的密钥的算法,可以用来实现数据的安全传输和身份认证,常见的非对称加密算法有 RSA、DSA、ECC 等。
|
||||||
|
|
||||||
|
## 参考
|
||||||
|
|
||||||
|
- 奇妙的安全旅行之 DSA 算法:<https://zhuanlan.zhihu.com/p/347025157>
|
||||||
|
- AES-GCM 加密简介:<https://juejin.cn/post/6844904122676690951>
|
@ -4,6 +4,12 @@ category: 知识星球
|
|||||||
star: 5
|
star: 5
|
||||||
---
|
---
|
||||||
|
|
||||||
|
我花费了两年多的时间,写了一本针对 Java 面试的《Java面试指北》。这份资料的内容质量还是非常高的,帮助了上万名同学高效准备 Java 面试。
|
||||||
|
|
||||||
|
目前的成绩:累计阅读 **162w+** ,点赞 **2300+** ,评论 **700+** (几乎每一条提问类型的评论我看到后都会用心回复)。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## 介绍
|
## 介绍
|
||||||
|
|
||||||
**《Java 面试指北》** 是我的[知识星球](../about-the-author/zhishixingqiu-two-years.md)的一个内部小册,和 [JavaGuide 开源版](https://javaguide.cn/)的内容互补。相比于开源版本来说,《Java 面试指北》添加了下面这些内容(不仅仅是这些内容):
|
**《Java 面试指北》** 是我的[知识星球](../about-the-author/zhishixingqiu-two-years.md)的一个内部小册,和 [JavaGuide 开源版](https://javaguide.cn/)的内容互补。相比于开源版本来说,《Java 面试指北》添加了下面这些内容(不仅仅是这些内容):
|
||||||
@ -44,7 +50,7 @@ star: 5
|
|||||||
|
|
||||||
如果你是非科班的同学,也能在这些文章中找到对应的非科班的同学写的面经。
|
如果你是非科班的同学,也能在这些文章中找到对应的非科班的同学写的面经。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
并且,[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)还有专门分享面经和面试题的专题,里面会分享很多优质的面经和面试题。
|
并且,[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)还有专门分享面经和面试题的专题,里面会分享很多优质的面经和面试题。
|
||||||
|
|
||||||
@ -72,6 +78,10 @@ star: 5
|
|||||||
|
|
||||||
每一篇内容都非常干货,不少球友看了之后表示收获满满。不过,最重要的还是知行合一。
|
每一篇内容都非常干货,不少球友看了之后表示收获满满。不过,最重要的还是知行合一。
|
||||||
|
|
||||||
|
### 工作篇
|
||||||
|
|
||||||
|
**「工作篇」** 这个系列主要内容是分享一些有助于个人以及职场发展的内容。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
<!-- @include: @planet2.snippet.md -->
|
<!-- @include: @planet2.snippet.md -->
|
||||||
|
@ -17,7 +17,7 @@ category: 知识星球
|
|||||||
|
|
||||||
## 更多专栏
|
## 更多专栏
|
||||||
|
|
||||||
除了上面介绍的之外,我的[知识星球](../about-the-author/zhishixingqiu-two-years.md)还有 《Kafka 常见面试题/知识点总结》、《程序员副业赚钱之路》等多个专栏。
|
除了上面介绍的之外,我的[知识星球](../about-the-author/zhishixingqiu-two-years.md)还有 《Kafka 常见面试题/知识点总结》、《程序员副业赚钱之路》等多个专栏。进入星球之后,统统都可以免费阅读。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user