0

Cấu trúc dữ liệu và Giải thuật Bài 147: Thuật toán Giảm cơ sở lưới LLL (Lenstra-Lenstra-Lovász Lattice Basis Reduction) - Nền tảng mật mã học hậu lượng tử và hình học của các con số.

Trong hình học của các con số (Geometry of Numbers) do Hermann Minkowski khởi xướng, một lưới (Lattice) là tập hợp vô hạn các điểm rời rạc trong không gian vector được sinh ra bởi các tổ hợp tuyến tính nguyên của một hệ cơ sở. Cùng một lưới có thể được biểu diễn bởi vô số cơ sở khác nhau. Một cơ sở "xấu" bao gồm các vector rất dài và gần như song song với nhau; ngược lại, một cơ sở "tốt" bao gồm các vector ngắn và gần như trực giao (orthogonal) với nhau.

Bài toán tìm vector khác không ngắn nhất trong lưới (Shortest Vector Problem - SVP) là một bài toán NP-hard dưới các phép quy nạp ngẫu nhiên hóa và là nền tảng an toàn của toàn bộ nền Mật mã học hậu lượng tử (Post-Quantum Cryptography - PQC) hiện đại.

Năm 1982, ba nhà toán học Arjen Lenstra, Hendrik Lenstra và László Lovász đã công bố Thuật toán LLL (Lenstra-Lenstra-Lovász Lattice Basis Reduction). Thuật toán này không giải chính xác bài toán SVP trong thời gian hàm mũ, mà giải bài toán xấp xỉ SVP: tìm ra một cơ sở gồm các vector ngắn có độ dài bị chặn trong phạm vi hệ số hàm mũ 2(d−1)/22^{(d-1)/2} so với vector ngắn nhất tuyệt đối trong thời gian đa thức. Đây là một trong những thuật toán toán học có ảnh hưởng sâu rộng nhất thế kỷ 20, ứng dụng từ việc phân tích đa thức hệ số hữu tỉ, giải quy hoạch nguyên, phá vỡ hệ mật mã knapsack và RSA, cho đến phân tích độ an toàn của các thuật toán mã hóa kháng lượng tử chuẩn NIST như Kyber hay Dilithium.

1. Cơ sở Lý thuyết: Khái niệm Lưới và Hình học Minkowski

Cho dd vector độc lập tuyến tính b1,b2,…,bd∈Rnb_1, b_2, \dots, b_d \in \mathbb{R}^n (d≤nd \le n).

Lưới Λ\Lambda sinh bởi hệ cơ sở B={b1,b2,…,bd}B = \{b_1, b_2, \dots, b_d\} là tập hợp tất cả các tổ hợp tuyến tính với hệ số nguyên:

Λ=L(B)={∑i=1dzibi  |  zi∈Z}\Lambda = \mathcal{L}(B) = \left\{ \sum_{i=1}^d z_i b_i \;\middle\vert{}\; z_i \in \mathbb{Z} \right\}

  • dd được gọi là hạng (rank) của lưới. Nếu d=nd = n, lưới được gọi là toàn hạng (full-rank).

  • Định thức của lưới (Determinant / Volume): Đại lượng đo lường thể tích của hình hộp cơ bản (fundamental parallelepiped) sinh bởi BB:

    det⁡(Λ)=det⁡(BTB)\det(\Lambda) = \sqrt{\det(B^T B)}

    Định thức là một bất biến hình học: mọi cơ sở hợp lệ của cùng một lưới Λ\Lambda đều có chung một định thức det⁡(Λ)\det(\Lambda).

   Cơ sở "xấu" (Vector dài, góc hẹp):         Cơ sở "tốt" (Vector ngắn, gần trực giao):
             b2                                         b2
            /                                           ^
           /                                            |
          /                                             |
         o--------> b1                                  o--------> b1
      (Rất khó giải bài toán)                      (Đạt chuẩn LLL-reduced)

