type
status
date
slug
summary
tags
category
password
icon

加密-Encryption & 解密-Decryption

现代密码学

不止可以用于文字内容,还可以用于各种二进制数据。
  • 对称加密
    • 原理:使用密钥和加密算法对数据进行转换,得到的无意义数据即为密文;使用密钥和解密算法对密文进行逆向转换,得到原数据。
    • 图1.对称加密示意图
      图1.对称加密示意图
    • 经典算法:
      • DES(56 位密钥,密钥太短⽽逐渐被弃⽤)
      • AES(128 位、192 位、256 位密钥,现在最流⾏)
破解思路 1. 拿到⼀组或多组原⽂-密⽂对 2. 设法找到⼀个密钥,这个密钥可以将这些原⽂-密⽂对中的原⽂加密为密⽂,以及将密⽂解密为原⽂的组合,即为成功破解 反破解 ⼀种优秀的对称加密算法的标准是,让破解者找不到⽐穷举法(暴⼒破解法)更有效的破解⼿段,并且穷举法的破解时间⾜够⻓(例如数千年)。
💡
问题 1 思考一下: 加密方解密方,其中一方生成了密钥后,是不是需要通过一种方式,将密钥发送给对方,如果在发送过程中,密钥被入侵者截获了,那么双方的通信就没有安全可言了。 那么如何解决这个问题呢?
  • 非对称加密
    • 原理:使用公钥(加密密钥)对数据进行加密得到密文;使用私钥(解密密钥)对数据进行解密得到原数据。
      • 图2.非对称加密示意图
        图2.非对称加密示意图
        公钥是私钥通过特定算法生成的。这个方法不可逆,也就是说,拿到公钥了,不能方向计算私钥。
    • 经典算法:
      • RSA (可以用来加密和签名)
      • DSA (只可以用来签名,速度快)
    • 优缺点
      • 优点:可以在不安全⽹络上传输密钥
      • 缺点:计算复杂,因此性能相⽐对称加密差很多
      使用非堆成加密,只需要互相拥有对方的公钥,每次发送信息,通过对方的公钥对信息进行加密,发送给对方,对方通过自己的私钥进行解密就可以了。
      图3.非对称加密通信
      图3.非对称加密通信
      💡
      问题 2 思考一下: 存在这么一种情况,双方都采用非对称加密的方式通信,但是双发的公钥在发送途中都被入侵者截获了,虽然入侵者 C 无法读懂 A 和 B 之间的消息,但是入侵者C 可以通过公钥伪造A和B的身份和信息,发送给对方。该如何解决呢? 是不是需要一个能够确认消息身份的方式呢? 我们先来看看非对称加密的一个延伸用法。
      破解思路 1. 和对称加密不同之处在于,⾮对称加密的公钥很容易获得,因此制造原⽂-密⽂对是没有困难的事 2. 所以,⾮对称加密的关键只在于,如何找到⼀个正确的私钥,可以解密所有经过公钥加密过的密⽂。找到这样的私钥即为成功破解 3. 由于⾮对称加密的⾃身特性,怎样通过公钥来推断出私钥通常是⼀种思路(例如 RSA),但往往最佳⼿段依然是穷举法,只是和对称加密破解的区别在于,对称加密破解是不断尝试⾃⼰的新密钥是否可以将⾃⼰拿到的原⽂-密⽂对进⾏加密和解密,⽽⾮对称加密时不断尝试⾃⼰的新私钥是否和公钥互相可解。 反破解 和对称加密⼀样,⾮对称加密算法优秀的标准同样在于,让破解者找不到⽐穷举法更有效的破解⼿段,并且穷举法的破解时间⾜够⻓。
       

数字签名-Digital Signature

