NOTE

1.4 加密

对称加密、分组模式、非对称加密、RSA 与基础实现。

Security更新于 约 3 分钟读完historical

这是历史学习笔记,可能存在过时或不完整的理解。

1. 加密是什么

2. 加密特性

机密性

3. 加密三要素

3.1. 加密

  • 明文
  • 密钥
  • 加密算法

3.2. 解密

  • 密文
  • 密钥
  • 解密算法:可能跟加密算法不同

4. 加密算法分类

4.1. 对称加密

4.1.1. 是什么

  • 通信双方共享同一个密钥
  • 优点:加解密效率高
  • 缺点:需要安全地分发和保管共享密钥

4.1.2. 凯撒密码

4.1.3. DES

不推荐使用,DES 已不适合现代安全场景。

  • 加密
  • 解密
  • 密钥 长度为8bytes
  • 分组 8bytes

4.1.4. 3DES

Triple DES。新系统也不应再优先选择 3DES。

  • 加密 中间使用解密的原因是为了兼容以前的DES

  • 解密

  • 密钥 长度为8bytes,总共3个密钥,所以总长度为24bytes 密钥1和密钥2相同,或者密钥2和密钥3相同,就是DES

  • 分组 8bytes

4.1.5. AES

现代系统优先使用 AES,并应配合合适的认证加密模式(如 GCM)或额外的完整性保护。

  • 密钥 长度可选,16、24、32
  • 分组 16bytes

4.2. 分组模式

DES、3DES、AES都属于分组密码,即每次只能处理特定长度的一块(block)数据的一类加解密 如果要加密的明文比较长,就需要对加密进行迭代

4.2.1. 分组与对称加密的关系

4.2.2. ECB

  • 需要分组,分组长度根据算法而定
  • 对数据分组之后需要填充
  • 加密效率高,但是相同明文块会产生相同密文块,会泄露数据模式,因此不应直接用于一般数据加密
  • 可以并行加解密

4.2.3. CBC

  • 需要分组,分组长度根据算法而定
  • 对数据分组之后需要填充
  • 需要提供初始化向量
  • 每一个密文都是下一个加密操作的输入
  • 不能并行加密,可以并行解密

4.2.4. CFB

  • 需要分组,分组长度根据算法而定
  • 没有直接对明文分组加密,故不需要填充
  • 需要提供初始化向量
  • 相对初始化向量加密,然后再与明文异或
  • 支持并行解密,不支持并行加密

4.2.5. OFB

  • 需要分组,分组长度根据算法而定
  • 没有直接对明文分组加密,故不需要填充
  • 是对初始化向量的结果不断进行加密,作为下一次加密的数据来源

4.2.6. CTR

  • 需要分组,分组长度根据算法而定
  • 没有直接对明文分组加密,故不需要填充
  • 可以并行加解密

4.3. 非对称加密

4.3.1. 是什么

  • 密钥有两个:公钥可以公开,私钥必须由持有者安全保管
    • 签名和验签:私钥签名,公钥验签,用于验证完整性和签名者身份
    • 加密和解密:公钥加密,私钥解密。目的是防止信息被第三方拦截和偷听
  • 缺点:加密解密效率很低
  • 优点:公开公钥不需要传输私钥

4.3.2. RSA算法

4.3.3. 数学原理

  • 假设由两个很大的质数:p和q
  • 记它们的乘积为:N=p * q 这里p * q计算很快,但是由N反推回p和q代价非常大,目前没有行之有效的公式
  • 计算出比N小且与N互质的自然数的个数:φ(n)=(p-1) * (q-1)。这个公式由集合论证明
  • 找出比φ(n)小且与之互质的自然数,记为e
  • 有了e和φ(n)后,根据辗转相除法的原理,可以找到x和y,即e * x - φ(n) * y=1
  • 把φ(n)=(p-1) * (q-1)代入,移动一下位置就有了e * x = 1 + (p - 1)* (q - 1) * y
  • 最后我们有了N,e,x, 公钥就是N和e,私钥就是x

4.3.4. 工作过程

  • 加密要用公钥(N,e)
    • 假设明文是A,那么根据A的e次方=R(mod N),公式的意思A的e次方 / N得到的余数是R,计算出的R就是密文
  • 解密要用私钥x
    • 假设密文是R,那么根据R的x次方 = A (mod N),公式的意思R的x次方 / N得到的余数是A,计算出的A就是明文
4.3.4.1. 欧拉函数

上面加密解密的过程的原理是欧拉函数:

  • A的e次方=R(mod N)R的x次方 = A (mod N),可以看出A的e次方R的x次方同余,换句话说A的e次方 / R 余数是N,R的x次方 / A余数是N,这里代入公式没搞懂
  • 且由于e * x - φ(n) * y=1,即A的e*x次方 = A的(1+φ(n) * y)次方 = A * A的(φ(n) * y)次方,这里φ(n) * y = 1的原理就是欧拉函数

5. 实现

5.1. OpenSSL

openssl

# 生成私钥
> genrsa -out rsa_private_key.pem

# 生成公钥
> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

5.2. Golang实现

5.2.1. AES-CTR

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "fmt"
    "io"
)

func cryptCTR(key, iv, input []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    output := make([]byte, len(input))
    cipher.NewCTR(block, iv).XORKeyStream(output, input)
    return output, nil
}

func main() {
    key := make([]byte, 32)
    if _, err := io.ReadFull(rand.Reader, key); err != nil {
        panic(err)
    }
    iv := make([]byte, aes.BlockSize)
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        panic(err)
    }

    plaintext := []byte("hello")
    ciphertext, _ := cryptCTR(key, iv, plaintext)
    recovered, _ := cryptCTR(key, iv, ciphertext)
    fmt.Println(string(recovered))
}

6. 参考

正在加载有帮助数量