Các bài toán tính toán cơ bản trên Lưới

  1. Shortest Vector Problem (SVP): Tìm vector v∈Λ∖{0}v \in \Lambda \setminus \{0\} sao cho độ dài Euclidean ∥v∥\Vert{}v\Vert{} đạt cực tiểu:

    λ1(Λ)=min⁡v∈Λ∖{0}∥v∥\lambda_1(\Lambda) = \min_{v \in \Lambda \setminus \{0\}} \Vert{}v\Vert{}

  2. Closest Vector Problem (CVP): Cho một điểm đích t∈Rnt \in \mathbb{R}^n, tìm vector v∈Λv \in \Lambda gần tt nhất:

    dist(t,Λ)=min⁡v∈Λ∥t−v∥\text{dist}(t, \Lambda) = \min_{v \in \Lambda} \Vert{}t - v\Vert{}

Định lý thứ nhất của Minkowski (Minkowski's First Theorem)

Minkowski chứng minh rằng trong bất kỳ lưới toàn hạng Λ⊂Rd\Lambda \subset \mathbb{R}^d nào, luôn tồn tại một vector khác không có độ dài bị chặn trên bởi:

λ1(Λ)≤d⋅(det⁡(Λ))1/d\lambda_1(\Lambda) \le \sqrt{d} \cdot (\det(\Lambda))^{1/d}

Tuy nhiên, định lý Minkowski chỉ mang tính chất tồn tại thuần túy, không cung cấp phương pháp tìm ra vector đó trong thời gian đa thức.

2. Trực chuẩn hóa Gram-Schmidt (GSO) và Cơ sở LLL-Reduced

Để đánh giá mức độ trực giao của một cơ sở, công cụ đại số then chốt là Quá trình Trực giao hóa Gram-Schmidt (Gram-Schmidt Orthogonalization - GSO).

Biểu diễn Gram-Schmidt

Cho cơ sở b1,…,bd∈Rnb_1, \dots, b_d \in \mathbb{R}^n, các vector trực giao tương ứng b1∗,…,bd∗b_1^*, \dots, b_d^* được xác định:

bi∗=bi−∑j=1i−1μi,jbj∗vớiμi,j=⟨bi,bj∗⟩∥bj∗∥2b_i^* = b_i - \sum_{j=1}^{i-1} \mu_{i, j} b_j^* \quad \text{với} \quad \mu_{i, j} = \frac{\langle b_i, b_j^* \rangle}{\Vert{}b_j^*\Vert{}^2}

  • Các vector bi∗b_i^* tạo thành hệ trực giao trong Rn\mathbb{R}^n: ⟨bi∗,bj∗⟩=0\langle b_i^*, b_j^* \rangle = 0 với mọi i≠ji \neq j.

  • Định thức của lưới liên hệ trực tiếp với GSO: det⁡(Λ)=∏i=1d∥bi∗∥\det(\Lambda) = \prod_{i=1}^d \Vert{}b_i^*\Vert{}.

  • Lưu ý cốt tử: Các vector bi∗b_i^* nói chung không thuộc lưới Λ\Lambda vì các hệ số μi,j\mu_{i, j} là số thực, không phải số nguyên.

Định nghĩa Cơ sở Giảm LLL (LLL-Reduced Basis)

Một cơ sở B=(b1,…,bd)B = (b_1, \dots, b_d) được gọi là LLL-reduced với tham số δ∈(1/4,1]\delta \in (1/4, 1] (thường chọn δ=3/4\delta = 3/4 hoặc δ=0.99\delta = 0.99) nếu thỏa mãn đồng thời hai điều kiện:

1. Điều kiện Giảm kích thước (Size-Reduced Condition)

∣μi,j∣≤12với mọi 1≤j<i≤d\vert{}\mu_{i, j}\vert{} \le \frac{1}{2} \quad \text{với mọi } 1 \le j < i \le d

Ý nghĩa: Hình chiếu của vector bib_i lên các vector trực giao trước đó bj∗b_j^* có độ dài không vượt quá một nửa độ dài của bj∗b_j^*. Điều này đảm bảo các vector cơ sở không bị "nghiêng" quá mức về phía các vector đi trước.

2. Điều kiện Lovász (Lovász Condition)

δ∥bk−1∗∥2≤∥bk∗+μk,k−1bk−1∗∥2=∥bk∗∥2+μk,k−12∥bk−1∗∥2\delta \Vert{}b_{k-1}^*\Vert{}^2 \le \Vert{}b_k^* + \mu_{k, k-1} b_{k-1}^*\Vert{}^2 = \Vert{}b_k^*\Vert{}^2 + \mu_{k, k-1}^2 \Vert{}b_{k-1}^*\Vert{}^2

hay tương đương:

∥bk∗∥2≥(δ−μk,k−12)∥bk−1∗∥2\Vert{}b_k^*\Vert{}^2 \ge \left( \delta - \mu_{k, k-1}^2 \right) \Vert{}b_{k-1}^*\Vert{}^2

Ý nghĩa: Đảm bảo độ dài của các vector trực giao bi∗b_i^* không bị suy giảm quá nhanh khi chỉ số ii tăng dần. Nếu điều kiện này bị vi phạm, việc hoán đổi hai vector bk−1b_{k-1} và bkb_k sẽ giúp vector đứng trước ngắn hơn đáng kể.

3. Các bước Thực thi của Thuật toán LLL

Thuật toán LLL liên tục thực hiện hai thao tác cơ bản:

  1. Size Reduction: Trừ đi các bội số nguyên của các vector trước đó để thu nhỏ hệ số ∣μi,j∣≤1/2\vert{}\mu_{i, j}\vert{} \le 1/2.

  2. Lovász Swap: Hoán đổi hai vector kề nhau khi điều kiện Lovász bị vi phạm, làm giảm thế năng của cơ sở.

                  Bắt đầu với k = 1
                          |
                          v
         +---> [Size-Reduce: b_k theo b_{k-1}]
         |                |
         |                v
         |     [Kiểm tra Điều kiện Lovász]
         |       /                     \
   (Vi phạm)   /                         \ (Thỏa mãn)
             v                             v
    [Hoán đổi b_{k-1} và b_k]    [Size-Reduce: b_k theo b_{k-2} ... b_0]
    [Cập nhật lại GSO]                     |
    [k = max(k - 1, 1)]                    v
             |                         [k = k + 1]
             +-----------------------------+
                          |
               (Dừng khi k == d)

Chứng minh Tính hữu hạn (Potential Function Argument)

Tại sao thuật toán LLL chắc chắn dừng lại trong thời gian đa thức mà không bị lặp vô hạn?

Lenstra, Lenstra và Lovász định nghĩa hàm thế năng (Potential function) DD:

D=∏i=1d−1divớidi=det⁡(L(b1,…,bi))2=∏j=1i∥bj∗∥2D = \prod_{i=1}^{d-1} d_i \quad \text{với} \quad d_i = \det(\mathcal{L}(b_1, \dots, b_i))^2 = \prod_{j=1}^i \Vert{}b_j^*\Vert{}^2

  • Mỗi khi thực hiện phép hoán đổi giữa bk−1b_{k-1} và bkb_k vi phạm điều kiện Lovász, chỉ có định thức con dk−1d_{k-1} bị thay đổi.

  • Giá trị mới dk−1′d_{k-1}' giảm ít nhất một hệ số hằng số: dk−1′≤δ⋅dk−1d_{k-1}' \le \delta \cdot d_{k-1} (với δ<1\delta < 1).

  • Các định thức con did_i khác (i≠k−1i \neq k-1) hoàn toàn không đổi.

  • Do đó, thế năng toàn cục DD giảm ít nhất một hệ số δ\delta sau mỗi phép hoán đổi.

  • Vì các vector có tọa độ nguyên, did_i luôn là các số nguyên dương ≥1\ge 1, chặn dưới giá trị của D≥1D \ge 1. Do đó, số phép hoán đổi tối đa bị chặn trên bởi O(d2log⁡B)O(d^2 \log B), chứng minh thuật toán kết thúc sau một số đa thức các bước.

4. Hiện thực hóa Thuật toán LLL bằng Golang

Chương trình Golang dưới đây cài đặt hoàn chỉnh:

  • Hàm tính toán Gram-Schmidt Orthogonalization (GSO) và ma trận hệ số μ\mu.

  • Thủ tục Size-Reduction trừ bội số nguyên.

  • Bước kiểm tra điều kiện Lovász và cập nhật hoán đổi vector.

  • Kiểm thử trên cơ sở lưới chiều cao để tìm vector ngắn.

Go

package main

import (
	"fmt"
	"math"
)

type LLLReducer struct {
	d     int         // Số lượng vector cơ sở (hạng)
	n     int         // Số chiều của không gian
	b     [][]float64 // Cơ sở hiện tại (d x n)
	bStar [][]float64 // Các vector trực giao Gram-Schmidt (d x n)
	mu    [][]float64 // Ma trận hệ số GSO (d x d)
	gamma []float64   // gamma[i] = ||bStar[i]||^2
	delta float64     // Tham số Lovasz (thường chọn 0.75)
}

func NewLLLReducer(basis [][]float64, delta float64) *LLLReducer {
	d := len(basis)
	n := len(basis[0])

	bCopy := make([][]float64, d)
	for i := 0; i < d; i++ {
		bCopy[i] = make([]float64, n)
		copy(bCopy[i], basis[i])
	}

	bStar := make([][]float64, d)
	mu := make([][]float64, d)
	for i := 0; i < d; i++ {
		bStar[i] = make([]float64, n)
		mu[i] = make([]float64, d)
	}

	return &LLLReducer{
		d:     d,
		n:     n,
		b:     bCopy,
		bStar: bStar,
		mu:    mu,
		gamma: make([]float64, d),
		delta: delta,
	}
}

func dot(u, v []float64) float64 {
	var sum float64
	for i := range u {
		sum += u[i] * v[i]
	}
	return sum
}

// Cập nhật biểu diễn Gram-Schmidt toàn bộ
func (lll *LLLReducer) updateGSO() {
	for i := 0; i < lll.d; i++ {
		// bStar[i] = b[i]
		copy(lll.bStar[i], lll.b[i])

		for j := 0; j < i; j++ {
			if lll.gamma[j] > 1e-12 {
				lll.mu[i][j] = dot(lll.b[i], lll.bStar[j]) / lll.gamma[j]
			} else {
				lll.mu[i][j] = 0
			}
			for k := 0; k < lll.n; k++ {
				lll.bStar[i][k] -= lll.mu[i][j] * lll.bStar[j][k]
			}
		}
		lll.mu[i][i] = 1.0
		lll.gamma[i] = dot(lll.bStar[i], lll.bStar[i])
	}
}

// Giảm kích thước b[k] theo b[j]
func (lll *LLLReducer) sizeReduce(k, j int) {
	if math.Abs(lll.mu[k][j]) > 0.5 {
		q := math.Round(lll.mu[k][j])
		for i := 0; i < lll.n; i++ {
			lll.b[k][i] -= q * lll.b[j][i]
		}
		// Cập nhật lại các hệ số mu sau khi trừ
		lll.mu[k][j] -= q
		for i := 0; i < j; i++ {
			lll.mu[k][i] -= q * lll.mu[j][i]
		}
	}
}

// Thuật toán LLL chính thức
func (lll *LLLReducer) Reduce() [][]float64 {
	lll.updateGSO()
	k := 1

	for k < lll.d {
		// 1. Giảm kích thước b[k] đối với b[k-1]
		lll.sizeReduce(k, k-1)

		// 2. Kiểm tra điều kiện Lovasz:
		// gamma[k] >= (delta - mu[k][k-1]^2) * gamma[k-1]
		lovaszBound := (lll.delta - lll.mu[k][k-1]*lll.mu[k][k-1]) * lll.gamma[k-1]

		if lll.gamma[k] < lovaszBound {
			// Điều kiện Lovasz bị vi phạm -> Hoán đổi b[k] và b[k-1]
			lll.b[k], lll.b[k-1] = lll.b[k-1], lll.b[k]

			// Cập nhật lại GSO và lùi k
			lll.updateGSO()
			if k > 1 {
				k--
			}
		} else {
			// Thỏa mãn Lovasz -> Giảm kích thước b[k] đối với tất cả các b[j] còn lại (j = k-2 lùi về 0)
			for j := k - 2; j >= 0; j-- {
				lll.sizeReduce(k, j)
			}
			k++
		}
	}

	return lll.b
}

func norm(v []float64) float64 {
	return math.Sqrt(dot(v, v))
}

func main() {
	// Khởi tạo một cơ sở 4 chiều rất "xấu" (các vector dài và gần như thẳng hàng)
	// sinh ra một mạng lưới số nguyên
	initialBasis := [][]float64{
		{1, 1, 1, 1},
		{-1, 0, 2, 1},
		{3, 5, 6, 8},
		{0, 1, -1, 0},
	}

	fmt.Println("=== CƠ SỞ BAN ĐẦU (Chưa giảm) ===")
	for i, v := range initialBasis {
		fmt.Printf("b_%d = %v (Độ dài: %.3f)\n", i, v, norm(v))
	}

	// Chạy thuật toán LLL với delta = 0.75
	reducer := NewLLLReducer(initialBasis, 0.75)
	reducedBasis := reducer.Reduce()

	fmt.Println("\n=== CƠ SỞ SAU KHI GIẢM BẰNG THUẬT TOÁN LLL (delta = 0.75) ===")
	for i, v := range reducedBasis {
		// Làm tròn nhẹ hiển thị để loại bỏ sai số số thực float64
		roundedV := make([]int64, len(v))
		for j := range v {
			roundedV[j] = int64(math.Round(v[j]))
		}
		fmt.Printf("b_%d = %v (Độ dài: %.3f)\n", i, roundedV, norm(v))
	}

	fmt.Printf("\nVector ngắn nhất tìm được bởi LLL (b_0): %.3f\n", norm(reducedBasis[0]))
}

5. Các Chặn Đánh giá Chất lượng và Phân tích Độ phức tạp

Các Chặn Đánh giá Lý thuyết của Cơ sở LLL

Gọi B=(b1,…,bd)B = (b_1, \dots, b_d) là cơ sở đã được LLL-reduced với tham số δ=3/4\delta = 3/4:

  1. Chặn độ dài vector đầu tiên so với nghiệm tối ưu SVP:

    ∥b1∥≤2(d−1)/2⋅λ1(Λ)\Vert{}b_1\Vert{} \le 2^{(d-1)/2} \cdot \lambda_1(\Lambda)

    Ý nghĩa: Vector đầu tiên b1b_1 đảm bảo xấp xỉ vector ngắn nhất tuyệt đối trong phạm vi hệ số mũ 2(d−1)/22^{(d-1)/2}.

  2. Chặn so với Định thức của Lưới:

    ∥b1∥≤2(d−1)/4⋅(det⁡(Λ))1/d\Vert{}b_1\Vert{} \le 2^{(d-1)/4} \cdot (\det(\Lambda))^{1/d}

  3. Tính trực giao tổng thể (Hadamard Ratio Bound):

    ∏i=1d∥bi∥≤2d(d−1)/4⋅det⁡(Λ)\prod_{i=1}^d \Vert{}b_i\Vert{} \le 2^{d(d-1)/4} \cdot \det(\Lambda)

    (Tích độ dài các vector LLL-reduced tiệm cận gần với thể tích hình hộp cơ sở, chứng minh tính gần trực giao).

Phân tích Độ phức tạp Thời gian

Gọi Bmax⁡=max⁡i∥bi∥B_{\max} = \max_i \Vert{}b_i\Vert{} là độ dài lớn nhất của các vector cơ sở đầu vào.

Tiêu chí Logical View Materialized View (MV)
Bản chất lưu trữ Chỉ lưu câu lệnh SQL Lưu SQL + File dữ liệu vật lý
Tốc độ truy vấn Bằng đúng thời gian chạy SQL gốc Siêu nhanh (Đọc dữ liệu đã tính sẵn)
Độ tươi (Freshness) Real-time (Luôn lấy dữ liệu mới nhất) Dữ liệu cũ (Cho đến khi được REFRESH)
Chi phí ổ cứng 0 Byte Tốn dung lượng lưu file Parquet
Khi nào nên dùng? Che giấu dữ liệu (Bảo mật), đổi tên cột, logic tính toán nhẹ. Dashboard cho sếp xem cần load nhanh, báo cáo tổng hợp cuối tháng/quý.

Để áp dụng trong thực tế mật mã học với số chiều lớn (d>100d > 100), các thư viện chuẩn (như NTL hay fplll) sử dụng kỹ thuật Floating-Point LLL kết hợp kiểm soát sai số động để đạt tốc độ cao mà không làm mất tính đúng đắn của đại số.

6. Ứng dụng Thực tế và Tầm ảnh hưởng trong Mật mã học

  • Mật mã học Hậu Lượng tử (Post-Quantum Cryptography - PQC):

    • Các thuật toán chữ ký số và mã hóa khóa công khai chuẩn hóa bởi Viện Tiêu chuẩn và Kỹ thuật Quốc gia Hoa Kỳ (NIST) như CRYSTALS-Kyber (ML-KEM) và CRYSTALS-Dilithium (ML-DSA) dựa trên bài toán Module Learning With Errors (M-LWE).

    • LLL và biến thể khối mở rộng của nó — Thuật toán BKZ (Block Korkine-Zolotarev) — là công cụ chuẩn mực số 1 được sử dụng để đánh giá độ an toàn bit thực tế (Concrete Hardness) của các hệ mật mã kháng lượng tử trước các cuộc tấn công thu hẹp lưới (Lattice Reduction Attacks).

  • Định lý Coppersmith & Tấn công Hệ mật RSA:

    • Năm 1996, Don Coppersmith sử dụng LLL để tìm nghiệm nguyên nhỏ của đa thức một biến theo modulo NN. Kỹ thuật này phá vỡ hoàn toàn các triển khai RSA khi số mũ công khai nhỏ (e=3e = 3) trong các kịch bản lộ một phần khóa bí mật, chia sẻ bản rõ, hoặc tấn công Franklin-Reiter Related Message.
  • Tấn công Hệ mật Knapsack (Merkle-Hellman Knapsack Cryptosystem):

    • Hệ mật Merkle-Hellman từng được coi là giải pháp thay thế RSA. Năm 1985, Andrew Odlyzko và Ernest Brickell sử dụng LLL quy bài toán Subset-Sum về bài toán tìm vector ngắn trong lưới đa chiều, bẻ gãy hệ mật này trong thời gian đa thức.
  • Phân tích Đa thức Thành Nhân tử (Factoring Polynomials over Q\mathbb{Q}):

    • Động lực ban đầu của Lenstra, Lenstra và Lovász năm 1982 là giải bài toán phân tích một đa thức bậc dd với hệ số hữu tỉ thành các nhân tử bất khả quy trong thời gian đa thức — một vấn đề toán học mở suốt nhiều thế kỷ.

All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.