How does Kyber Encryption Work
Table of Contents
1. 简介
Kyber 是一种后量子(Post-Quantum Cryptography)公钥加密算法,能够抵抗量子计算机的攻击,本文将介绍它。
2. Baby Kyber
下面我们将介绍 Baby Kyber,它和常规 Kyber 相比,安全参数更小,只保留了最核心的过程,比如省略了对密文的压缩等。这样使得 Baby Kyber 的可读性更好,方便理解。
与其他公钥系统一样,Kyber 也需要一个模数
对于 Kyber,我们必须处理多项式。由于我们将多项式相乘和相加,我们将对多项式进行模多项式运算,否则他们的次数会变得太大而我们无法处理。我们将使用的多项式模数是
下面的所有计算都隐含着 1. 对多项式的系数进行模数
注:如果您不了解多项式模多项式的运算,可以参考 Cryptography and Network Security - Principles and Practice, 8th edition, 5.5 Polynomial Arithmetic
2.1. Key Generation
Kyber 的私钥
对于 Baby Kyber 来说,假设私钥
Kyber 的公钥由两部分组成:随机矩阵多项式
Kyber 公钥中另一部分
从而,我们可以计算出公钥
2.1.1. 依赖的数学难题(Module-LWE)
前面介绍了 Kyber 私钥
已知
2.2. 加密
对于非对称加密系统来说,使用公钥对消息进行加密,使用私钥对消息进行解密。
Kyber 加密时,会使用 2 个一次一用的系数比较小的随机矩阵
在加密消息前,我们需要先把消息编码为某个多项式。 我们可以使用消息的二进制表达作为多项式的系数。比如我们想加密数字
在加密前,还需要把
也就是说待加密的数字
使用公钥
代入各个值,我们可以计算出数字
2.3. 解密
使用私钥
第一步,使用下面公式计算出带有噪声的解密结果(noisy result)
第二步,检查
- 系数
更接近于 ,所以改为 - 系数
更接近于 (或者 ),所以改为 - 系数
更接近于 ,所以改为 - 系数
更接近于 ,所以改为
所以,得到解密多项式
第三步,把多项式的缩小
所以,我们得到二进制数据
3. Kyber 总结
Kyber 加解密的总结如图 1 所示(改编自 https://youtu.be/gp7KFOs7y3g?t=3818 中截图)。
Figure 1: Kyber 总结
需要注意的是,图 1 中采用的定义是
4. Kyber 和 ElGamal 的相似之处
从形式上看,Kyber 和 ElGamal 有相似之处,它们的密文都由两部分构成,而且每部分的产生过程也比较类似,如表 1 所示。从形式上说,可以认为 Kyber 是一种 noisy ElGamal 算法。
ElGamal 加密 | Kyber 加密 |
---|---|
密文第 1 部分 |
密文第 1 部分 |
密文第 2 部分 |
密文第 2 部分 |
5. 参考
- 原论文 CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM
- Kyber - How does it work?(本文 Bady Kyber 的例子来源这个文章,注:本文修正了这个文章中的几处错误)
- Cryptography and Network Security - Principles and Practice, 8th edition, 5.5 Polynomial Arithmetic
- CRYSTALS – Kyber and Dilithium, by Peter Schwabe
6. 附录
6.1. Baby Kyber 示例代码
# polynomials/modules from: https://github.com/GiacomoPope/kyber-py from polynomials import * from modules import * q = 17 n = 4 # x^4 + 1 R = PolynomialRing(q, n) M = Module(R) s0 = R([0,1,-1,-1]) s1 = R([0,-1,0,-1]) s = M([s0,s1]).transpose() A00 = R([11,16,16,6]) A01 = R([3,6,4,9]) A10 = R([1,10,3,5]) A11 = R([15,9,1,6]) A = M([[A00, A01],[A10, A11]]) e0 = R([0,0,1,0]) e1 = R([0,-1,1,0]) e = M([e0,e1]).transpose() t = A @ s + e print("s:",s) print("A:",A) print("e:",e) print("t:",t) r0 = R([0,0,1,-1]) r1 = R([-1,0,1,1]) r = M([r0, r1]).transpose() print("r:",r) e1_0 = R([0,1,1,0]) e1_1 = R([0,0,1,0]) e1 = M([e1_0, e1_1]).transpose() print("e1:",e1) e2 = M([R([0,0,-1,-1])]) print("e2:",e2) m = M([R([9,9,0,9])]) # Encryption u = A.transpose() @ r + e1 v = t.transpose() @ r + e2 + m print("u:", u) print("v:", v) # Decryption m_noisy = v - s.transpose() @ u print("m_noisy:", m_noisy) # m_noisy: [6 + 8*x + 14*x^2 + 8*x^3]