如果我们仔细观察图 2 ,可以思考一下:
图4.非对称加密变换
图4.非对称加密变换
如果B是想要发送的原数据,B通过私钥生成了A 加密数据,A 可以通过公钥再次生成 B。如果把图转换一下就是下面这样:
图5.非对称加密演算数字签名
图5.非对称加密演算数字签名
从上面的演算可以看出,于公钥和私钥是相互可解的,然而公钥大部分情况是暴露出去的,因此这里就不能被称为是加密了,不能用做加密,那能干什么呢?
设想这么一种情况,你想发布一个新应用,文件是 ABC.apk,大家都可以在网络上下载你的 apk,但是有没有可能,入侵者或者其他人也有同名的文件,而大家只想下载你的 ABC.apk,该如何确认是你的 ABC.apk 呢?
通过上面的方式,我们可以这么做,用自己的私钥,对 ABC.apk 进行加密(签名),然后发布加密后的 apk,并附带上公钥。大家只有通过你的公钥才能正确转换获得 ABC.apk。这样是不是能确保 ABC.apk 是由你发布的呢。
图6.简化数字签名
图6.简化数字签名
这里就通过非对称加密,扩展出一个新的用法,数字签名。
💡
问题 3 图 5 中还存在一些问题,由于接收方并不知道原数据是什么,通过不正确的公钥转换后也能得到数据,接收方并不知道这个数据正不正确,所以还需要有一种方式验证的公钥转换后的数据正确与否? 大部分情况下我们可以带上原数据一起发送给对方,这样对方验证后,可以进行比较,判断验证是否通过
图7.数字签名验证
图7.数字签名验证
了解了数字签名后,我们回到问题 2,非对称加密不仅可以加密,而且可以验证消息身份,那么我们是不是可以构建一个比较安全的沟通方式呢,
图8.加密+签名通信
图8.加密+签名通信
图 8 中,发送方使用接收方的公钥对消息进行加密,并通过发送方的私钥进行签名,将加密数据和签名数据一起发送给接收方接收方通过接受方的私钥对加密数据进行解密,通过发送方的公钥对签名数据进行验证,即可确认消息来源和消息内容,并保证安全。当然加密算法和签名算法可以是两种不同的算法。
💡
问题 4 仔细看图 8 其实还是存在问题,我们的签名数据是通过私钥将原数据加密过来的,入侵者很容易获取到公钥,通过签名数据就将原数据解密出来,那么如何解决这个问题呢? 我们是否需要一种不通过原数据就能生成签名数据,并能够验证数据的正确性的东西呢?

密码学密钥和登录密码 密钥(key):
  • 场景:⽤于加密和解密
  • ⽬的:保证数据被盗时不会被⼈读懂内容
  • 焦点:数据
密码(password):
  • 场景:⽤户进⼊⽹站或游戏前的身份验证
  • ⽬的:数据提供⽅或应⽤服务⽅对账户拥有者数据的保护,保证「你是你」的时候才提供权限
  • 焦点:身份

 

编码-Encoding & 解码-Decoding

Base64:

将⼆进制数据转换成由 64 个字符组成的字符串的编码算法
💡
什么是⼆进制数据?
  • ⼴义:所有计算机数据都是⼆进制数据
  • 狭义:⾮⽂本数据即⼆进制数据

算法:

将原数据每 6 位对应成 Base 64 索引表中的⼀个字符编排成⼀个字符串(每个字符 8 位)

Base64 索引表:

索引
对应字符
索引
对应字符
索引
对应字符
索引
对应字符
0
A
17
R
34
i
51
z
1
B
18
S
35
j
52
0
2
C
19
T
36
k
53
1
3
D
20
U
37
l
54
2
4
E
21
V
38
m
55
3
5
F
22
W
39
n
56
4
6
G
23
X
40
o
57
5
7
H
24
Y
41
p
58
6
8
I
25
Z
42
q
59
7
9
J
26
a
43
r
60
8
10
K
27
b
44
s
61
9
11
L
28
c
45
t
62
+
12
M
29
d
46
u
63
/
13
N
30
e
47
v
14
O
31
f
48
w
15
P
32
g
49
x
16
Q
33
h
50
y
padding
=
编码示例:把「Man」进⾏ Base64 编码
图9.base64编码案例
图9.base64编码案例
编码示例:Base64 的末尾补⾜
图10.base64编码补足案例
图10.base64编码补足案例

