Lattice Cryptography 格密碼概述
Lattice Cryptography 格密碼概述
Date: October 06, 2025
Author:@3cH0_Nu1L
嗯博客運(yùn)營(yíng)至今閱讀量終于突破了10w,新的方向,新的開(kāi)始,新的挑戰(zhàn)嗯
目錄
1. Lattice 格的歷史發(fā)展
1.1 早期數(shù)學(xué)基礎(chǔ)(1840-1980)
格理論的研究起源可以追溯到 1611 年開(kāi)普勒提出的堆球猜想,但真正的數(shù)學(xué)基礎(chǔ)建立于 19 世紀(jì)。1840 年前后,高斯(Carl Friedrich Gauss)正式引進(jìn)了格的概念,并證明了在三維空間中堆球的最大密度。
高斯的貢獻(xiàn):
-
證明了在三維空間中,如果所有球心構(gòu)成格,那么堆積密度的最大值是\(\pi/\sqrt{18} \approx 0.74048\)
-
深入研究了格的幾何性質(zhì),為后續(xù)格理論的發(fā)展奠定了基礎(chǔ)
閔可夫斯基的工作:
1896 年,閔可夫斯基發(fā)表了《數(shù)的幾何》,系統(tǒng)地發(fā)展了格理論:
-
提出了著名的閔可夫斯基定理
-
建立了格的基本理論框架
-
為格在數(shù)論中的應(yīng)用奠定了基礎(chǔ)
1.2 算法突破階段(1982-1996)
1982 年是格理論發(fā)展的重要轉(zhuǎn)折點(diǎn),Lenstra、Lenstra 和 Lovász 提出了著名的LLL 算法(Lenstra-Lenstra-Lovász 算法)。
LLL 算法的主要貢獻(xiàn):
-
提供了第一個(gè)多項(xiàng)式時(shí)間的格基約化算法
-
能夠?qū)⑷我飧窕D(zhuǎn)換為 "好基"(短且接近正交的基)
-
為解決格上的困難問(wèn)題提供了有效工具
LLL 算法的時(shí)間復(fù)雜度:\(O(n^6 \log^3 q)\),其中\(n\)是格的維度,\(q\)是最大元素的絕對(duì)值。
密碼分析應(yīng)用:
LLL 算法在密碼學(xué)和計(jì)算數(shù)論中有著廣泛的應(yīng)用:
-
攻擊背包密碼系統(tǒng)
-
破解低指數(shù) RSA
-
求解整數(shù)規(guī)劃問(wèn)題
-
證明了格密碼的可證明安全性
1.3 第一代格密碼(1996-2005)
1996 年,Miklós Ajtai 發(fā)表了開(kāi)創(chuàng)性論文《Generating Hard Instances of Lattice Problems》,首次將格上的平均情況困難問(wèn)題與最壞情況困難問(wèn)題聯(lián)系起來(lái),奠定了格密碼的理論基礎(chǔ)。
重要里程碑:
-
1996 年:Ajtai 提出 SIS(Short Integer Solution)問(wèn)題
-
1997 年:Ajtai-Dwork 密碼體制問(wèn)世,這是第一個(gè)基于格的密碼體制
-
1999 年:Goldreich、Goldwasser 和 Halevi 提出 GGH 密碼體制
-
1998 年:Hoffstein、Pipher 和 Silverman 提出 NTRU 加密方案
Ajtai 的革命性貢獻(xiàn):
Ajtai 首次證明了可以將格上的最壞情況困難問(wèn)題歸約到平均情況困難問(wèn)題,這為格密碼的安全性提供了堅(jiān)實(shí)的理論基礎(chǔ)。
1.4 第二代格密碼(2005 - 至今)
2005 年,Oded Regev 在 STOC 會(huì)議上發(fā)表了《On Lattices, Learning with Errors, Random Linear Codes, and Cryptography》,提出了 LWE(Learning With Errors)問(wèn)題,這標(biāo)志著格密碼進(jìn)入了快速發(fā)展階段。
關(guān)鍵發(fā)展:
-
2005 年:Regev 證明 LWE 問(wèn)題與格上困難問(wèn)題相關(guān),并構(gòu)建了基于 LWE 的公鑰密碼方案
-
2008 年:Gentry、Peikert、Vaikuntanathan 提出格基陷門函數(shù)
-
2009 年:Gentry 提出第一個(gè)完全同態(tài)加密方案
-
2011 年:Lyubashevsky、Peikert、Regev 提出格基數(shù)字簽名
-
2013 年:Brakerski、Vaikuntanathan 提出 Ring-LWE 的同態(tài)加密方案
-
2016 年:NIST 啟動(dòng)后量子密碼標(biāo)準(zhǔn)化項(xiàng)目
-
2022 年:NIST 選定 CRYSTALS-Kyber 和 CRYSTALS-Dilithium 作為標(biāo)準(zhǔn)
-
2024 年:NIST 發(fā)布 FIPS 203、204、205 后量子密碼標(biāo)準(zhǔn)
1.5 格密碼發(fā)展時(shí)間線
| 年份 | 研究者 | 重要貢獻(xiàn) | 意義 |
|---|---|---|---|
| 1840 | 高斯 | 引入格的數(shù)學(xué)概念,研究格堆積問(wèn)題 | 將格從物理直覺(jué)抽象為數(shù)學(xué)結(jié)構(gòu) |
| 1896 | 閔可夫斯基 | 發(fā)表《數(shù)的幾何》,系統(tǒng)發(fā)展格理論 | 建立格理論的數(shù)學(xué)基礎(chǔ) |
| 1982 | Lenstra-Lenstra-Lovász | 提出 LLL 算法 | 首個(gè)多項(xiàng)式時(shí)間格基約化算法 |
| 1996 | Ajtai | 提出隱藏超平面問(wèn)題及其歸約 | 首次實(shí)現(xiàn)平均 - 最壞情況歸約 |
| 1997 | Ajtai-Dwork | 提出第一個(gè)基于格的密碼系統(tǒng) | 現(xiàn)代格密碼學(xué)的誕生 |
| 1998 | Hoffstein-Pipher-Silverman | 提出 NTRU 加密方案 | 首個(gè)實(shí)用的格密碼方案 |
| 2005 | Regev | 提出 LWE 問(wèn)題 | 格密碼的重大理論突破 |
| 2009 | Gentry | 提出第一個(gè)完全同態(tài)加密方案 | 密碼學(xué) "圣杯" 的實(shí)現(xiàn) |
| 2016 | NIST | 啟動(dòng)后量子密碼標(biāo)準(zhǔn)化項(xiàng)目 | 推動(dòng)格密碼走向標(biāo)準(zhǔn)化 |
| 2022 | NIST | 選定 Kyber 和 Dilithium 作為標(biāo)準(zhǔn) | 格密碼成為國(guó)際標(biāo)準(zhǔn) |
| 2024 | NIST | 發(fā)布 FIPS 203/204/205 標(biāo)準(zhǔn) | 格密碼正式進(jìn)入主流應(yīng)用 |
2. 格的數(shù)學(xué)基礎(chǔ)與理論推導(dǎo)
2.1 格的嚴(yán)格數(shù)學(xué)定義
定義 2.1(格):在\(n\)維歐幾里得空間\(\mathbb{R}^m\)(\(m \geq n\))中,設(shè)\(b_1, b_2, \ldots, b_n\)是一組線性無(wú)關(guān)的向量,則由這些向量的所有整數(shù)線性組合構(gòu)成的集合稱為格:
\(\mathcal{L}(b_1, b_2, \ldots, b_n) = \left\{ \sum_{i=1}^n x_i b_i \mid x_i \in \mathbb{Z} \right\}\)
其中\(B = [b_1 \mid b_2 \mid \ldots \mid b_n] \in \mathbb{R}^{m \times n}\)稱為格的基矩陣。
格的基本性質(zhì):
-
離散性:格由離散的點(diǎn)(格點(diǎn))組成,在任意有界區(qū)域內(nèi)只有有限個(gè)格點(diǎn)
-
周期性:格具有平移對(duì)稱性,格點(diǎn)在各個(gè)方向上周期性排列
-
無(wú)限性:格包含無(wú)限多個(gè)格點(diǎn)
-
線性結(jié)構(gòu):格在向量加法下構(gòu)成交換群,并且與\(\mathbb{Z}^n\)同構(gòu)
2.2 格的基表示與變換
基的非唯一性:
同一個(gè)格可以有不同的基表示。如果\(B\)和\(B'\)是同一格的兩個(gè)基,則存在幺模矩陣\(U \in \mathbb{Z}^{n \times n}\)(\(\det(U) = \pm 1\)),使得:
\(B' = B U\)
證明:
設(shè)\(B = [b_1, b_2, \ldots, b_n]\)和\(B' = [b_1', b_2', \ldots, b_n']\)是同一格的兩個(gè)基,則每個(gè)\(b_i'\)都可以表示為\(B\)的列向量的整數(shù)線性組合:
\(b_i' = \sum_{j=1}^n u_{j,i} b_j\)
其中\(u_{j,i} \in \mathbb{Z}\)。因此\(B' = B U\),其中\(U = (u_{j,i}) \in \mathbb{Z}^{n \times n}\)。
由于\(B\)和\(B'\)都是基,\(U\)必須是可逆的,且其逆矩陣\(U^{-1}\)也必須有整數(shù) entries。這意味著\(\det(U) = \pm 1\),即\(U\)是幺模矩陣。
2.3 格的基本區(qū)域
定義 2.2(基本區(qū)域):格\(\mathcal{L}\)的基本區(qū)域(Fundamental Domain)是指格基在區(qū)間\([0,1)\)內(nèi)的所有實(shí)系數(shù)線性組合構(gòu)成的集合:
\(\mathcal{F}(B) = \left\{ \sum_{i=1}^n x_i b_i \mid 0 \leq x_i < 1 \right\}\)
基本區(qū)域的性質(zhì):
-
體積不變性:基本區(qū)域的體積等于格的行列式\(\det(\mathcal{L}) = |\det(B^T B)|^{1/2}\)
-
覆蓋性:將基本區(qū)域平移到每個(gè)格點(diǎn)上,可以覆蓋整個(gè)空間而不重疊
-
唯一性表示:空間中的任意向量都可以唯一表示為格點(diǎn)加上基本區(qū)域中的向量
2.4 格的行列式與體積
定義 2.3(格的行列式):格\(\mathcal{L}\)的行列式(或協(xié)體積)是格基向量構(gòu)成的平行多面體的體積,記為\(\det(\mathcal{L})\)或\(\text{vol}(\mathcal{L})\)。
對(duì)于滿秩格(\(m = n\)),行列式為:
\(\det(\mathcal{L}) = |\det(B)|\)
對(duì)于非滿秩格(\(m > n\)),行列式為:
\(\det(\mathcal{L}) = |\det(B^T B)|^{1/2}\)
行列式的幾何意義:
行列式表示格點(diǎn)的分布密度。行列式越小,格點(diǎn)分布越密集;行列式越大,格點(diǎn)分布越稀疏。
2.5 閔可夫斯基定理的詳細(xì)證明
定理 2.1(閔可夫斯基第一定理):任何秩為\(n\)的格\(\mathcal{L}\)都包含一個(gè)非零向量\(v\),使得:
\(\|v\| \leq \sqrt{n} \cdot (\det(\mathcal{L}))^{1/n}\)
證明:
第一步:構(gòu)造輔助集合
設(shè)\(R = \sqrt{n} \cdot (\det(\mathcal{L}))^{1/n}\),考慮以原點(diǎn)為中心、半徑為\(R\)的閉球\(B(0, R)\)。我們需要證明\(B(0, R)\)中包含非零格點(diǎn)。
第二步:體積比較
球\(B(0, R)\)的體積為:
\(\text{vol}(B(0, R)) = \frac{\pi^{n/2}}{\Gamma(n/2 + 1)} R^n\)
代入\(R\)的值:
\(\text{vol}(B(0, R)) = \frac{\pi^{n/2}}{\Gamma(n/2 + 1)} n^{n/2} \det(\mathcal{L})\)
第三步:應(yīng)用鴿巢原理
考慮球\(B(0, R/2)\)與格的平移\(v + B(0, R/2)\),其中\(v \in \mathcal{L}\)。
這些平移球的體積為:
\(\text{vol}(v + B(0, R/2)) = \frac{\pi^{n/2}}{\Gamma(n/2 + 1)} (R/2)^n\)
如果這些球互不相交,則它們的總體積不會(huì)超過(guò)基本區(qū)域的體積\(\det(\mathcal{L})\)。但實(shí)際上:
\(\frac{\pi^{n/2}}{\Gamma(n/2 + 1)} (R/2)^n = \frac{\pi^{n/2}}{\Gamma(n/2 + 1)} \frac{n^{n/2}}{2^n} \det(\mathcal{L})\)
對(duì)于\(n \geq 1\),我們有\(\frac{\pi^{n/2} n^{n/2}}{\Gamma(n/2 + 1) 2^n} > 1\),這意味著至少有兩個(gè)平移球相交。
第四步:得出結(jié)論
設(shè)\(u + B(0, R/2)\)和\(v + B(0, R/2)\)相交,則存在\(x, y \in B(0, R/2)\)使得\(u + x = v + y\)。因此\(u - v = y - x\),且:
\(\|u - v\| = \|y - x\| \leq \|y\| + \|x\| < R/2 + R/2 = R\)
由于\(u - v \in \mathcal{L}\)且\(u \neq v\),所以\(u - v\)是\(B(0, R)\)中的非零格點(diǎn)。
閔可夫斯基定理的應(yīng)用:
-
給出最短向量長(zhǎng)度的上界
-
證明格中存在短向量
-
密碼學(xué)安全性分析
-
格基約化算法的理論指導(dǎo)
2.6 對(duì)偶格的理論推導(dǎo)
定義 2.4(對(duì)偶格):給定格\(\mathcal{L}(B)\),其對(duì)偶格\(\mathcal{L}^*\)定義為:
\(\mathcal{L}^* = \left\{ x \in \text{span}(\mathcal{L}) \mid \langle x, v \rangle \in \mathbb{Z} \text{ for all } v \in \mathcal{L} \right\}\)
對(duì)偶格的基表示:
如果\(B\)是\(\mathcal{L}\)的基,則對(duì)偶格\(\mathcal{L}^*\)的基為:
\(B^* = (B^T B)^{-1} B^T\)
證明:
設(shè)\(B = [b_1, b_2, \ldots, b_n]\),\(B^* = [b_1^*, b_2^*, \ldots, b_n^*]\)。我們需要證明\(\langle b_i^*, b_j \rangle = \delta_{i,j}\)(Kronecker 符號(hào))。
計(jì)算:
\(\langle b_i^*, b_j \rangle = e_i^T (B^T B)^{-1} B^T b_j = e_i^T (B^T B)^{-1} (B^T B) e_j = e_i^T e_j = \delta_{i,j}\)
因此\(B^*\)確實(shí)是對(duì)偶格的基。
對(duì)偶格的重要性質(zhì):
-
\((\mathcal{L}^*)^* = \mathcal{L}\)
-
\(\det(\mathcal{L}^*) = 1/\det(\mathcal{L})\)
-
\(\lambda_k(\mathcal{L}) \lambda_{n-k+1}(\mathcal{L}^*) \geq 1\)(Banaszczyk 不等式)
3. 格基與格基約化算法
3.1 Gram-Schmidt 正交化過(guò)程
Gram-Schmidt 算法:
將任意基轉(zhuǎn)換為正交基的過(guò)程。
算法 3.1(Gram-Schmidt 正交化):
輸入:基\(B = [b_1, b_2, \ldots, b_n]\)
輸出:正交基\(B^* = [b_1^*, b_2^*, \ldots, b_n^*]\)和系數(shù)矩陣\(\mu\)
for i from 1 to n:
b_i^* = b_i
for j from 1 to i-1:
mu[i,j] = <b_i, b_j^*> / <b_j^*, b_j^*>
b_i^* = b_i^* - mu[i,j] * b_j^*
數(shù)學(xué)表示:
\(b_i^* = b_i - \sum_{j=1}^{i-1} \mu_{i,j} b_j^*\)
其中\(\mu_{i,j} = \frac{\langle b_i, b_j^* \rangle}{\langle b_j^*, b_j^* \rangle}\)。
性質(zhì):
-
\(b_i^*\)與\(b_j^*\)正交(\(i \neq j\))
-
\(\det(B) = \prod_{i=1}^n \|b_i^*\|\)
-
Gram-Schmidt 正交化不改變格的行列式
3.2 LLL 算法的詳細(xì)推導(dǎo)
3.2.1 LLL 約化條件
定義 3.1(LLL 約化基):一個(gè)格基被稱為 LLL 約化的,如果滿足以下條件:
-
尺寸縮減條件:\(|\mu_{i,j}| \leq 1/2\) for all \(j < i\)
-
Lovász 條件:\(\|b_i^* + \mu_{i,i-1} b_{i-1}^*\|^2 \geq (\delta - \mu_{i,i-1}^2) \|b_{i-1}^*\|^2\)
其中\(\delta \in (1/4, 1)\)是一個(gè)參數(shù),通常取\(\delta = 3/4\)。
3.2.2 LLL 算法的完整實(shí)現(xiàn)
import numpy as np
from numpy.linalg import inv, norm
def gram_schmidt(B):
"""Gram-Schmidt正交化"""
n = B.shape[1]
B_star = B.astype(np.float64).copy()
mu = np.zeros((n, n), dtype=np.float64)
for i in range(n):
for j in range(i):
mu[i, j] = np.dot(B_star[:, i], B_star[:, j]) / np.dot(B_star[:, j], B_star[:, j])
B_star[:, i] -= mu[i, j] * B_star[:, j]
return B_star, mu
def lll_reduction(B, delta=0.75):
"""完整的LLL格基約化算法"""
n = B.shape[1]
B = B.astype(np.float64).copy()
B_star, mu = gram_schmidt(B)
i = 1
while i < n:
# 尺寸縮減
for j in range(i-1, -1, -1):
if abs(mu[i, j]) > 0.5:
t = round(mu[i, j])
B[:, i] -= t * B[:, j]
# 更新Gram-Schmidt系數(shù)
B_star, mu = gram_schmidt(B)
# 檢查L(zhǎng)ovász條件
current_norm_sq = np.dot(B_star[:, i], B_star[:, i])
prev_norm_sq = np.dot(B_star[:, i-1], B_star[:, i-1])
lovasz_left = current_norm_sq + mu[i, i-1]**2 * prev_norm_sq
lovasz_right = delta * prev_norm_sq
if lovasz_left < lovasz_right:
# 交換列i和i-1
B[:, [i, i-1]] = B[:, [i-1, i]]
# 更新Gram-Schmidt系數(shù)
B_star, mu = gram_schmidt(B)
i = max(i-1, 1)
else:
i += 1
return B
# 示例
basis = np.array([[1000, 999], [999, 998]])
print("原始基:")
print(basis)
reduced_basis = lll_reduction(basis)
print("\nLLL約化基:")
print(reduced_basis)
print("\n基向量長(zhǎng)度:", [norm(col) for col in reduced_basis.T])
3.2.3 LLL 算法的近似保證
定理 3.1(LLL 算法的近似保證):
設(shè)\(B\)是 LLL 約化基,則對(duì)于所有\(1 \leq k \leq n\):
\(\|b_k\| \leq 2^{(n-1)/2} \lambda_k(\mathcal{L})\)
其中\(\lambda_k(\mathcal{L})\)是格的第\(k\)個(gè)連續(xù)最小長(zhǎng)度。
證明概要:
通過(guò)歸納法證明。對(duì)于\(k=1\),利用 Lovász 條件和尺寸縮減條件,可以得到:
\(\|b_1\|^2 \leq \frac{2}{4\delta - 1} \det(\mathcal{L})^{2/n}\)
結(jié)合閔可夫斯基定理,可得\(\|b_1\| \leq 2^{(n-1)/2} \lambda_1(\mathcal{L})\)。
對(duì)于一般\(k\),通過(guò)考慮子格和應(yīng)用歸納假設(shè),可以得到相應(yīng)的界。
3.3 BKZ 算法的原理與實(shí)現(xiàn)
3.3.1 BKZ 算法的基本思想
BKZ(Block Korkine-Zolotarev)算法是 LLL 算法的改進(jìn)版本,通過(guò)塊約化的方式獲得更好的基質(zhì)量。
算法 3.2(BKZ 算法框架):
function BKZ(B, block_size):
n = dimension of B
while True:
improved = False
for i from 0 to n - block_size:
# 提取塊
block = B[:, i:i+block_size]
# 對(duì)塊進(jìn)行局部約化(精確求解SVP)
reduced_block = solve_SVP(block)
# 更新原基
if reduced_block != block:
B[:, i:i+block_size] = reduced_block
improved = True
# 重新進(jìn)行Gram-Schmidt正交化
recompute Gram-Schmidt coefficients
if not improved:
break
return B
3.3.2 BKZ 算法的 Python 實(shí)現(xiàn)
def bkz_reduction(B, block_size=20, max_iterations=100):
"""簡(jiǎn)化版BKZ算法"""
n = B.shape[1]
B = B.astype(np.float64).copy()
for iteration in range(max_iterations):
improved = False
for i in range(n - block_size + 1):
# 提取當(dāng)前塊
block = B\[:, i:i+block_size].copy()
# 對(duì)塊進(jìn)行LLL約化(實(shí)際中應(yīng)該用更精確的算法)
reduced_block = lll_reduction(block)
# 檢查是否有改進(jìn)
original_norm = sum(norm(col)\*\*2 for col in block.T)
reduced_norm = sum(norm(col)\*\*2 for col in reduced_block.T)
if reduced_norm < original_norm - 1e-9: # 允許小的數(shù)值誤差
B[:, i:i+block_size] = reduced_block
improved = True
if not improved:
break
return B
# 示例
np.random.seed(42)
basis = np.random.randint(1, 100, size=(5, 5))
print("原始基:")
print(basis)
bkz_basis = bkz_reduction(basis, block_size=3)
print("\nBKZ約化基:")
print(bkz_basis)
print("\n基向量長(zhǎng)度:", \[norm(col) for col in bkz_basis.T])
4. 格的基本屬性及關(guān)鍵概念
4.1 格的核心參數(shù)
4.1.1 秩與維度
定義 4.1(秩):格基中向量的個(gè)數(shù)\(n\)稱為格的秩,記為\(\text{rank}(\mathcal{L})\)。
定義 4.2(維度):格所在的歐幾里得空間的維度\(m\)稱為格的維度。
滿秩格與低秩格:
-
當(dāng)\(n = m\)時(shí),稱格為滿秩格
-
當(dāng)\(n < m\)時(shí),稱格為低秩格
4.1.2 行列式與密度
定義 4.3(格的密度):格的密度\(\rho(\mathcal{L})\)是格點(diǎn)在空間中的分布密度:
\(\rho(\mathcal{L}) = \frac{1}{\det(\mathcal{L})}\)
物理意義:
密度表示單位體積內(nèi)的格點(diǎn)數(shù)量。密度越高,格點(diǎn)分布越密集。
4.1.3 最小距離
定義 4.4(最小距離):格\(\mathcal{L}\)的最小距離\(d(\mathcal{L})\)是格中兩個(gè)不同格點(diǎn)之間的最小歐幾里得距離:
\(d(\mathcal{L}) = \min_{u, v \in \mathcal{L}, u \neq v} \|u - v\|\)
計(jì)算:
最小距離等于格中最短非零向量的長(zhǎng)度:
\(d(\mathcal{L}) = \min_{v \in \mathcal{L}, v \neq 0} \|v\| = \lambda_1(\mathcal{L})\)
其中\(\lambda_1(\mathcal{L})\)是格的第一個(gè)連續(xù)最小長(zhǎng)度。
4.2 連續(xù)最小長(zhǎng)度
定義 4.5(連續(xù)最小長(zhǎng)度):格\(\mathcal{L}\)的第\(k\)個(gè)連續(xù)最小長(zhǎng)度\(\lambda_k(\mathcal{L})\)是包含\(k\)個(gè)線性無(wú)關(guān)格向量的最小球的半徑。
數(shù)學(xué)表示:
\(\lambda_k(\mathcal{L})\)是滿足以下條件的最小實(shí)數(shù)\(r\):以原點(diǎn)為中心、半徑為\(r\)的球體內(nèi)至少包含\(k\)個(gè)線性無(wú)關(guān)的格向量。
性質(zhì):
-
\(\lambda_1(\mathcal{L}) \leq \lambda_2(\mathcal{L}) \leq \ldots \leq \lambda_n(\mathcal{L})\)
-
\(\lambda_k(\mathcal{L}) \leq \sqrt{k} \cdot (\det(\mathcal{L}))^{1/n}\)(閔可夫斯基定理的推廣)
-
\(\lambda_k(\mathcal{L}) \lambda_{n-k+1}(\mathcal{L}^*) \geq 1\)(對(duì)偶性)
4.3 覆蓋半徑
定義 4.6(覆蓋半徑):格\(\mathcal{L}\)的覆蓋半徑\(\mu(\mathcal{L})\)是從原點(diǎn)到格的最遠(yuǎn)點(diǎn)的距離:
\(\mu(\mathcal{L}) = \max_{x \in \mathbb{R}^n} \min_{v \in \mathcal{L}} \|x - v\|\)
幾何意義:
覆蓋半徑是能夠覆蓋整個(gè)空間的最小球的半徑,使得每個(gè)球心都是格點(diǎn)。
與連續(xù)最小長(zhǎng)度的關(guān)系:
對(duì)于滿秩格,有:
\(\mu(\mathcal{L}) \leq \frac{1}{2} \sum_{i=1}^n \lambda_i(\mathcal{L})\)
4.4 基質(zhì)量評(píng)估指標(biāo)
4.4.1 Hadamard 比率
定義 4.7(Hadamard 比率):
\(\text{HR}(B) = \frac{|\det(B)|}{\prod_{i=1}^n \|b_i\|}\)
意義:
Hadamard 比率衡量基的正交性。理想正交基的 Hadamard 比率為 1,比率越接近 1,基的正交性越好。
4.4.2 正交缺陷
定義 4.8(正交缺陷):
\(\text{OD}(B) = \frac{\prod_{i=1}^n \|b_i\|}{|\det(B)|} = \frac{1}{\text{HR}(B)}\)
意義:
正交缺陷越小,基的質(zhì)量越好。對(duì)于 LLL 約化基,有\(\text{OD}(B) \leq 2^{n(n-1)/4}\)。
4.5 代碼實(shí)現(xiàn):格參數(shù)計(jì)算
def compute_lattice_parameters(B):
"""計(jì)算格的基本參數(shù)"""
n = B.shape[1]
# 計(jì)算行列式
if B.shape[0] == B.shape[1]: # 滿秩格
det = abs(np.linalg.det(B))
else: # 非滿秩格
det = np.sqrt(abs(np.linalg.det(B.T @ B)))
# 計(jì)算Gram-Schmidt正交化
B_star, mu = gram_schmidt(B)
# 計(jì)算基向量長(zhǎng)度
lengths = [np.linalg.norm(col) for col in B.T]
# 計(jì)算Hadamard比率
product_lengths = np.prod(lengths)
hadamard_ratio = det / product_lengths if product_lengths > 0 else 0
# 計(jì)算正交缺陷
ortho_defect = product_lengths / det if det > 0 else float('inf')
# 計(jì)算密度
density = 1 / det if det > 0 else 0
return {
'dimension': n,
'determinant': det,
'basis_lengths': lengths,
'hadamard_ratio': hadamard_ratio,
'orthogonal_defect': ortho_defect,
'density': density
}
# 示例
basis1 = np.array(\[\[3, 1], \[1, 2]])
basis2 = np.array(\[\[1, 0], \[0, 1]]) # 標(biāo)準(zhǔn)正交基
basis3 = np.array(\[\[10, 9], \[8, 7]]) # 條件數(shù)較大的基
print("標(biāo)準(zhǔn)正交基參數(shù):")
print(compute_lattice_parameters(basis2))
print("\n一般基參數(shù):")
print(compute_lattice_parameters(basis1))
print("\n條件數(shù)較大的基參數(shù):")
print(compute_lattice_parameters(basis3))
5. SVP 最短向量問(wèn)題深度解析
5.1 SVP 問(wèn)題的嚴(yán)格定義
定義 5.1(最短向量問(wèn)題 SVP):
給定格\(\mathcal{L}\),尋找格中最短的非零向量\(v \in \mathcal{L}\),即尋找\(v \neq 0\)使得\(\|v\| = \lambda_1(\mathcal{L})\),其中\(\lambda_1(\mathcal{L})\)是格的最小距離。
數(shù)學(xué)形式:
\(\text{Find } v \in \mathcal{L} \setminus \{0\} \text{ such that } \|v\| = \min_{u \in \mathcal{L} \setminus \{0\}} \|u\|\)
5.2 SVP 問(wèn)題的變體
5.2.1 近似 SVP
定義 5.2(****- 近似 SVP):
給定格\(\mathcal{L}\)和近似因子\(\gamma \geq 1\),尋找非零向量\(v \in \mathcal{L}\)使得\(\|v\| \leq \gamma \cdot \lambda_1(\mathcal{L})\)。
5.2.2 判定 SVP
定義 5.3(判定 SVP):
給定格\(\mathcal{L}\)和實(shí)數(shù)\(d\),判定是否存在非零向量\(v \in \mathcal{L}\)使得\(\|v\| \leq d\)。
5.2.3 GapSVP
定義 5.4(GapSVP):
給定格\(\mathcal{L}\)和兩個(gè)實(shí)數(shù)\(d_1 < d_2\),區(qū)分以下兩種情況:
-
\(\lambda_1(\mathcal{L}) \leq d_1\)
-
\(\lambda_1(\mathcal{L}) > d_2\)
5.3 計(jì)算復(fù)雜性分析
5.3.1 精確 SVP 的復(fù)雜性
定理 5.1:精確 SVP 問(wèn)題是 NP 困難的。
證明概要:
通過(guò)將 NP 完全問(wèn)題(如子集和問(wèn)題)歸約到 SVP 問(wèn)題來(lái)證明。
推論:
在 P ≠ NP 的假設(shè)下,不存在多項(xiàng)式時(shí)間算法能夠精確求解 SVP 問(wèn)題。
5.3.2 近似 SVP 的復(fù)雜性
定理 5.2:對(duì)于任意常數(shù)\(\gamma \geq 1\),\(\gamma\)- 近似 SVP 問(wèn)題是 NP 困難的。
定理 5.3:對(duì)于\(\gamma = 2^{O(n/\log n)}\),存在多項(xiàng)式時(shí)間算法求解\(\gamma\)- 近似 SVP 問(wèn)題。
復(fù)雜性總結(jié):
| 問(wèn)題變體 | 復(fù)雜性 | 已知算法 |
|---|---|---|
| 精確 SVP | NP 困難 | 枚舉算法、篩法 |
| 常數(shù)近似 SVP | NP 困難 | LLL 算法(指數(shù)近似) |
| 多項(xiàng)式近似 SVP | NP 困難 | BKZ 算法(多項(xiàng)式近似) |
| 指數(shù)近似 SVP | P | LLL 算法 |
5.4 SVP 求解算法詳解
5.4.1 枚舉算法
基本思想:
通過(guò)系統(tǒng)性地搜索格中的向量來(lái)尋找最短向量。
算法 5.1(枚舉算法):
def svp_enumeration(B, max_depth=20):
"""基于枚舉的SVP求解算法"""
n = B.shape[1]
shortest_vector = None
shortest_norm = float('inf')
# 遞歸枚舉函數(shù)
def enumerate_recursive(current_sum, depth, coefficients):
nonlocal shortest_vector, shortest_norm
if depth == n:
if np.any(current_sum != 0): # 非零向量
current_norm = np.linalg.norm(current_sum)
if current_norm < shortest_norm:
shortest_norm = current_norm
shortest_vector = current_sum.copy()
return
# 為了控制搜索空間,限制系數(shù)范圍
max_coeff = max_depth // (n - depth + 1)
for coeff in range(-max_coeff, max_coeff + 1):
new_sum = current_sum + coeff \* B\[:, depth]
new_coeffs = coefficients + \[coeff]
# 剪枝:如果當(dāng)前向量已經(jīng)比已知最短向量長(zhǎng),停止搜索
current_norm = np.linalg.norm(new_sum)
if current_norm >= shortest_norm \* 1.1: # 增加一點(diǎn)余量
continue
enumerate_recursive(new_sum, depth + 1, new_coeffs)
# 從原點(diǎn)開(kāi)始枚舉
enumerate_recursive(np.zeros(B.shape\[0]), 0, \[])
return shortest_vector, shortest_norm
# 示例
basis = np.array(\[\[3, 1], \[1, 2]])
print("格基:")
print(basis)
shortest_vec, shortest_length = svp_enumeration(basis)
print("\n最短向量:", shortest_vec)
print("最短向量長(zhǎng)度:", shortest_length)
print("理論最短長(zhǎng)度:", np.sqrt(2)) # 對(duì)于這個(gè)基,理論最短向量是(1,-1),長(zhǎng)度√2
時(shí)間復(fù)雜度分析:
枚舉算法的時(shí)間復(fù)雜度為\(O((2k)^n)\),其中\(k\)是搜索系數(shù)的范圍。在實(shí)踐中,該算法只適用于維度\(n \leq 30\)的格。
5.4.2 篩法
基本思想:
通過(guò)迭代地生成和篩選短向量來(lái)尋找最短向量。
算法 5.2(基于列表的篩法):
def svp_sieve(B, max_vectors=10000):
"""基于篩法的SVP求解算法"""
n = B.shape\[1]
vectors = \[]
# 生成初始向量集
for i in range(n):
vectors.append(B\[:, i].copy())
vectors.append(-B\[:, i].copy())
# 迭代篩法
improved = True
while improved and len(vectors) < max_vectors:
improved = False
# 計(jì)算當(dāng)前最短向量
vectors.sort(key=lambda v: np.linalg.norm(v))
current_shortest = vectors\[0]
current_norm = np.linalg.norm(current_shortest)
# 嘗試生成更短的向量
new_vectors = \[]
for i in range(len(vectors)):
for j in range(i+1, len(vectors)):
v = vectors\[i] - vectors\[j]
if np.any(v != 0): # 非零向量
v_norm = np.linalg.norm(v)
if v_norm < current_norm \* 0.99: # 找到更短的向量
new_vectors.append(v)
improved = True
# 添加新向量并去重
for v in new_vectors:
is_new = True
for existing in vectors:
if np.allclose(v, existing):
is_new = False
break
if is_new:
vectors.append(v)
# 限制向量集大小
if len(vectors) > max_vectors:
vectors.sort(key=lambda v: np.linalg.norm(v))
vectors = vectors\[:max_vectors]
# 返回最短向量
vectors.sort(key=lambda v: np.linalg.norm(v))
shortest_vector = vectors\[0]
shortest_norm = np.linalg.norm(shortest_vector)
return shortest_vector, shortest_norm
# 示例
basis = np.array(\[\[5, 2], \[3, 4]])
print("格基:")
print(basis)
shortest_vec, shortest_length = svp_sieve(basis)
print("\n最短向量:", shortest_vec)
print("最短向量長(zhǎng)度:", shortest_length)
時(shí)間復(fù)雜度分析:
篩法的時(shí)間復(fù)雜度為\(O(2^{O(n/\log n)})\),比枚舉算法更高效,適用于維度\(n \leq 80\)的格。
5.4.3 基于 LLL 的近似算法
算法 5.3(基于 LLL 的 SVP 近似求解):
def svp_lll_approx(B):
"""基于LLL算法的SVP近似求解"""
reduced_basis = lll_reduction(B)
# 返回約化基中的最短向量
basis_vectors = \[reduced\_basis\[:, i] for i in range(reduced_basis.shape\[1])]
basis_vectors.sort(key=lambda v: np.linalg.norm(v))
return basis_vectors\[0], np.linalg.norm(basis_vectors\[0])
# 示例
np.random.seed(42)
basis = np.random.randint(1, 100, size=(5, 5))
print("原始基:")
print(basis)
lll_shortest, lll_length = svp_lll_approx(basis)
print("\nLLL近似最短向量:", lll_shortest)
print("LLL近似最短長(zhǎng)度:", lll_length)
5.5 西浦團(tuán)隊(duì) SVP 突破的技術(shù)分析
5.5.1 突破概述
2025 年,西交利物浦大學(xué)丁津泰教授團(tuán)隊(duì)成功破解了 200 維 SVP 難題,刷新了全球紀(jì)錄。
技術(shù)突破點(diǎn):
-
創(chuàng)新的算法設(shè)計(jì),結(jié)合了篩法和深度學(xué)習(xí)技術(shù)
-
高效的硬件加速,使用了專門的 GPU 集群
-
優(yōu)化的內(nèi)存管理,解決了高維數(shù)據(jù)的存儲(chǔ)問(wèn)題
5.5.2 對(duì)格密碼的影響
安全參數(shù)重新評(píng)估:
西浦團(tuán)隊(duì)的突破表明,格密碼的安全參數(shù)需要重新評(píng)估。原本認(rèn)為安全的參數(shù)可能需要調(diào)整。
新的研究方向:
-
開(kāi)發(fā)更強(qiáng)的格基約化算法
-
設(shè)計(jì)更安全的格密碼方案
-
探索新的格困難問(wèn)題
6. CVP 最近向量問(wèn)題理論與算法
6.1 CVP 問(wèn)題的嚴(yán)格定義
定義 6.1(最近向量問(wèn)題 CVP):
給定格\(\mathcal{L}\)和目標(biāo)向量\(t\),尋找格中離\(t\)最近的向量\(v\)。
數(shù)學(xué)形式:
\(\text{Find } v \in \mathcal{L} \text{ such that } \|v - t\| = \min_{u \in \mathcal{L}} \|u - t\|\)
6.2 CVP 問(wèn)題的變體
6.2.1 近似 CVP
定義 6.2(****- 近似 CVP):
給定格\(\mathcal{L}\)、目標(biāo)向量\(t\)和近似因子\(\gamma \geq 1\),尋找向量\(v \in \mathcal{L}\)使得\(\|v - t\| \leq \gamma \cdot \min_{u \in \mathcal{L}} \|u - t\|\)。
6.2.2 判定 CVP
定義 6.3(判定 CVP):
給定格\(\mathcal{L}\)、目標(biāo)向量\(t\)和實(shí)數(shù)\(d\),判定是否存在向量\(v \in \mathcal{L}\)使得\(\|v - t\| \leq d\)。
6.2.3 BDD 問(wèn)題
定義 6.4(有界距離解碼 BDD):
給定格\(\mathcal{L}\)、目標(biāo)向量\(t\)和實(shí)數(shù)\(\alpha\),假設(shè)\(\min_{u \in \mathcal{L}} \|u - t\| \leq \alpha \cdot \lambda_1(\mathcal{L})\),尋找向量\(v \in \mathcal{L}\)使得\(\|v - t\| = \min_{u \in \mathcal{L}} \|u - t\|\)。
6.3 CVP 與格陪集
6.3.1 格陪集的定義
定義 6.5(格陪集):
給定格\(\mathcal{L}\)和向量\(t\),格陪集定義為:
\(\mathcal{L} + t = \{ v + t \mid v \in \mathcal{L} \}\)
性質(zhì):
-
格陪集是格的平移
-
不同的陪集要么不相交,要么完全相同
-
所有陪集構(gòu)成空間的一個(gè)劃分
6.3.2 CVP 的幾何意義
CVP 問(wèn)題等價(jià)于在格陪集中尋找離原點(diǎn)最近的點(diǎn):
\(\min_{v \in \mathcal{L}} \|v - t\| = \min_{w \in \mathcal{L} + t} \|w\|\)
6.4 CVP 求解算法詳解
6.4.1 最近平面算法
算法 6.1(最近平面算法):
def nearest_plane_algorithm(B, t):
"""最近平面算法求解CVP問(wèn)題"""
n = B.shape[1]
B = B.astype(np.float64).copy()
t = t.astype(np.float64).copy()
# Gram-Schmidt正交化
B_star, mu = gram_schmidt(B)
# 計(jì)算系數(shù)
x = np.zeros(n, dtype=np.int64)
current_t = t.copy()
for i in range(n-1, -1, -1):
# 計(jì)算投影系數(shù)
c = np.dot(current_t, B_star[:, i]) / np.dot(B_star[:, i], B_star[:, i])
x[i] = round(c)
# 更新目標(biāo)向量
current_t -= x[i] * B[:, i]
# 計(jì)算最近向量
nearest_vector = B @ x
return nearest_vector, x
# 示例
basis = np.array([[3, 1], [1, 2]])
target = np.array([4.2, 3.7])
print("格基:")
print(basis)
print("目標(biāo)向量:", target)
nearest_vec, coeffs = nearest_plane_algorithm(basis, target)
print("\n最近格向量:", nearest_vec)
print("系數(shù):", coeffs)
print("距離:", np.linalg.norm(target - nearest_vec))
算法分析:
最近平面算法是一種貪心算法,時(shí)間復(fù)雜度為\(O(n^3)\)。該算法不能保證找到精確解,但在實(shí)踐中表現(xiàn)良好。
6.4.2 球形解碼算法
算法 6.2(球形解碼算法):
def sphere_decoding(B, t, radius=None):
"""球形解碼算法求解CVP問(wèn)題"""
n = B.shape[1]
B = B.astype(np.float64).copy()
t = t.astype(np.float64).copy()
# 如果沒(méi)有指定半徑,使用最近平面算法的結(jié)果作為初始半徑
if radius is None:
initial_nearest, _ = nearest_plane_algorithm(B, t)
radius = np.linalg.norm(initial_nearest - t) * 1.1 # 增加10%的余量
# Gram-Schmidt正交化
B_star, mu = gram_schmidt(B)
# 預(yù)計(jì)算一些值
inv_norms_sq = [1.0 / np.dot(B_star[:, i], B_star[:, i]) for i in range(n)]
# 遞歸搜索函數(shù)
best_vector = None
best_distance_sq = float('inf')
def search(i, current_sum, current_distance_sq):
nonlocal best_vector, best_distance_sq
if i == 0:
# 找到一個(gè)候選向量
if current_distance_sq < best_distance_sq:
best_distance_sq = current_distance_sq
best_vector = current_sum.copy()
return
# 計(jì)算當(dāng)前層的參數(shù)
i -= 1
residual = t - current_sum
# 計(jì)算投影系數(shù)
proj = np.dot(residual, B_star[:, i]) * inv_norms_sq[i]
c = round(proj)
# 計(jì)算距離貢獻(xiàn)
distance_contribution = (proj - c)**2 * np.dot(B_star[:, i], B_star[:, i])
# 剪枝:如果當(dāng)前距離已經(jīng)超過(guò)半徑,停止搜索
new_distance_sq = current_distance_sq + distance_contribution
if new_distance_sq > radius**2:
return
# 嘗試當(dāng)前系數(shù)
new_sum = current_sum + c * B[:, i]
search(i, new_sum, new_distance_sq)
# 嘗試相鄰系數(shù)(c-1和c+1)
for dc in [-1, 1]:
new_c = c + dc
distance_contribution = (proj - new_c)**2 * np.dot(B_star[:, i], B_star[:, i])
new_distance_sq = current_distance_sq + distance_contribution
if new_distance_sq <= radius**2:
new_sum = current_sum + new_c * B[:, i]
search(i, new_sum, new_distance_sq)
# 開(kāi)始搜索
search(n, np.zeros_like(t), 0.0)
return best_vector, np.sqrt(best_distance_sq) if best_vector is not None else None
# 示例
basis = np.array([[3, 1], [1, 2]])
target = np.array([4.2, 3.7])
print("格基:")
print(basis)
print("目標(biāo)向量:", target)
sphere_nearest, sphere_dist = sphere_decoding(basis, target)
print("\n球形解碼找到的最近向量:", sphere_nearest)
print("距離:", sphere_dist)
算法分析:
球形解碼算法在有利情況下可以找到精確解,時(shí)間復(fù)雜度在最壞情況下為指數(shù)級(jí),但在實(shí)踐中通常比枚舉算法更高效。
6.4.3 基于 LLL 的近似算法
算法 6.3(基于 LLL 的 CVP 近似求解):
def cvp_lll_approx(B, t):
"""基于LLL算法的CVP近似求解"""
# 對(duì)格基進(jìn)行LLL約化
reduced_basis = lll_reduction(B)
# 應(yīng)用最近平面算法
nearest_vector, _ = nearest_plane_algorithm(reduced_basis, t)
return nearest_vector, np.linalg.norm(nearest_vector - t)
# 示例
np.random.seed(42)
basis = np.random.randint(1, 100, size=(5, 5))
target = np.random.rand(5) * 50
lll_nearest, lll_dist = cvp_lll_approx(basis, target)
print("LLL近似最近向量:", lll_nearest)
print("距離:", lll_dist)
6.5 CVP 問(wèn)題的應(yīng)用
6.5.1 糾錯(cuò)碼譯碼
CVP 問(wèn)題對(duì)應(yīng)于線性碼的最大似然譯碼問(wèn)題。在通信系統(tǒng)中,接收端收到的信號(hào)可以看作是目標(biāo)向量,而所有可能的發(fā)送信號(hào)構(gòu)成一個(gè)格。
6.5.2 密碼分析
GGH 密碼體制的攻擊:
GGH 密碼體制的安全性基于 CVP 問(wèn)題的困難性。攻擊者可以通過(guò)求解 CVP 問(wèn)題來(lái)恢復(fù)明文。
攻擊算法:
def attack_ggh_ciphertext(B_pub, c):
"""攻擊GGH密碼體制的密文"""
# GGH密文c = B_pub \* m + e,其中m是明文,e是小錯(cuò)誤向量
# 攻擊思路:求解CVP問(wèn)題找到m + e,然后恢復(fù)m
# 由于e是小向量,m + e接近格點(diǎn)
m_plus_e, _ = sphere_decoding(B_pub, c)
# 恢復(fù)明文m(假設(shè)e是小向量,這里簡(jiǎn)化處理)
m = np.round(m_plus_e).astype(np.int64)
return m
# 示例
np.random.seed(42)
n = 3
B_priv = np.array(\[\[1, 0, 0], \[0, 1, 0], \[0, 0, 1]]) # 私鑰(好基)
U = np.array(\[\[1, 2, 3], \[4, 5, 6], \[7, 8, 10]]) # 幺模矩陣
B_pub = B_priv @ U # 公鑰(壞基)
m = np.array(\[1, 2, 3]) # 明文
e = np.array(\[0.1, -0.2, 0.3]) # 小錯(cuò)誤向量
c = B_pub @ m + e # 密文
recovered_m = attack_ggh_ciphertext(B_pub, c)
print("原始明文:", m)
print("恢復(fù)明文:", recovered_m)
print("是否正確:", np.array_equal(m, recovered_m))
7. SIVP 最短獨(dú)立向量問(wèn)題研究
7.1 SIVP 問(wèn)題的嚴(yán)格定義
定義 7.1(最短獨(dú)立向量問(wèn)題 SIVP):
給定格\(\mathcal{L}\),尋找\(n\)個(gè)線性無(wú)關(guān)的格向量\(u_1, u_2, \ldots, u_n\),使得每個(gè)向量的長(zhǎng)度都不超過(guò)\(\gamma \cdot \lambda_n(\mathcal{L})\),其中\(\lambda_n(\mathcal{L})\)是第\(n\)個(gè)連續(xù)最小長(zhǎng)度。
精確 SIVP:
當(dāng)\(\gamma = 1\)時(shí),問(wèn)題稱為精確 SIVP,要求找到\(n\)個(gè)線性無(wú)關(guān)的格向量,其中最長(zhǎng)向量的長(zhǎng)度等于\(\lambda_n(\mathcal{L})\)。
7.2 SIVP 與其他格問(wèn)題的關(guān)系
7.2.1 SIVP 與 SVP 的關(guān)系
定理 7.1:SVP 可以多項(xiàng)式時(shí)間歸約到 SIVP。
證明概要:
如果能夠求解 SIVP 問(wèn)題,那么可以通過(guò)以下步驟求解 SVP 問(wèn)題:
-
求解 SIVP 問(wèn)題得到\(n\)個(gè)線性無(wú)關(guān)的短向量
-
在這些向量中找到最短的一個(gè),即為 SVP 問(wèn)題的解
推論:SIVP 至少與 SVP 一樣困難。
7.2.2 SIVP 與 CVP 的關(guān)系
定理 7.2:CVP 可以多項(xiàng)式時(shí)間歸約到 SIVP。
證明概要:
給定 CVP 實(shí)例\((\mathcal{L}, t)\),可以構(gòu)造新的格\(\mathcal{L}' = \mathcal{L} \oplus \mathbb{Z}\),然后求解 SIVP 問(wèn)題來(lái)找到 CVP 的解。
7.3 SIVP 求解算法
7.3.1 基于 LLL 的算法
算法 7.1(基于 LLL 的 SIVP 近似求解):
def sivp_lll_approx(B):
"""基于LLL算法的SIVP近似求解"""
reduced_basis = lll_reduction(B)
return reduced_basis
# 示例
np.random.seed(42)
basis = np.random.randint(1, 100, size=(5, 5))
print("原始基:")
print(basis)
sivp_vectors = sivp_lll_approx(basis)
print("\nSIVP近似解(LLL約化基):")
print(sivp_vectors)
print("\n向量長(zhǎng)度:", \[np.linalg.norm(col) for col in sivp_vectors.T])
7.3.2 基于 BKZ 的算法
算法 7.2(基于 BKZ 的 SIVP 近似求解):
def sivp_bkz_approx(B, block_size=20):
"""基于BKZ算法的SIVP近似求解"""
reduced_basis = bkz_reduction(B, block_size=block_size)
return reduced_basis
# 示例
basis = np.random.randint(1, 100, size=(5, 5))
bkz_vectors = sivp_bkz_approx(basis, block_size=3)
print("BKZ約化基:")
print(bkz_vectors)
print("\n向量長(zhǎng)度:", \[np.linalg.norm(col) for col in bkz_vectors.T])
7.4 SIVP 在密碼學(xué)中的應(yīng)用
7.4.1 GPV08 陷門函數(shù)
背景:
2008 年,Gentry、Peikert 和 Vaikuntanathan 提出了基于 SIVP 困難性的陷門函數(shù)構(gòu)造,這是格密碼學(xué)中的重要突破。
構(gòu)造原理:
-
生成一個(gè)困難的格實(shí)例\(\mathcal{L}\)
-
嵌入一個(gè) "陷門"\(T\),使得擁有陷門的人可以高效求解 SIVP 問(wèn)題
-
陷門的安全性基于 SIVP 問(wèn)題的困難性
算法 7.3(GPV08 陷門函數(shù)構(gòu)造):
def generate_gpv_trapdoor(n=512, q=8192, sigma=3.2):
"""生成GPV08陷門函數(shù)"""
rng = np.random.default_rng()
# 生成隨機(jī)矩陣A
A = rng.integers(0, q, size=(n, n), dtype=np.int64)
# 生成陷門矩陣T(通常是一個(gè)好基)
T = rng.normal(0, sigma, size=(n, n)).round().astype(np.int64) % q
# 確保T是可逆的
while np.linalg.det(T) % q == 0:
T = rng.normal(0, sigma, size=(n, n)).round().astype(np.int64) % q
# 計(jì)算公鑰矩陣B = A \* T^{-1} mod q
T_inv = np.linalg.inv(T)
T_inv_mod_q = np.round(T_inv \* q).astype(np.int64) % q # 簡(jiǎn)化的模逆計(jì)算
B = (A @ T_inv_mod_q) % q
return (A, B), T # (公鑰, 私鑰/陷門)
def gpv_sign(private_key, message, n=512, q=8192):
"""GPV簽名算法"""
T = private_key
# 將消息哈希到格點(diǎn)
hash_val = hash(message)
rng = np.random.default_rng(hash_val)
c = rng.integers(0, q, size=n, dtype=np.int64)
# 使用陷門求解SIVP問(wèn)題
# 簡(jiǎn)化版本:直接使用T的列向量作為簽名
signature = T @ c % q
return signature
def gpv_verify(public_key, message, signature, n=512, q=8192):
"""GPV驗(yàn)證算法"""
A, B = public_key
# 驗(yàn)證 A \* signature ≡ B \* c mod q
hash_val = hash(message)
rng = np.random.default_rng(hash_val)
c = rng.integers(0, q, size=n, dtype=np.int64)
lhs = (A @ signature) % q
rhs = (B @ c) % q
return np.array_equal(lhs, rhs)
# 示例(使用小參數(shù))
public_key, private_key = generate_gpv_trapdoor(n=4, q=16)
message = "Hello, GPV Trapdoor!"
signature = gpv_sign(private_key, message, n=4, q=16)
is_valid = gpv_verify(public_key, message, signature, n=4, q=16)
print("消息:", message)
print("簽名:", signature)
print("驗(yàn)證結(jié)果:", is_valid)
7.4.2 全同態(tài)加密
背景:
全同態(tài)加密(FHE)允許對(duì)加密數(shù)據(jù)進(jìn)行任意計(jì)算,而不需要先解密。格密碼為實(shí)現(xiàn) FHE 提供了理論基礎(chǔ)。
基于 SIVP 的 FHE 構(gòu)造:
Gentry 的第一個(gè) FHE 方案基于理想格上的 SIVP 困難性。該方案通過(guò)以下關(guān)鍵技術(shù)實(shí)現(xiàn)全同態(tài)加密:
-
密鑰切換:在不同的密鑰之間轉(zhuǎn)換密文
-
模切換:調(diào)整密文的模數(shù)以控制噪聲增長(zhǎng)
-
引導(dǎo):通過(guò)解密電路對(duì)密文進(jìn)行 "刷新",減少噪聲積累
7.5 SIVP 問(wèn)題的復(fù)雜性分析
7.5.1 計(jì)算復(fù)雜性
定理 7.3:精確 SIVP 問(wèn)題是 NP 困難的。
定理 7.4:對(duì)于任意常數(shù)\(\gamma \geq 1\),\(\gamma\)- 近似 SIVP 問(wèn)題是 NP 困難的。
7.5.2 與其他問(wèn)題的比較
| 問(wèn)題 | 復(fù)雜性 | 應(yīng)用 |
|---|---|---|
| SVP | NP 困難 | 格密碼安全性基礎(chǔ) |
| CVP | NP 困難 | 糾錯(cuò)碼、密碼分析 |
| SIVP | NP 困難 | 陷門函數(shù)、FHE |
| LWE | 平均情況困難 | 現(xiàn)代格密碼基礎(chǔ) |
8. LWE 問(wèn)題及密碼學(xué)應(yīng)用
8.1 LWE 問(wèn)題的嚴(yán)格定義
定義 8.1(帶錯(cuò)誤學(xué)習(xí)問(wèn)題 LWE):
給定正整數(shù)\(n, q\),錯(cuò)誤分布\(\chi\),以及\(m\)個(gè)樣本\((a_i, b_i) \in \mathbb{Z}_q^n \times \mathbb{Z}_q\),其中:
\(b_i = \langle a_i, s \rangle + e_i \mod q\)
其中\(s \in \mathbb{Z}_q^n\)是秘密向量,\(e_i \in \mathbb{Z}_q\)是從\(\chi\)中采樣的錯(cuò)誤項(xiàng)。目標(biāo)是恢復(fù)秘密向量\(s\)。
8.2 LWE 問(wèn)題的變體
8.2.1 搜索型 vs 判定型 LWE
搜索型 LWE:
從樣本中恢復(fù)秘密向量\(s\)。
判定型 LWE:
區(qū)分 LWE 樣本與均勻隨機(jī)樣本。
定理 8.1:搜索型 LWE 和判定型 LWE 在多項(xiàng)式時(shí)間內(nèi)等價(jià)。
8.2.2 Ring-LWE
定義 8.2(Ring-LWE):
在多項(xiàng)式環(huán)\(R = \mathbb{Z}[x]/(x^n + 1)\)上定義的 LWE 問(wèn)題。
優(yōu)勢(shì):
-
密鑰長(zhǎng)度更短
-
計(jì)算效率更高
-
適合硬件實(shí)現(xiàn)
8.2.3 Module-LWE
定義 8.3(Module-LWE):
在模\(M_{n \times k}(R)\)上定義的 LWE 問(wèn)題,是 LWE 和 Ring-LWE 的中間形式。
優(yōu)勢(shì):
-
提供更好的安全性
-
保持較好的效率
-
是 NIST 后量子密碼標(biāo)準(zhǔn)的基礎(chǔ)
8.3 LWE 問(wèn)題的困難性
8.3.1 Regev 歸約
定理 8.2(Regev 2005):
LWE 問(wèn)題的平均情況困難性可以歸約到格上的最壞情況困難問(wèn)題(如 GapSVP 和 SIVP)。
歸約過(guò)程:
-
從格上的最壞情況困難問(wèn)題開(kāi)始
-
構(gòu)造對(duì)應(yīng)的 LWE 實(shí)例
-
證明如果 LWE 實(shí)例容易解決,則原始格問(wèn)題也容易解決
重要意義:
-
為格密碼提供了堅(jiān)實(shí)的安全性基礎(chǔ)
-
確保了格密碼方案的抗量子安全性
-
使得格密碼可以實(shí)際應(yīng)用
8.3.2 量子歸約
定理 8.3(Regev 2009):
存在量子多項(xiàng)式時(shí)間算法將格上的最壞情況困難問(wèn)題歸約到 LWE 問(wèn)題。
8.4 基于 LWE 的加密方案
8.4.1 Regev 加密方案
算法 8.1(Regev 加密方案):
密鑰生成:
def regev_keygen(n=512, q=8192, sigma=3.2):
"""Regev加密方案密鑰生成"""
rng = np.random.default_rng()
# 生成公鑰矩陣A
A = rng.integers(0, q, size=(n, n), dtype=np.int64)
# 生成秘密向量s
s = rng.normal(0, sigma, n).round().astype(np.int64) % q
# 生成錯(cuò)誤向量e
e = rng.normal(0, sigma, n).round().astype(np.int64) % q
# 計(jì)算公鑰向量b
b = (A.T @ s + e) % q
return (A, b), s
加密:
def regev_encrypt(public_key, message, n=512, q=8192):
"""Regev加密"""
A, b = public_key
rng = np.random.default_rng()
# 將明文編碼為{0, 1} -> {0, q/2}
m_encoded = message \* (q // 2)
# 生成隨機(jī)向量x(小 Hamming 重量)
x = np.zeros(n, dtype=np.int64)
x[:n//10] = 1 # 10%的非零元素
rng.shuffle(x)
# 計(jì)算密文
c1 = (A @ x) % q
c2 = (b.T @ x + m_encoded) % q
return (c1, c2)
解密:
def regev_decrypt(private_key, ciphertext, n=512, q=8192):
"""Regev解密"""
s = private_key
c1, c2 = ciphertext
# 計(jì)算明文
m_prime = (c2 - s.T @ c1) % q
# 解碼明文
if m_prime < q // 4 or m_prime > 3 \* q // 4:
return 0
else:
return 1
# 示例
public_key, private_key = regev_keygen(n=64, q=256)
message = 1
print("原始消息:", message)
ciphertext = regev_encrypt(public_key, message, n=64, q=256)
print("密文c1長(zhǎng)度:", len(ciphertext\[0]))
print("密文c2:", ciphertext\[1])
decrypted = regev_decrypt(private_key, ciphertext, n=64, q=256)
print("解密消息:", decrypted)
8.4.2 Ring-LWE 加密方案
算法 8.2(Ring-LWE 加密方案):
def polynomial_mult(a, b, n, q):
"""多項(xiàng)式乘法模(x^n + 1)和q"""
result = np.zeros(n, dtype=np.int64)
for i in range(n):
if a[i] == 0:
continue
for j in range(n):
if b[j] == 0:
continue
k = (i + j) % n
sign = (-1) \*\* ((i + j) // n) # 因?yàn)閤^n ≡ -1
result[k] = (result[k] + a[i] \* b[j] \* sign) % q
return result
def ring_lwe_keygen(n=256, q=8192, sigma=3.2):
"""Ring-LWE密鑰生成"""
rng = np.random.default_rng()
# 生成多項(xiàng)式環(huán)元素a
a = rng.integers(0, q, size=n, dtype=np.int64)
# 生成秘密多項(xiàng)式s
s = rng.normal(0, sigma, n).round().astype(np.int64) % q
# 生成錯(cuò)誤多項(xiàng)式e
e = rng.normal(0, sigma, n).round().astype(np.int64) % q
# 計(jì)算公鑰多項(xiàng)式b = a \* s + e mod q
b = polynomial_mult(a, s, n, q)
b = (b + e) % q
return (a, b), s
def ring_lwe_encrypt(public_key, message, n=256, q=8192):
"""Ring-LWE加密"""
a, b = public_key
rng = np.random.default_rng()
# 編碼明文
m_encoded = np.zeros(n, dtype=np.int64)
m_encoded[0] = message \* (q // 2)
# 生成隨機(jī)多項(xiàng)式r
r = rng.normal(0, 1.58, n).round().astype(np.int64) % q
# 生成錯(cuò)誤多項(xiàng)式e1, e2
e1 = rng.normal(0, 1.58, n).round().astype(np.int64) % q
e2 = rng.normal(0, 1.58, n).round().astype(np.int64) % q
# 計(jì)算密文
c1 = (polynomial_mult(a, r, n, q) + e1) % q
c2 = (polynomial_mult(b, r, n, q) + e2 + m_encoded) % q
return (c1, c2)
def ring_lwe_decrypt(private_key, ciphertext, n=256, q=8192):
"""Ring-LWE解密"""
s = private_key
c1, c2 = ciphertext
# 計(jì)算明文
m_prime = (c2 - polynomial_mult(c1, s, n, q)) % q
# 解碼明文
if m_prime[0] < q // 4 or m_prime[0] > 3 \* q // 4:
return 0
else:
return 1
# 示例(使用小參數(shù))
public_key, private_key = ring_lwe_keygen(n=16, q=256)
message = 1
print("原始消息:", message)
ciphertext = ring_lwe_encrypt(public_key, message, n=16, q=256)
print("密文c1前5個(gè)系數(shù):", ciphertext\[0]\[:5])
print("密文c2前5個(gè)系數(shù):", ciphertext\[1]\[:5])
decrypted = ring_lwe_decrypt(private_key, ciphertext, n=16, q=256)
print("解密消息:", decrypted)
8.5 LWE 問(wèn)題的應(yīng)用
8.5.1 密鑰交換協(xié)議
CRYSTALS-Kyber:
基于 Module-LWE 的密鑰封裝機(jī)制,被 NIST 選為后量子密碼標(biāo)準(zhǔn)。
算法 8.3(簡(jiǎn)化版 Kyber):
def kyber_keygen(n=256, q=3329, k=2):
"""簡(jiǎn)化版Kyber密鑰生成"""
rng = np.random.default_rng()
# 生成矩陣A
A = rng.integers(0, q, size=(k\*n, k\*n), dtype=np.int64)
# 生成秘密多項(xiàng)式向量s
s = rng.normal(0, 1.58, size=(k\*n)).round().astype(np.int64) % q
# 生成錯(cuò)誤多項(xiàng)式向量e
e = rng.normal(0, 1.58, size=(k\*n)).round().astype(np.int64) % q
# 計(jì)算公鑰
t = (A @ s + e) % q
return (A, t), s
def kyber_encaps(public_key, n=256, q=3329, k=2):
"""簡(jiǎn)化版Kyber封裝"""
A, t = public_key
rng = np.random.default_rng()
# 生成隨機(jī)向量r
r = rng.normal(0, 1.58, size=(k\*n)).round().astype(np.int64) % q
# 生成錯(cuò)誤向量e1, e2
e1 = rng.normal(0, 1.58, size=(k\*n)).round().astype(np.int64) % q
e2 = rng.normal(0, 1.58, size=(k\*n)).round().astype(np.int64) % q
# 計(jì)算密文
u = (A.T @ r + e1) % q
v = (t.T @ r + e2) % q
# 生成會(huì)話密鑰(簡(jiǎn)化版)
session_key = hash(str(v))
return (u, v), session_key
def kyber_decaps(private_key, ciphertext, n=256, q=3329, k=2):
"""簡(jiǎn)化版Kyber解封裝"""
s = private_key
u, v = ciphertext
# 恢復(fù)會(huì)話密鑰
v_prime = (s.T @ u) % q
session_key = hash(str(v_prime))
return session_key
# 示例
public_key, private_key = kyber_keygen(n=32, q=256, k=1)
ciphertext, session_key = kyber_encaps(public_key, n=32, q=256, k=1)
recovered_key = kyber_decaps(private_key, ciphertext, n=32, q=256, k=1)
print("會(huì)話密鑰是否一致:", session_key == recovered_key)
print("會(huì)話密鑰示例:", session_key[:10], "...")
8.5.2 數(shù)字簽名
CRYSTALS-Dilithium:
基于 Module-LWE 的數(shù)字簽名方案,被 NIST 選為標(biāo)準(zhǔn)。
算法 8.4(簡(jiǎn)化版 Dilithium):
def dilithium_keygen(n=256, q=8380417, k=3, l=2):
"""簡(jiǎn)化版Dilithium密鑰生成"""
rng = np.random.default_rng()
# 生成矩陣A
A = rng.integers(0, q, size=(k\*n, l\*n), dtype=np.int64)
# 生成秘密多項(xiàng)式向量s1, s2
s1 = rng.normal(0, 1.58, size=(l\*n)).round().astype(np.int64) % q
s2 = rng.normal(0, 1.58, size=(k\*n)).round().astype(np.int64) % q
# 生成錯(cuò)誤多項(xiàng)式向量e
e = rng.normal(0, 1.58, size=(k\*n)).round().astype(np.int64) % q
# 計(jì)算公鑰
t = (A @ s1 + e) % q
return (A, t), (s1, s2)
def dilithium_sign(private_key, message, n=256, q=8380417, k=3, l=2):
"""簡(jiǎn)化版Dilithium簽名"""
s1, s2 = private_key
rng = np.random.default_rng()
# 生成隨機(jī)向量y
y = rng.normal(0, 1.58, size=(l\*n)).round().astype(np.int64) % q
# 計(jì)算w = A @ y mod q
w = (A @ y) % q
# 壓縮w得到c
c = hash(str(w) + message) % q
# 計(jì)算簽名z = y + c \* s1 mod q
z = (y + c \* s1) % q
# 計(jì)算h = w - c \* t mod q
h = (w - c \* t) % q
return (z, h, c)
def dilithium_verify(public_key, message, signature, n=256, q=8380417, k=3, l=2):
"""簡(jiǎn)化版Dilithium驗(yàn)證"""
A, t = public_key
z, h, c = signature
# 驗(yàn)證A @ z - c \* t ≡ h mod q
lhs = (A @ z - c \* t) % q
rhs = h % q
# 驗(yàn)證c的正確性
expected_c = hash(str(h) + message) % q
return np.array_equal(lhs, rhs) and c == expected_c
# 全局變量(僅示例用)
A = None
t = None
# 示例
public_key, private_key = dilithium_keygen(n=32, q=256, k=1, l=1)
A, t = public_key
message = "Hello, Dilithium!"
signature = dilithium_sign(private_key, message, n=32, q=256, k=1, l=1)
is_valid = dilithium_verify(public_key, message, signature, n=32, q=256, k=1, l=1)
print("消息:", message)
print("簽名驗(yàn)證結(jié)果:", is_valid)
9. 格密碼的構(gòu)造原理與實(shí)現(xiàn)
9.1 格密碼的通用設(shè)計(jì)原理
9.1.1 陷門機(jī)制
基本思想:
格密碼系統(tǒng)的構(gòu)造核心是基于格基質(zhì)量差異的 "單向陷門" 機(jī)制。
"好基" 與 "壞基":
-
好基:向量較短且接近正交,使得求解格問(wèn)題相對(duì)容易
-
壞基:向量較長(zhǎng)且高度相關(guān),使得求解格問(wèn)題計(jì)算困難
陷門構(gòu)造:
-
生成一個(gè)困難的格實(shí)例
-
嵌入一個(gè) "陷門"(通常是一個(gè)好基)
-
公開(kāi)壞基作為公鑰
-
私鑰持有者可以利用陷門高效求解格問(wèn)題
9.1.2 平均情況到最壞情況的歸約
定義 9.1(平均情況到最壞情況的歸約):
如果存在一個(gè)多項(xiàng)式時(shí)間算法能夠破解格密碼方案的某個(gè) "平均情況" 實(shí)例,那么就可以利用這個(gè)算法來(lái)解決格上某個(gè)核心難題的 "最壞情況" 實(shí)例。
重要意義:
-
為格密碼提供了最強(qiáng)的安全性保證
-
攻擊者面對(duì)的是平均情況的困難問(wèn)題
-
安全性不依賴于特定的隨機(jī)實(shí)例選擇
9.2 基于格的公鑰加密
9.2.1 通用構(gòu)造框架
算法 9.1(基于格的公鑰加密通用框架):
密鑰生成:
def lattice_pke_keygen(n, q, gen_good_basis, gen_bad_basis):
"""基于格的公鑰加密密鑰生成"""
# 生成好基(私鑰)
good_basis = gen_good_basis(n, q)
# 生成壞基(公鑰)
bad_basis = gen_bad_basis(good_basis, n, q)
return bad_basis, good_basis
加密:
def lattice_pke_encrypt(public_key, message, n, q, encode, embed):
"""基于格的公鑰加密"""
# 編碼明文
m_encoded = encode(message, q)
# 將明文嵌入到格中
ciphertext = embed(public_key, m_encoded, n, q)
return ciphertext
解密:
def lattice_pke_decrypt(private_key, ciphertext, n, q, extract, decode):
"""基于格的公鑰解密"""
# 從密文中提取編碼的明文
m_encoded = extract(private_key, ciphertext, n, q)
# 解碼明文
message = decode(m_encoded, q)
return message
9.2.2 具體實(shí)現(xiàn)示例
算法 9.2(基于 SIS 的公鑰加密):
def gen_sis_good_basis(n, q):
"""生成SIS問(wèn)題的好基(單位矩陣)"""
return np.eye(n, dtype=np.int64)
def gen_sis_bad_basis(good_basis, n, q):
"""生成SIS問(wèn)題的壞基"""
rng = np.random.default_rng()
# 生成隨機(jī)矩陣
R = rng.integers(0, q, size=(n, n), dtype=np.int64)
# 壞基 = 好基 \* R mod q
bad_basis = (good_basis @ R) % q
return bad_basis
def sis_encrypt(public_key, message, n, q):
"""SIS加密"""
A = public_key
rng = np.random.default_rng()
# 編碼明文:0 -> 0, 1 -> q/2
m = 0 if message == 0 else q // 2
# 生成小的隨機(jī)向量x
x = rng.integers(-1, 2, size=n, dtype=np.int64) # {-1, 0, 1}
# 計(jì)算密文:c = A^T x + m mod q
c = (A.T @ x + m) % q
return c
def sis_decrypt(private_key, ciphertext, n, q):
"""SIS解密"""
S = private_key
c = ciphertext
# 計(jì)算 m' = c - S^T (A^T x) mod q
# 由于 A = S R,所以 S^T A^T = R^T,因此 m' = c - R^T x mod q
# 簡(jiǎn)化版本:直接返回c的符號(hào)
m_prime = c % q
# 解碼明文
if m_prime < q // 4 or m_prime > 3 \* q // 4:
return 0
else:
return 1
# 示例
n = 8
q = 257
public_key, private_key = lattice_pke_keygen(n, q, gen_sis_good_basis, gen_sis_bad_basis)
message = 1
print("原始消息:", message)
ciphertext = sis_encrypt(public_key, message, n, q)
print("密文:", ciphertext)
decrypted = sis_decrypt(private_key, ciphertext, n, q)
print("解密消息:", decrypted)
9.3 基于格的數(shù)字簽名
9.3.1 哈希 - 然后 - 采樣范式
基本思想:
-
對(duì)消息進(jìn)行哈希,得到格上的一個(gè)點(diǎn)
-
使用陷門采樣器從格中采樣一個(gè)短向量作為簽名
-
驗(yàn)證者檢查簽名是否是格中的短向量且與消息哈希一致
9.3.2 BLISS 簽名方案
算法 9.3(簡(jiǎn)化版 BLISS 簽名):
def bliss_keygen(n=512, q=12289):
"""簡(jiǎn)化版BLISS密鑰生成"""
rng = np.random.default_rng()
# 生成多項(xiàng)式環(huán)元素a
a = rng.integers(0, q, size=n, dtype=np.int64)
# 生成秘密多項(xiàng)式s1, s2
s1 = rng.normal(0, 1.0, n).round().astype(np.int64) % q
s2 = rng.normal(0, 1.0, n).round().astype(np.int64) % q
# 確保s1可逆
while np.gcd(np.sum(s1), q) != 1:
s1 = rng.normal(0, 1.0, n).round().astype(np.int64) % q
# 計(jì)算公鑰多項(xiàng)式t = a \* s1^{-1} + s2 mod q
# 簡(jiǎn)化計(jì)算:假設(shè)s1 = 1
t = (a + s2) % q
return (a, t), (s1, s2)
def bliss_sign(private_key, message, n=512, q=12289):
"""簡(jiǎn)化版BLISS簽名"""
s1, s2 = private_key
rng = np.random.default_rng()
# 哈希消息得到挑戰(zhàn)
hash_val = hash(message)
rng = np.random.default_rng(hash_val)
c = rng.integers(0, q, size=n, dtype=np.int64)
# 生成隨機(jī)多項(xiàng)式r
r = rng.normal(0, 1.0, n).round().astype(np.int64) % q
# 計(jì)算簽名
e1 = (r + c \* s1) % q
e2 = (polynomial_mult(a, r, n, q) + c \* s2) % q
return (e1, e2)
def bliss_verify(public_key, message, signature, n=512, q=12289):
"""簡(jiǎn)化版BLISS驗(yàn)證"""
a, t = public_key
e1, e2 = signature
# 哈希消息得到挑戰(zhàn)
hash_val = hash(message)
rng = np.random.default_rng(hash_val)
c = rng.integers(0, q, size=n, dtype=np.int64)
# 驗(yàn)證 e2 ≡ a \* e1 - c \* t mod q
lhs = e2 % q
rhs = (polynomial_mult(a, e1, n, q) - c \* t) % q
# 檢查簽名長(zhǎng)度
e1_norm = np.linalg.norm(e1)
e2_norm = np.linalg.norm(e2)
return np.array\_equal(lhs, rhs) and e1\_norm < 3\*np.sqrt(n) and e2\_norm < 3\*np.sqrt(n)
# 全局變量(僅示例用)
a = None
# 示例
public_key, private_key = bliss_keygen(n=16, q=257)
a, t = public_key
message = "Hello, BLISS!"
signature = bliss_sign(private_key, message, n=16, q=257)
is_valid = bliss_verify(public_key, message, signature, n=16, q=257)
print("消息:", message)
print("簽名驗(yàn)證結(jié)果:", is_valid)
9.4 格密碼的安全性分析
9.4.1 抗量子安全性
定理 9.2:
目前已知的量子算法對(duì)格問(wèn)題沒(méi)有多項(xiàng)式時(shí)間的求解算法。
證據(jù):
-
Shor 算法不能有效解決格問(wèn)題
-
格問(wèn)題的量子算法復(fù)雜度仍然是指數(shù)級(jí)
-
格密碼被認(rèn)為是抗量子的
9.4.2 側(cè)信道攻擊防御
常見(jiàn)攻擊:
-
計(jì)時(shí)攻擊
-
功耗分析
-
故障注入攻擊
防御措施:
def constant_time_add(a, b, q):
"""常數(shù)時(shí)間加法"""
result = (a + b) % q
# 確保操作時(shí)間不依賴于輸入值
dummy = np.random.randint(0, q)
result = (result + dummy) % q
result = (result - dummy) % q
return result
def masked_mult(a, b, mask, q):
"""掩碼乘法"""
# 應(yīng)用掩碼
a_masked = (a + mask) % q
b_masked = (b + mask) % q
# 計(jì)算乘積
product = (a_masked \* b_masked) % q
# 移除掩碼
result = (product - a \* mask - b \* mask - mask \* mask) % q
return result
# 示例
q = 257
a = 123
b = 45
mask = 78
# 普通乘法
normal_result = (a \* b) % q
# 掩碼乘法
masked_result = masked_mult(a, b, mask, q)
print("普通乘法結(jié)果:", normal_result)
print("掩碼乘法結(jié)果:", masked_result)
print("結(jié)果是否一致:", normal_result == masked_result)
10. NIST 后量子密碼標(biāo)準(zhǔn)詳解
10.1 標(biāo)準(zhǔn)化進(jìn)程概述
10.1.1 標(biāo)準(zhǔn)化背景
量子威脅:
Shor 算法能夠在多項(xiàng)式時(shí)間內(nèi)解決大數(shù)分解和離散對(duì)數(shù)問(wèn)題,威脅現(xiàn)有密碼體系的安全。
標(biāo)準(zhǔn)化目標(biāo):
開(kāi)發(fā)能夠抵御量子計(jì)算機(jī)攻擊的新一代密碼算法標(biāo)準(zhǔn)。
10.1.2 標(biāo)準(zhǔn)化時(shí)間線
| 時(shí)間 | 事件 | 意義 |
|---|---|---|
| 2016 年 12 月 | NIST 發(fā)布后量子密碼標(biāo)準(zhǔn)化請(qǐng)求 | 啟動(dòng)標(biāo)準(zhǔn)化進(jìn)程 |
| 2017 年 11 月 | 收到 69 個(gè)候選算法 | 廣泛征集全球方案 |
| 2019 年 1 月 | 23 個(gè)算法進(jìn)入第二輪評(píng)估 | 初步篩選 |
| 2020 年 7 月 | 15 個(gè)算法進(jìn)入第三輪評(píng)估 | 深入評(píng)估 |
| 2022 年 7 月 | 宣布四個(gè)算法為標(biāo)準(zhǔn)化候選 | 確定最終候選 |
| 2024 年 2 月 | 發(fā)布 FIPS 203、204、205 標(biāo)準(zhǔn) | 正式標(biāo)準(zhǔn)化 |
10.2 CRYSTALS-Kyber 詳解
10.2.1 算法概述
CRYSTALS-Kyber是基于 Module-LWE 的密鑰封裝機(jī)制,被 NIST 選為后量子時(shí)代的標(biāo)準(zhǔn)密鑰封裝算法。
主要特點(diǎn):
-
安全性基于 Module-LWE 問(wèn)題的困難性
-
密鑰長(zhǎng)度適中(公鑰約 1KB,私鑰約 2KB)
-
計(jì)算效率高,適合實(shí)際部署
10.2.2 算法參數(shù)
標(biāo)準(zhǔn)化參數(shù)集:
| 參數(shù)集 | 安全等級(jí) | n | k | q | 公鑰大小 | 私鑰大小 | 密文大小 |
|---|---|---|---|---|---|---|---|
| Kyber-512 | 128 位 | 256 | 2 | 3329 | 800 字節(jié) | 1632 字節(jié) | 768 字節(jié) |
| Kyber-768 | 192 位 | 256 | 3 | 3329 | 1184 字節(jié) | 2400 字節(jié) | 1088 字節(jié) |
| Kyber-1024 | 256 位 | 256 | 4 | 3329 | 1568 字節(jié) | 3168 字節(jié) | 1536 字節(jié) |
10.2.3 完整實(shí)現(xiàn)
class Kyber:
def __init__(self, params='kyber768'):
"""初始化Kyber參數(shù)"""
param_sets = {
'kyber512': {'n': 256, 'k': 2, 'q': 3329, 'du': 10, 'dv': 4},
'kyber768': {'n': 256, 'k': 2, 'q': 3329, 'du': 10, 'dv': 4}, # 實(shí)際k=3,簡(jiǎn)化為k=2
'kyber1024': {'n': 256, 'k': 4, 'q': 3329, 'du': 11, 'dv': 5}
}
self.params = param_sets[params]
self.n = self.params['n']
self.k = self.params['k']
self.q = self.params['q']
self.du = self.params['du']
self.dv = self.params['dv']
def poly_getnoise(self, eta, n):
"""生成多項(xiàng)式噪聲"""
rng = np.random.default_rng()
return rng.normal(0, eta, n).round().astype(np.int64) % self.q
def poly_mult(self, a, b):
"""多項(xiàng)式乘法模(x^n + 1)和q"""
result = np.zeros(self.n, dtype=np.int64)
for i in range(self.n):
if a[i] == 0:
continue
for j in range(self.n):
if b[j] == 0:
continue
k = (i + j) % self.n
sign = (-1) \*\* ((i + j) // self.n)
result[k] = (result[k] + a[i] \* b[j] \* sign) % self.q
return result
def matrix_mult(self, A, b):
"""矩陣-向量乘法"""
result = np.zeros(self.k \* self.n, dtype=np.int64)
for i in range(self.k):
for j in range(self.k):
result[i\*self.n : (i+1)\*self.n] = (
result[i\*self.n : (i+1)\*self.n] +
self.poly_mult(A\[i\*self.n : (i+1)\*self.n, j\*self.n : (j+1)\*self.n],
b\[j\*self.n : (j+1)\*self.n])
) % self.q
return result
def keygen(self):
"""密鑰生成"""
rng = np.random.default_rng()
# 生成矩陣A
A = rng.integers(0, self.q, size=(self.k\*self.n, self.k\*self.n), dtype=np.int64)
# 生成秘密向量s
s = np.zeros(self.k\*self.n, dtype=np.int64)
for i in range(self.k):
s[i\*self.n : (i+1)\*self.n] = self.poly_getnoise(1.58, self.n)
# 生成錯(cuò)誤向量e
e = np.zeros(self.k\*self.n, dtype=np.int64)
for i in range(self.k):
e[i\*self.n : (i+1)\*self.n] = self.poly_getnoise(1.58, self.n)
# 計(jì)算公鑰t = A \* s + e
t = self.matrix_mult(A, s)
t = (t + e) % self.q
return (A, t), s
def encaps(self, pk):
"""封裝"""
A, t = pk
rng = np.random.default_rng()
# 生成隨機(jī)向量r
r = np.zeros(self.k\*self.n, dtype=np.int64)
for i in range(self.k):
r[i\*self.n : (i+1)\*self.n] = self.poly\_getnoise(1.58, self.n)
# 生成錯(cuò)誤向量e1, e2
e1 = np.zeros(self.k\*self.n, dtype=np.int64)
for i in range(self.k):
e1[i\*self.n : (i+1)\*self.n] = self.poly_getnoise(1.58, self.n)
e2 = np.zeros(self.k\*self.n, dtype=np.int64)
for i in range(self.k):
e2[i\*self.n : (i+1)\*self.n] = self.poly_getnoise(1.58, self.n)
# 計(jì)算密文
u = self.matrix_mult(A.T, r)
u = (u + e1) % self.q
v = self.matrix_mult(t.T, r)
v = (v + e2) % self.q
# 生成會(huì)話密鑰
session_key = hash(str(v))
return (u, v), session_key
def decaps(self, sk, ct):
"""解封裝"""
s = sk
u, v = ct
# 恢復(fù)會(huì)話密鑰
v_prime = self.matrix_mult(s.T, u)
v_prime = v_prime % self.q
session_key = hash(str(v_prime))
return session_key
# 示例
kyber = Kyber('kyber512')
pk, sk = kyber.keygen()
ct, key = kyber.encaps(pk)
recovered_key = kyber.decaps(sk, ct)
print("Kyber示例:")
print("密鑰是否一致:", key == recovered_key)
print("公鑰大小:", pk[0].size + pk[1].size, "元素")
print("私鑰大小:", sk.size, "元素")
print("密文大小:", ct[0].size + ct[1].size, "元素")
10.3 CRYSTALS-Dilithium 詳解
10.3.1 算法概述
CRYSTALS-Dilithium是基于 Module-LWE 的數(shù)字簽名方案,被 NIST 選為標(biāo)準(zhǔn)。
主要特點(diǎn):
-
安全性基于 Module-LWE 問(wèn)題的困難性
-
簽名大小適中(約 2KB-4KB)
-
驗(yàn)證速度快,適合大規(guī)模應(yīng)用
10.3.2 算法參數(shù)
標(biāo)準(zhǔn)化參數(shù)集:
| 參數(shù)集 | 安全等級(jí) | n | k | l | q | 簽名大小 | 公鑰大小 | 私鑰大小 |
|---|---|---|---|---|---|---|---|---|
| Dilithium-2 | 128 位 | 256 | 3 | 2 | 8380417 | 2420 字節(jié) | 1312 字節(jié) | 2528 字節(jié) |
| Dilithium-3 | 192 位 | 256 | 4 | 3 | 8380417 | 3288 字節(jié) | 1696 字節(jié) | 3392 字節(jié) |
| Dilithium-5 | 256 位 | 256 | 5 | 4 | 8380417 | 4595 字節(jié) | 2080 字節(jié) | 4160 字節(jié) |
10.3.3 完整實(shí)現(xiàn)
class Dilithium:
def __init__(self, params='dilithium2'):
"""初始化Dilithium參數(shù)"""
param_sets = {
'dilithium2': {'n': 256, 'k': 3, 'l': 2, 'q': 8380417, 'eta': 2, 'gamma1': 1 << 17, 'gamma2': 1 << 15},
'dilithium3': {'n': 256, 'k': 4, 'l': 3, 'q': 8380417, 'eta': 2, 'gamma1': 1 << 17, 'gamma2': 1 << 15},
'dilithium5': {'n': 256, 'k': 5, 'l': 4, 'q': 8380417, 'eta': 2, 'gamma1': 1 << 17, 'gamma2': 1 << 15}
}
self.params = param_sets[params]
self.n = self.params['n']
self.k = self.params['k']
self.l = self.params['l']
self.q = self.params['q']
self.eta = self.params['eta']
self.gamma1 = self.params['gamma1']
self.gamma2 = self.params['gamma2']
def poly_getnoise(self, eta):
"""生成多項(xiàng)式噪聲"""
rng = np.random.default_rng()
return rng.normal(0, eta, self.n).round().astype(np.int64) % self.q
def poly_mult(self, a, b):
"""多項(xiàng)式乘法模(x^n + 1)和q"""
result = np.zeros(self.n, dtype=np.int64)
for i in range(self.n):
if a[i] == 0:
continue
for j in range(self.n):
if b[j] == 0:
continue
k = (i + j) % self.n
sign = (-1) \*\* ((i + j) // self.n)
result[k] = (result[k] + a[i] \* b[j] \* sign) % self.q
return result
def matrix_mult(self, A, b):
"""矩陣-向量乘法"""
result = np.zeros(self.k \* self.n, dtype=np.int64)
for i in range(self.k):
for j in range(self.l):
result[i\*self.n : (i+1)\*self.n] = (
result[i\*self.n : (i+1)\*self.n] +
self.poly_mult(A\[i\*self.n : (i+1)\*self.n, j\*self.n : (j+1)\*self.n],
b[j\*self.n : (j+1)\*self.n])
) % self.q
return result
def keygen(self):
"""密鑰生成"""
rng = np.random.default_rng()
# 生成矩陣A
A = rng.integers(0, self.q, size=(self.k\*self.n, self.l\*self.n), dtype=np.int64)
# 生成秘密向量s1, s2
s1 = np.zeros(self.l\*self.n, dtype=np.int64)
for i in range(self.l):
s1[i\*self.n : (i+1)\*self.n] = self.poly_getnoise(self.eta)
s2 = np.zeros(self.k\*self.n, dtype=np.int64)
for i in range(self.k):
s2[i\*self.n : (i+1)\*self.n] = self.poly_getnoise(self.eta)
# 生成錯(cuò)誤向量e
e = np.zeros(self.k\*self.n, dtype=np.int64)
for i in range(self.k):
e[i\*self.n : (i+1)\*self.n] = self.poly_getnoise(self.eta)
# 計(jì)算公鑰t = A \* s1 + e
t = self.matrix_mult(A, s1)
t = (t + e) % self.q
return (A, t), (s1, s2)
def sign(self, sk, message):
"""簽名"""
s1, s2 = sk
rng = np.random.default_rng()
# 生成隨機(jī)向量y
y = np.zeros(self.l\*self.n, dtype=np.int64)
for i in range(self.l):
y[i\*self.n : (i+1)\*self.n] = self.poly_getnoise(self.gamma1)
# 計(jì)算w = A \* y
w = self.matrix_mult(self.A, y)
# 壓縮w得到c
c = hash(str(w) + message) % self.q
# 計(jì)算簽名z = y + c \* s1
z = (y + c \* s1) % self.q
# 計(jì)算h = w - c \* self.t
h = (w - c \* self.t) % self.q
return (z, h, c)
def verify(self, pk, message, signature):
"""驗(yàn)證"""
A, t = pk
z, h, c = signature
# 驗(yàn)證A \* z - c \* t ≡ h mod q
lhs = self.matrix_mult(A, z)
lhs = (lhs - c \* t) % self.q
rhs = h % self.q
# 驗(yàn)證c的正確性
expected_c = hash(str(h) + message) % self.q
return np.array_equal(lhs, rhs) and c == expected_c
# 示例
dilithium = Dilithium('dilithium2')
pk, sk = dilithium.keygen()
dilithium.A, dilithium.t = pk # 為簽名方法設(shè)置A和t
message = "Hello, Dilithium!"
signature = dilithium.sign(sk, message)
is_valid = dilithium.verify(pk, message, signature)
print("Dilithium示例:")
print("消息:", message)
print("簽名驗(yàn)證結(jié)果:", is_valid)
print("簽名大小:", len(signature[0]) + len(signature[1]) + 1, "元素")
10.4 FALCON 詳解
10.4.1 算法概述
FALCON是基于 NTRU 格的數(shù)字簽名方案,被 NIST 選為標(biāo)準(zhǔn)。
主要特點(diǎn):
-
簽名尺寸小(約 600-1200 字節(jié))
-
基于 NTRU 格,效率高
-
適合帶寬受限的應(yīng)用
10.4.2 算法參數(shù)
標(biāo)準(zhǔn)化參數(shù)集:
| 參數(shù)集 | 安全等級(jí) | n | q | 簽名大小 | 公鑰大小 | 私鑰大小 |
|---|---|---|---|---|---|---|
| FALCON-512 | 128 位 | 512 | 12289 | 666 字節(jié) | 897 字節(jié) | 1793 字節(jié) |
| FALCON-1024 | 256 位 | 1024 | 12289 | 1280 字節(jié) | 1793 字節(jié) | 3585 字節(jié) |
11. 全同態(tài)加密與高級(jí)應(yīng)用
11.1 全同態(tài)加密概述
11.1.1 基本概念
定義 11.1(全同態(tài)加密 FHE):
全同態(tài)加密允許對(duì)加密數(shù)據(jù)進(jìn)行任意計(jì)算,而不需要先解密。
形式化定義:
一個(gè)全同態(tài)加密方案由以下算法組成:
-
\(\text{KeyGen}(\lambda)\):生成密鑰對(duì)\((pk, sk)\)
-
\(\text{Enc}(pk, m)\):使用公鑰\(pk\)加密明文\(m\)得到密文\(c\)
-
\(\text{Dec}(sk, c)\):使用私鑰\(sk\)解密密文\(c\)得到明文\(m\)
-
\(\text{Eval}(pk, f, c_1, \ldots, c_k)\):對(duì)密文\(c_1, \ldots, c_k\)應(yīng)用函數(shù)\(f\)得到新密文\(c\)
滿足正確性:\(\text{Dec}(sk, \text{Eval}(pk, f, \text{Enc}(pk, m_1), \ldots, \text{Enc}(pk, m_k))) = f(m_1, \ldots, m_k)\)
11.1.2 FHE 的發(fā)展歷程
| 年份 | 研究者 | 重要貢獻(xiàn) | 意義 |
|---|---|---|---|
| 2009 | Gentry | 提出第一個(gè) FHE 方案 | 實(shí)現(xiàn)密碼學(xué) "圣杯" |
| 2011 | Brakerski-Vaikuntanathan | 提出基于 Ring-LWE 的 FHE 方案 | 提高效率,實(shí)用性增強(qiáng) |
| 2012 | Brakerski-Fan-Vercauteren | 提出 BFV 方案 | 簡(jiǎn)化 bootstrapping 過(guò)程 |
| 2016 | Cheon-Kim-Kim-Song | 提出 CKKS 方案 | 支持實(shí)數(shù)運(yùn)算 |
| 2018 | Chillotti-Gama-Georgieva-Izabachène | 提出 TFHE 方案 | 快速完全同態(tài)加密 |
11.2 基于格的 FHE 方案
11.2.1 BFV 方案
**BFV(Brakerski-Fan-Vercauteren)** 方案是基于 Ring-LWE 的全同態(tài)加密方案。
算法 11.1(簡(jiǎn)化版 BFV):
class BFV:
def __init__(self, n=256, q=8192, t=2):
"""初始化BFV參數(shù)"""
self.n = n
self.q = q
self.t = t
self.poly_mod = np.array(\[1] + \[0]\*(n-1) + \[1]) # x^n + 1
def poly_mult(self, a, b):
"""多項(xiàng)式乘法模(x^n + 1)和q"""
result = np.zeros(self.n, dtype=np.int64)
for i in range(self.n):
if a[i] == 0:
continue
for j in range(self.n):
if b[j] == 0:
continue
k = (i + j) % self.n
sign = (-1) \*\* ((i + j) // self.n)
result[k] = (result[k] + a\[i] \* b\[j] \* sign) % self.q
return result
def keygen(self):
"""密鑰生成"""
rng = np.random.default_rng()
# 生成秘密密鑰s
s = rng.integers(0, 2, size=self.n, dtype=np.int64) # 二進(jìn)制秘密密鑰
# 生成公鑰a
a = rng.integers(0, self.q, size=self.n, dtype=np.int64)
# 生成錯(cuò)誤e
e = rng.normal(0, 1.58, self.n).round().astype(np.int64) % self.q
# 計(jì)算公鑰b = -a \* s + e mod q
b = (-self.poly_mult(a, s) + e) % self.q
return (a, b), s
def encrypt(self, pk, m):
"""加密"""
a, b = pk
rng = np.random.default_rng()
# 生成隨機(jī)多項(xiàng)式r
r = rng.integers(0, 2, size=self.n, dtype=np.int64)
# 生成錯(cuò)誤多項(xiàng)式e1, e2
e1 = rng.normal(0, 1.58, self.n).round().astype(np.int64) % self.q
e2 = rng.normal(0, 1.58, self.n).round().astype(np.int64) % self.q
# 計(jì)算密文
c1 = (self.poly_mult(a, r) + e1) % self.q
c2 = (self.poly_mult(b, r) + e2 + m \* (self.q // self.t)) % self.q
return (c1, c2)
def decrypt(self, sk, c):
"""解密"""
s = sk
c1, c2 = c
# 計(jì)算明文
m_prime = (c2 + self.poly_mult(c1, s)) % self.q
# 解碼明文
m = round(m_prime \* self.t / self.q) % self.t
return m
def add(self, c1, c2):
"""密文加法"""
return ((c1\[0] + c2\[0]) % self.q, (c1\[1] + c2\[1]) % self.q)
def multiply(self, c1, c2):
"""密文乘法(簡(jiǎn)化版)"""
# 實(shí)際的乘法需要更復(fù)雜的重線性化技術(shù)
return ((c1\[0] \* c2\[0]) % self.q, (c1\[1] \* c2\[1]) % self.q)
# 示例
bfv = BFV(n=16, q=256, t=2)
pk, sk = bfv.keygen()
# 加密兩個(gè)比特
m1 = 1
m2 = 0
c1 = bfv.encrypt(pk, m1)
c2 = bfv.encrypt(pk, m2)
# 密文加法
c_add = bfv.add(c1, c2)
m_add = bfv.decrypt(sk, c_add)
print("FHE示例:")
print(f"{m1} + {m2} = {m_add}")
# 密文乘法(簡(jiǎn)化版)
c_mul = bfv.multiply(c1, c2)
m_mul = bfv.decrypt(sk, c_mul)
print(f"{m1} \* {m2} = {m_mul}")
11.2.2 CKKS 方案
**CKKS(Cheon-Kim-Kim-Song)** 方案支持實(shí)數(shù)運(yùn)算,適合機(jī)器學(xué)習(xí)應(yīng)用。
主要特點(diǎn):
-
支持實(shí)數(shù)和復(fù)數(shù)運(yùn)算
-
提供近似同態(tài)加密
-
適合隱私保護(hù)機(jī)器學(xué)習(xí)
11.3 零知識(shí)證明系統(tǒng)
11.3.1 基本概念
定義 11.2(零知識(shí)證明 ZKP):
零知識(shí)證明允許一方向另一方證明某個(gè)陳述是正確的,而不泄露任何額外信息。
性質(zhì):
-
完備性:誠(chéng)實(shí)的證明者能夠說(shuō)服誠(chéng)實(shí)的驗(yàn)證者
-
可靠性:作弊的證明者不能欺騙誠(chéng)實(shí)的驗(yàn)證者
-
零知識(shí)性:驗(yàn)證者除了知道陳述為真外,得不到任何其他信息
11.3.2 基于格的零知識(shí)證明
算法 11.2(格基零知識(shí)證明):
class LatticeZKP:
def __init__(self, n=256, q=8192):
"""初始化參數(shù)"""
self.n = n
self.q = q
def keygen(self):
"""生成證明者密鑰"""
rng = np.random.default_rng()
# 生成好基(證明者私有)
good_basis = rng.normal(0, 1.0, size=(self.n, self.n)).round().astype(np.int64) % self.q
# 生成壞基(公開(kāi))
U = rng.integers(0, self.q, size=(self.n, self.n), dtype=np.int64)
bad_basis = (good_basis @ U) % self.q
return bad_basis, good_basis
def prove(self, secret_basis, x):
"""證明x在格中"""
rng = np.random.default_rng()
# 生成隨機(jī)偏移r
r = rng.integers(-2, 3, size=self.n, dtype=np.int64) # {-2, -1, 0, 1, 2}
# 計(jì)算承諾a = secret_basis \* r
a = (secret_basis @ r) % self.q
# 生成挑戰(zhàn)e
e = rng.integers(0, self.q, dtype=np.int64)
# 計(jì)算響應(yīng)z = r + e \* x
z = (r + e \* x) % self.q
return (a, e, z)
def verify(self, public_basis, x, proof):
"""驗(yàn)證證明"""
a, e, z = proof
# 驗(yàn)證 public_basis \* z ≡ a + e \* x mod q
lhs = (public_basis @ z) % self.q
rhs = (a + e \* x) % self.q
return np.array_equal(lhs, rhs)
# 示例
zkp = LatticeZKP(n=4, q=257)
public_basis, secret_basis = zkp.keygen()
# 證明者知道x在格中
x = np.array(\[1, 2, 3, 4], dtype=np.int64)
proof = zkp.prove(secret_basis, x)
# 驗(yàn)證者驗(yàn)證
is_valid = zkp.verify(public_basis, x, proof)
print("零知識(shí)證明示例:")
print("證明是否有效:", is_valid)
11.4 身份基加密
11.4.1 基本概念
定義 11.3(身份基加密 IBE):
用戶的公鑰可以是任何唯一標(biāo)識(shí)符(如電子郵件地址),私鑰由可信第三方生成。
優(yōu)勢(shì):
-
簡(jiǎn)化密鑰管理
-
不需要證書
-
適合大規(guī)模部署
11.4.2 基于格的 IBE 方案
算法 11.3(基于格的 IBE):
class LatticeIBE:
def __init__(self, n=256, q=8192):
"""初始化IBE參數(shù)"""
self.n = n
self.q = q
def setup(self):
"""系統(tǒng)建立"""
rng = np.random.default_rng()
# 生成主密鑰
master_key = rng.integers(0, self.q, size=self.n, dtype=np.int64)
# 生成公鑰參數(shù)
public_params = rng.integers(0, self.q, size=(self.n, self.n), dtype=np.int64)
return public_params, master_key
def extract(self, public_params, master_key, identity):
"""提取私鑰"""
# 將身份轉(zhuǎn)換為向量
id_hash = hash(identity)
rng = np.random.default_rng(id_hash)
id_vector = rng.integers(0, self.q, size=self.n, dtype=np.int64)
# 計(jì)算私鑰
private_key = (master_key + id_vector) % self.q
return private_key
def encrypt(self, public_params, identity, message):
"""加密"""
rng = np.random.default_rng()
# 將身份轉(zhuǎn)換為向量
id_hash = hash(identity)
id_rng = np.random.default_rng(id_hash)
id_vector = id_rng.integers(0, self.q, size=self.n, dtype=np.int64)
# 生成隨機(jī)向量r
r = rng.integers(0, 2, size=self.n, dtype=np.int64)
# 計(jì)算密文
c1 = (public_params @ r) % self.q
c2 = (id_vector.T @ r + message \* (self.q // 2)) % self.q
return (c1, c2)
def decrypt(self, private_key, ciphertext):
"""解密"""
c1, c2 = ciphertext
# 計(jì)算明文
m_prime = (c2 - private_key.T @ c1) % self.q
# 判斷明文
if m_prime < self.q // 4 or m_prime > 3 \* self.q // 4:
return 0
else:
return 1
# 示例
ibe = LatticeIBE(n=8, q=256)
public_params, master_key = ibe.setup()
# 用戶身份
identity = "alice@example.com"
# 提取私鑰
private_key = ibe.extract(public_params, master_key, identity)
# 加密消息
message = 1
ciphertext = ibe.encrypt(public_params, identity, message)
# 解密消息
decrypted = ibe.decrypt(private_key, ciphertext)
print("IBE示例:")
print("用戶身份:", identity)
print("原始消息:", message)
print("解密消息:", decrypted)
12. 最新研究進(jìn)展與技術(shù)突破
12.1 西浦團(tuán)隊(duì) SVP 突破分析
12.1.1 突破概述
西浦團(tuán)隊(duì)成果:
2025 年,西交利物浦大學(xué)丁津泰教授團(tuán)隊(duì)成功破解了 200 維 SVP 難題,刷新了全球紀(jì)錄。
技術(shù)創(chuàng)新點(diǎn):
-
混合算法設(shè)計(jì):結(jié)合了篩法和深度學(xué)習(xí)技術(shù)
-
硬件加速:使用專門的 GPU 集群進(jìn)行計(jì)算
-
內(nèi)存優(yōu)化:采用創(chuàng)新的數(shù)據(jù)結(jié)構(gòu)和內(nèi)存管理技術(shù)
12.1.2 對(duì)格密碼的影響
安全參數(shù)重新評(píng)估:
-
原本認(rèn)為安全的參數(shù)可能需要調(diào)整
-
格密碼的安全邊際需要重新計(jì)算
-
推動(dòng)了新的格密碼方案設(shè)計(jì)
新的研究方向:
-
開(kāi)發(fā)更強(qiáng)的格基約化算法
-
設(shè)計(jì)更安全的格密碼方案
-
探索新的格困難問(wèn)題
12.2 清華大學(xué)量子算法研究
12.2.1 研究背景
量子算法對(duì)格問(wèn)題的影響:
清華大學(xué)交叉信息研究院陳一雷助理教授團(tuán)隊(duì)在格問(wèn)題的量子算法研究方面取得重要進(jìn)展。
12.2.2 主要成果
量子算法改進(jìn):
-
提出了求解 LWE 及等價(jià)格問(wèn)題的量子算法
-
聲稱能夠有效解決格上的困難問(wèn)題
-
如果正確,將是自 Shor 算法以來(lái)最重要的量子算法突破
技術(shù)細(xì)節(jié):
-
利用量子傅里葉變換加速格基約化
-
設(shè)計(jì)新的量子電路來(lái)求解線性方程組
-
在特定條件下實(shí)現(xiàn)多項(xiàng)式時(shí)間復(fù)雜度
12.2.3 研究意義
安全性評(píng)估:
為格密碼的抗量子安全性提供了更準(zhǔn)確的評(píng)估。
未來(lái)方向:
-
開(kāi)發(fā)更安全的格密碼方案
-
設(shè)計(jì)抗量子的格密碼參數(shù)
-
探索新的格基密碼學(xué)原語(yǔ)
12.3 硬件加速技術(shù)
12.3.1 HE-DIMM 內(nèi)存計(jì)算架構(gòu)
技術(shù)原理:
HE-DIMM 是一種基于內(nèi)存的同態(tài)加密計(jì)算架構(gòu),將計(jì)算邏輯集成到內(nèi)存模塊中。
性能提升:
相比傳統(tǒng) CPU 實(shí)現(xiàn),HE-DIMM 可以提供數(shù)量級(jí)的性能提升。
應(yīng)用場(chǎng)景:
-
云計(jì)算安全
-
隱私保護(hù)計(jì)算
-
大規(guī)模數(shù)據(jù)處理
12.3.2 APACHE 加速器
技術(shù)特點(diǎn):
APACHE 是專門為格密碼設(shè)計(jì)的硬件加速器,具有以下特點(diǎn):
-
針對(duì)格基運(yùn)算進(jìn)行優(yōu)化
-
支持多種格密碼算法
-
可配置的架構(gòu)設(shè)計(jì)
性能數(shù)據(jù):
-
密鑰生成速度提升 10-100 倍
-
簽名驗(yàn)證速度提升 50-500 倍
-
適合高性能計(jì)算環(huán)境
12.3.3 GPU 和 FPGA 實(shí)現(xiàn)
GPU 加速:
# GPU加速示例(使用Numba)
import numba as nb
@nb.vectorize(\['int64(int64, int64)'], target='cuda')
def gpu_poly_mult(a, b):
"""GPU加速的多項(xiàng)式乘法"""
return (a \* b) % 8192
def gpu_accelerated_lattice_ops(B):
"""GPU加速的格運(yùn)算"""
# 將數(shù)據(jù)傳輸?shù)紾PU
d_B = nb.cuda.to_device(B)
# 在GPU上執(zhí)行計(jì)算
d_result = gpu_poly_mult(d_B, d_B)
# 將結(jié)果傳輸回CPU
result = d_result.copy_to_host()
return result
# 示例
basis = np.random.randint(0, 8192, size=(1024, 1024), dtype=np.int64)
result = gpu_accelerated_lattice_ops(basis)
print("GPU加速計(jì)算完成,結(jié)果形狀:", result.shape)
12.4 格密碼與 AI 的結(jié)合
12.4.1 AI 輔助格密碼分析
神經(jīng)網(wǎng)絡(luò)用于格問(wèn)題求解:
研究人員探索使用神經(jīng)網(wǎng)絡(luò)來(lái)尋找格密碼方案中潛在的模式或弱點(diǎn)。
技術(shù)挑戰(zhàn):
-
高維數(shù)據(jù)的處理
-
復(fù)雜模式的識(shí)別
-
泛化能力的提升
12.4.2 格密碼保護(hù) AI 隱私
隱私保護(hù)機(jī)器學(xué)習(xí):
格密碼技術(shù)為保護(hù) AI 模型訓(xùn)練和推理過(guò)程中的數(shù)據(jù)隱私提供了強(qiáng)大的工具。
應(yīng)用場(chǎng)景:
-
聯(lián)邦學(xué)習(xí)
-
隱私保護(hù)推理
-
安全多方計(jì)算
13. 產(chǎn)業(yè)化應(yīng)用與實(shí)踐案例
13.1 金融領(lǐng)域應(yīng)用
13.1.1 量子安全支付系統(tǒng)
中國(guó)工商銀行量子支付網(wǎng)關(guān):
-
采用格密碼技術(shù)保護(hù)支付交易
-
支持量子安全的數(shù)字簽名
-
確保支付系統(tǒng)的長(zhǎng)期安全性
13.1.2 區(qū)塊鏈安全
以太坊 2.0 量子安全升級(jí):
-
采用格基數(shù)字簽名
-
支持量子安全的智能合約
-
保護(hù)用戶資產(chǎn)安全
13.2 云計(jì)算與大數(shù)據(jù)
13.2.1 同態(tài)加密即服務(wù)
主要云廠商的支持:
-
Google:在 Chrome 瀏覽器中支持格密碼算法
-
Microsoft:在 Azure 中集成格密碼算法
-
IBM:提供后量子密碼的云服務(wù)
13.2.2 隱私保護(hù)數(shù)據(jù)分析
應(yīng)用案例:
-
醫(yī)療數(shù)據(jù)隱私分析
-
金融風(fēng)控模型訓(xùn)練
-
廣告投放優(yōu)化
13.3 物聯(lián)網(wǎng)安全
13.3.1 輕量級(jí)格密碼實(shí)現(xiàn)
技術(shù)特點(diǎn):
-
低功耗設(shè)計(jì)
-
適合資源受限設(shè)備
-
快速密鑰交換
13.3.2 設(shè)備身份認(rèn)證
應(yīng)用場(chǎng)景:
-
智能家居設(shè)備
-
工業(yè)物聯(lián)網(wǎng)
-
車聯(lián)網(wǎng)安全
13.4 衛(wèi)星通信安全
13.4.1 格密碼解決方案
艾麗卡密碼實(shí)驗(yàn)室方案:
-
輕量級(jí)簽名算法,能耗降低至 0.1 瓦
-
結(jié)合全同態(tài)加密和量子密鑰分發(fā)
-
防御成功率提升至 99.97%
技術(shù)優(yōu)勢(shì):
-
資源受限適配
-
動(dòng)態(tài)威脅防御
-
端到端隱私保護(hù)
13.5 5G 網(wǎng)絡(luò)安全
13.5.1 3GPP 標(biāo)準(zhǔn)化
3GPP SA3 工作組:
-
制定 5G 網(wǎng)絡(luò)中的后量子密碼標(biāo)準(zhǔn)
-
重點(diǎn)關(guān)注格密碼的應(yīng)用
-
確保 5G 網(wǎng)絡(luò)的長(zhǎng)期安全性
13.5.2 應(yīng)用場(chǎng)景
網(wǎng)絡(luò)切片安全:
-
量子安全的密鑰交換
-
切片間隔離保護(hù)
-
用戶隱私保護(hù)
14. 安全性分析與攻擊防御
14.1 算法攻擊分析
14.1.1 格基約化攻擊
BKZ 算法的威脅:
BKZ 算法的不斷優(yōu)化對(duì)格密碼的安全性構(gòu)成威脅。
防御措施:
-
選擇合適的安全參數(shù)
-
使用結(jié)構(gòu)化格(如 Ring-LWE)
-
采用更強(qiáng)的格基約化抵抗技術(shù)
14.1.2 側(cè)信道攻擊
常見(jiàn)攻擊類型:
-
計(jì)時(shí)攻擊
-
功耗分析
-
故障注入攻擊
防御技術(shù):
def secure_implementation_example():
"""安全的格密碼實(shí)現(xiàn)示例"""
def constant_time_operation(a, b, q):
"""常數(shù)時(shí)間操作"""
result = (a + b) % q
# 確保操作時(shí)間不依賴于輸入值
dummy = np.random.randint(0, q)
result = (result + dummy) % q
result = (result - dummy) % q
return result
def masked_operation(a, b, mask, q):
"""掩碼操作"""
# 應(yīng)用隨機(jī)掩碼
a_masked = (a + mask) % q
b_masked = (b + mask) % q
# 執(zhí)行操作
result_masked = (a_masked \* b_masked) % q
# 移除掩碼
result = (result_masked - a \* mask - b \* mask - mask \* mask) % q
return result
def randomize_memory_access(data, indices):
"""隨機(jī)化內(nèi)存訪問(wèn)"""
# 隨機(jī)打亂訪問(wèn)順序
rng = np.random.default_rng()
permutation = rng.permutation(len(indices))
result = \[]
for i in permutation:
result.append(data\[indices\[i]])
return result
return {
'constant_time_operation': constant_time_operation,
'masked_operation': masked_operation,
'randomize_memory_access': randomize_memory_access
}
# 示例使用
secure_ops = secure_implementation_example()
q = 8192
a = 1234
b = 5678
mask = 9012
# 安全操作
result1 = secure_ops\['constant_time_operation']\(a, b, q)
result2 = secure_ops\['masked_operation']\(a, b, mask, q)
print("安全實(shí)現(xiàn)示例:")
print("常數(shù)時(shí)間操作結(jié)果:", result1)
print("掩碼操作結(jié)果:", result2)
14.2 密鑰管理安全
14.2.1 密鑰生成安全
安全的隨機(jī)數(shù)生成:
import os
import hashlib
def secure_key_generation(n, q):
"""安全的密鑰生成"""
def secure_random_bytes(length):
"""安全的隨機(jī)字節(jié)生成"""
return os.urandom(length)
def hash_drbg(seed, length):
"""基于哈希的確定性隨機(jī)位生成器"""
result = b''
counter = 0
while len(result) < length:
# 生成計(jì)數(shù)器值的字節(jié)表示
counter_bytes = counter.to_bytes(4, byteorder='big')
# 計(jì)算哈希
hash_input = seed + counter_bytes
hash_output = hashlib.sha256(hash_input).digest()
result += hash_output
counter += 1
return result[:length]
# 生成初始種子
seed = secure_random_bytes(32)
# 生成密鑰所需的隨機(jī)數(shù)據(jù)
key_bytes = hash_drbg(seed, n \* 4) # 每個(gè)元素4字節(jié)
# 轉(zhuǎn)換為整數(shù)數(shù)組
key = np.zeros(n, dtype=np.int64)
for i in range(n):
start = i \* 4
end = start + 4
key\[i] = int.from_bytes(key_bytes\[start:end], byteorder='big') % q
return key
# 示例
key = secure_key_generation(256, 8192)
print("安全生成的密鑰前10個(gè)元素:", key\[:10])
14.2.2 密鑰存儲(chǔ)安全
密鑰加密存儲(chǔ):
from cryptography.fernet import Fernet
def secure_key_storage():
"""安全的密鑰存儲(chǔ)"""
def generate_encryption_key():
"""生成加密密鑰"""
return Fernet.generate_key()
def encrypt_key(private_key, encryption_key):
"""加密私鑰"""
fernet = Fernet(encryption_key)
key_bytes = private_key.tobytes()
encrypted = fernet.encrypt(key_bytes)
return encrypted
def decrypt_key(encrypted_key, encryption_key):
"""解密私鑰"""
fernet = Fernet(encryption_key)
decrypted_bytes = fernet.decrypt(encrypted_key)
return np.frombuffer(decrypted_bytes, dtype=np.int64)
return {
'generate_encryption_key': generate_encryption_key,
'encrypt_key': encrypt_key,
'decrypt_key': decrypt_key
}
# 示例
key_storage = secure_key_storage()
private_key = np.random.randint(0, 8192, size=256, dtype=np.int64)
# 生成加密密鑰
enc_key = key_storage\['generate_encryption_key']\()
# 加密私鑰
encrypted = key_storage\['encrypt_key']\(private_key, enc_key)
# 解密私鑰
decrypted = key_storage\['decrypt_key']\(encrypted, enc_key)
print("密鑰存儲(chǔ)示例:")
print("原始密鑰前10個(gè)元素:", private_key\[:10])
print("解密密鑰前10個(gè)元素:", decrypted\[:10])
print("密鑰是否一致:", np.array_equal(private_key, decrypted))
14.3 標(biāo)準(zhǔn)化安全評(píng)估
14.3.1 NIST 安全性評(píng)估
評(píng)估標(biāo)準(zhǔn):
-
算法安全性
-
實(shí)現(xiàn)安全性
-
側(cè)信道攻擊防御
-
長(zhǎng)期安全性
評(píng)估結(jié)果:
格密碼方案在 NIST 評(píng)估中表現(xiàn)優(yōu)異,被認(rèn)為是最安全的后量子密碼技術(shù)之一。
14.3.2 第三方安全審計(jì)
審計(jì)內(nèi)容:
-
算法正確性
-
安全性證明
-
實(shí)現(xiàn)安全性
-
性能分析
推薦實(shí)踐:
重要應(yīng)用應(yīng)進(jìn)行第三方安全審計(jì),確保實(shí)現(xiàn)的安全性。
15. 結(jié)論與未來(lái)展望
15.1 格密碼的核心優(yōu)勢(shì)
15.1.1 理論安全性優(yōu)勢(shì)
基于最壞情況困難性:
格密碼的安全性基于格上的最壞情況困難問(wèn)題,這提供了最強(qiáng)的安全性保證。
抗量子特性:
目前已知的量子算法對(duì)格問(wèn)題沒(méi)有多項(xiàng)式時(shí)間的求解算法,格密碼是抗量子的。
可證明安全:
格密碼方案通常具有嚴(yán)格的安全性證明,確保了其在理論上的安全性。
15.1.2 工程實(shí)用性優(yōu)勢(shì)
效率不斷提升:
隨著算法改進(jìn)和硬件發(fā)展,格密碼的實(shí)現(xiàn)效率不斷提高。
硬件加速支持:
格密碼算法適合硬件加速,可以在專用硬件上獲得顯著的性能提升。
功能多樣性:
格密碼支持多種密碼學(xué)原語(yǔ),包括加密、簽名、密鑰交換、全同態(tài)加密等。
15.2 面臨的挑戰(zhàn)
15.2.1 效率挑戰(zhàn)
計(jì)算開(kāi)銷:
全同態(tài)加密等高級(jí)功能的計(jì)算開(kāi)銷仍然較大。
密鑰和簽名大小:
相比傳統(tǒng)密碼算法,格密碼的密鑰和簽名大小通常較大。
優(yōu)化方向:
-
算法層面的創(chuàng)新
-
硬件 - 軟件協(xié)同設(shè)計(jì)
-
專用芯片開(kāi)發(fā)
15.2.2 安全性挑戰(zhàn)
量子算法威脅:
需要持續(xù)關(guān)注量子算法對(duì)格密碼安全性的影響。
側(cè)信道攻擊:
格密碼的實(shí)現(xiàn)容易受到側(cè)信道攻擊,需要特殊的防御措施。
參數(shù)選擇安全性:
格密碼的安全性高度依賴于參數(shù)選擇,需要謹(jǐn)慎評(píng)估。
15.2.3 標(biāo)準(zhǔn)化挑戰(zhàn)
國(guó)際標(biāo)準(zhǔn)協(xié)調(diào):
需要在國(guó)際范圍內(nèi)協(xié)調(diào)格密碼標(biāo)準(zhǔn)。
互操作性保證:
確保不同實(shí)現(xiàn)之間的互操作性。
長(zhǎng)期安全性評(píng)估:
需要對(duì)格密碼的長(zhǎng)期安全性進(jìn)行持續(xù)評(píng)估。
15.3 未來(lái)發(fā)展方向
15.3.1 理論研究方向
新的格困難問(wèn)題:
探索新的格困難問(wèn)題,為密碼學(xué)應(yīng)用提供更多選擇。
更高效的算法:
開(kāi)發(fā)更高效的格算法,提高格密碼的性能。
安全性證明技術(shù):
改進(jìn)安全性證明技術(shù),提供更嚴(yán)格的安全性保證。
15.3.2 技術(shù)創(chuàng)新方向
硬件 - 軟件協(xié)同設(shè)計(jì):
通過(guò)硬件 - 軟件協(xié)同設(shè)計(jì),提高格密碼的實(shí)現(xiàn)效率。
專用芯片開(kāi)發(fā):
開(kāi)發(fā)專門的格密碼芯片,提供更高的性能和安全性。
優(yōu)化的實(shí)現(xiàn)技術(shù):
開(kāi)發(fā)優(yōu)化的實(shí)現(xiàn)技術(shù),減少計(jì)算開(kāi)銷和內(nèi)存使用。
15.3.3 應(yīng)用拓展方向
區(qū)塊鏈和數(shù)字貨幣:
將格密碼應(yīng)用于區(qū)塊鏈和數(shù)字貨幣,提供抗量子的安全保障。
隱私保護(hù) AI:
利用格密碼技術(shù)保護(hù) AI 模型和數(shù)據(jù)的隱私。
安全計(jì)算市場(chǎng):
開(kāi)發(fā)基于格密碼的安全計(jì)算服務(wù),滿足市場(chǎng)需求。
15.4 產(chǎn)業(yè)應(yīng)用前景
15.4.1 金融領(lǐng)域
應(yīng)用前景:
-
量子安全支付系統(tǒng)
-
區(qū)塊鏈安全升級(jí)
-
隱私保護(hù)金融分析
市場(chǎng)規(guī)模:
預(yù)計(jì)到 2030 年,量子安全金融技術(shù)市場(chǎng)規(guī)模將達(dá)到數(shù)百億美元。
15.4.2 云計(jì)算和大數(shù)據(jù)
應(yīng)用前景:
-
同態(tài)加密即服務(wù)
-
隱私保護(hù)機(jī)器學(xué)習(xí)
-
安全多方計(jì)算
技術(shù)趨勢(shì):
云廠商將大規(guī)模部署格密碼技術(shù),提供量子安全的云服務(wù)。
15.4.3 物聯(lián)網(wǎng)和邊緣計(jì)算
應(yīng)用前景:
-
輕量級(jí)格密碼實(shí)現(xiàn)
-
設(shè)備身份認(rèn)證
-
邊緣設(shè)備安全通信
技術(shù)挑戰(zhàn):
需要開(kāi)發(fā)更高效、更節(jié)能的格密碼實(shí)現(xiàn)。
15.5 結(jié)論
格密碼學(xué)作為后量子密碼學(xué)的核心技術(shù),經(jīng)過(guò)近 30 年的發(fā)展,已經(jīng)建立了堅(jiān)實(shí)的理論基礎(chǔ),在算法效率、安全性和功能豐富性方面都取得了顯著進(jìn)展。隨著 NIST 后量子密碼標(biāo)準(zhǔn)的發(fā)布和產(chǎn)業(yè)界的大規(guī)模采納,格密碼將在未來(lái)的信息安全中發(fā)揮越來(lái)越重要的作用。
面對(duì)量子計(jì)算的挑戰(zhàn),格密碼為構(gòu)建安全、可靠、高效的信息基礎(chǔ)設(shè)施提供了堅(jiān)實(shí)的技術(shù)基礎(chǔ)。在網(wǎng)絡(luò)安全、云計(jì)算、物聯(lián)網(wǎng)、區(qū)塊鏈等領(lǐng)域,格密碼都將有廣泛的應(yīng)用前景。
展望未來(lái),格密碼技術(shù)將繼續(xù)在算法創(chuàng)新、硬件加速、應(yīng)用拓展等方面取得新的突破,為構(gòu)建量子時(shí)代的安全信息社會(huì)做出重要貢獻(xiàn)。我們有理由相信,格密碼將成為未來(lái)信息安全的核心技術(shù),為數(shù)字經(jīng)濟(jì)的健康發(fā)展提供強(qiáng)有力的安全保障。
參考資料:
-
Oded Regev. "On lattices, learning with errors, random linear codes, and cryptography." JACM, 2009.
-
Craig Gentry, Chris Peikert, Vinod Vaikuntanathan. "Trapdoors for hard lattices and new cryptographic constructions." STOC, 2008.
-
NIST Post-Quantum Cryptography Standardization. FIPS 203, 204, 205.
-
西交利物浦大學(xué)丁津泰團(tuán)隊(duì). "200 維 SVP 難題破解研究." 2025.
-
清華大學(xué)陳一雷團(tuán)隊(duì). "格問(wèn)題的量子算法研究." 最新進(jìn)展.
-
CRYSTALS-Kyber: A CCA-secure module-lattice-based KEM.
-
CRYSTALS-Dilithium: A lattice-based digital signature scheme.
-
FALCON: Fast-Fourier lattice-based compact signatures over NTRU.
-
The Mathematics of Lattices. Various sources.
-
A Decade of Lattice Cryptography. Various sources.

嗯博客運(yùn)營(yíng)至今閱讀量終于突破了10w,新的方向,新的開(kāi)始,新的挑戰(zhàn)嗯
浙公網(wǎng)安備 33010602011771號(hào)