Base64 的用途

  1. 将⼆进制数据扩充了储存和传输途径(例如可以把数据保存到⽂本⽂件、可以通过聊天对话框或短 信形式发送⼆进制数据、可以在 URL 中加⼊简单的⼆进制数据)
  1. 普通的字符串在经过 Base64 编码后的结果会变得⾁眼不可读,因此可以适⽤于⼀定条件下的防偷 窥(较少⽤)

Base64 的缺点

因为⾃身的原理(6 位变 8 位),因此每次 Base64 编码之后,数据都会增⼤约 1/3,所以会影响存储 和传输性能。
💡
「Base64 加密图⽚传输更安全和⾼效」??? 不。⾸先,Base64 并不是加密;另外,Base64 会导致数据增⼤ 1/3,降低⽹络性能,增⼤⽤户流量开销,是画蛇添⾜的⼿段。(最好不要拿来 diss 你们公司的后端哟,友善) Base64 对图⽚进⾏编码的⽤于在于,有时需要使⽤⽂本形式来传输图⽚。除此之外,完全没必要使⽤ Base64 对图⽚进⾏额外处理。

变种 Base58

⽐特币使⽤的编码⽅式,去掉了 Base64 中的数字 "0",字⺟⼤写 "O",字⺟⼤写 "I",和字⺟⼩写 "l", 以及 "+" 和 "/" 符号,⽤于⽐特币地址的表示。 Base58 对于 Base64 的改动,主要⽬的在于⽤户的便捷性。由于去掉了难以区分的字符,使得 Base58 对于「⼈⼯抄写」更加⽅便。另外,去掉了 "+" "/" 号后也让⼤多数的软件可以⽅便双击选取。

URL 使⽤的百分号编码

在 URL 的字符串中,对⼀些不⽤于特殊⽤途的保留字符,使⽤百分号 "%" 为前缀进⾏单独编码,以避 免出现解析错误。
目的:消除歧义,避免解析错误
例如,要在 http://hencoder.com/users 后⾯添加查询字符串,查询 name 为「隐秘&伟⼤」的⽤户,如果直接写成 http://hencoder.com/user/?name=隐秘&伟⼤ ,"&" 符号就会被解析为分隔符号,因此需要对它进⾏转码,转码后的 URL 为 http://hencoder.com/user/?name=隐秘%26伟⼤ 。 这种编码仅⽤于 URL,⽬的是避免解析错误的出现。

压缩-Compression & 解压-Decompression

含义

  • 压缩:把数据换一种方式来存储,以减小存储空间。将数据使⽤更具有存储优势的编码算法进⾏编码
  • 解压缩:将压缩数据解码还原成原来的形式,以⽅便使⽤。
  • 常见的压缩算法:DEFLATE、JPEG、MP3
💡
ZIP是一种归档方法,它使用的压缩算法也是DEFLATE

⽬的

减⼩数据占⽤的存储空间。
💡
粗暴算法举例 将下⾯⽂本内容压缩:
使⽤某种算法压缩后的数据为:
注:具体的压缩场景有很多,因此压缩算法也会复杂得多,上⾯只是⼀个原型算法。
💡
压缩属于编码吗?
是。所谓编码,即把数据从⼀种形式转换为另⼀种形式。压缩过程属于编码过程,解压缩过程属于解码过程。

媒体数据的编码

含义:将图像、音频,视频数据通过编码来转换成存档形式(编码),以及从存档形式转换回来(解码)。
目的:存储和压缩媒体数据(大多数媒体编码算法会压缩数据,但不是全部)。
有损压缩:媒体的有损压缩,是保证人类感官体验的前提下,舍弃部分数据,达到减小存储的目的。严格来说有损压缩不算编码,因为压缩后无法恢复为原数据(不可逆),因为原数据已经部分缺失。
无损压缩:不损失感官上的体验,只是换一种存储方式,来减少存储,可以完整的恢复原数据,算编码。

序列化-Serialization & 反序列化-Deserialization

序列化:把数据对象(⼀般是内存中的,例如 JVM 中的对象)转换成字节序列的过程。
反序列化:把自己饿序列重新转换成内存中的对象。
对象在程序内存⾥的存放形式是散乱的(存放在不同的内存区域、并且由引⽤进⾏连接),通过序列化可以把内存中的对象转换成⼀个字节序列,从⽽使⽤ byte[] 等形式进⾏本地存储或⽹络传输,在需要的时候重新组装(反序列化)来使⽤。
目的:让内存中的对象可以被储存和传输。
💡
序列化是编码吗? 不是
序列化和编码的区别?
编码是把数据由⼀种数据格式转换成另⼀种数据格式;⽽序列化是把数据由内存中的对象(⽽不是某种具体的格式)转换成字节序列。

哈希-Hash

定义:把任意数据转换成指定大小范围(通常很小,例如 256 字节以内)的数据。
作用:相当于从数据中提出摘要信息,因此最主要⽤途是数字指纹,
Hash 是不可逆的。
常见算法:MD5,SHA1,SHA256 等

Hash的实际用途:

  • 唯一性验证
    • 💡
      例如 java 中的 hashCode() 方法
      怎么重写 hashCode() 方法?
      把 equals() 方法中的每个用于判断相等的变量都放进 hashCode() 中,一起生成一个尽量不会碰撞的整数即可
      为什么每次重写 equals() ⽅法都需要?
      因为你要把新的判断条件放进 hashCode() 啊。
  • 数据完整性验证
    • 从⽹络上下载⽂件后,通过⽐对⽂件的 Hash 值(例如 MD5、SHA1),可以确认下载的⽂件是否有损坏。如果下载的⽂件 Hash 值和⽂件提供⽅给出的 Hash 值⼀致,则证明下载的⽂件是完好⽆损的。
  • 快速查找
    • HashMap
  • 隐私保护
    • 当重要数据必须暴露的时候,有事可以选择暴露它的 Hash 值(例如 MD5),以保障原数据的安全。
      例如⽹站登录时,可以只保存⽤户密码的 Hash 值,在每次登录验证时只需要将输⼊的密码的 Hash 值和数据库中保存的 Hash 值作⽐对就好,⽹站⽆需知道⽤户的密码。这样,当⽹站数据失窃时,⽤户不会因为⾃⼰的密码被盗导致其他⽹站的安全也受到威胁。 注意:这不属于加密。
Hash 是编码吗?
不是。 Hash 是单向过程,往往是不可逆的,⽆法进⾏逆向恢复操作,因此 Hash 不属于编码
Hash 是加密吗?
不是。Hash 是单向过程,⽆法进⾏逆向回复操作,因此 Hash 不属于加密。(记住,MD5 不是加密!)
💡
现在存用户的密码都采用 Hash 的方式存储,即使被入侵者“脱库”,入侵者也无法知道你的密码。但是如果密码很简单,入侵者可以通过“彩虹表”(明文和 Hash 计算后的字符串组成的键值对)去查 Hash 密码的明文。对付彩虹表的方式是,给明文的密码加“盐”后再计算 Hash 值后保存。
现在我们回到问题 4,就可以使用 Hash 解决,完整的签名与验证
图11.完整的签名与验证。
图11.完整的签名与验证。
图12.完整的加密解密验证流程。
图12.完整的加密解密验证流程。

字符集-Charset

含义:一个由整数向现实世界中的文字符号的 Map(映射)
分⽀:
  • ASCII:128 个字符,1 字节
  • ISO-8859-1:对 ASCII 进⾏扩充,1 字节
  • Unicode:13 万个字符,多字节
    • UTF-8:Unicode 的编码分⽀
    • UTF-16 :Unicode 的编码分⽀
  • GBK / GB2312 / GB18030:中国⾃研标准,多字节,字符集 + 编码
TCP/IPHTTP
Loading...
shuouyang
shuouyang
android开发 ReactNative开发 小程序开发
最新发布
AOSP 环境搭建
2025-3-29
View 绘制流程-源码解析
2025-3-12
HTTP
2025-3-4
JVM 虚拟机
2025-2-28
蓝牙-BLE-基础
2025-2-28
从 OkHttp 的原理来看 HTTP
2025-2-19
公告
🎉热点信息🎉
--- 1 ---
Jet Brains 推出新的跨平台支持 Kotlin MultiPlatform
--- 2 ---
新的小巧便捷的依赖注入框架 Koin
--- 3 ---
新一代 API 查询语言 GraphQL