背包密码密度的作用(LLL算法的实现)

背包问题通解:

当密度d满足以下条件时,LLL算法能有效地解决这类背包问题

 ![](https://cdn.nlark.com/yuque/0/2025/png/49294098/1739349426771-401f2fa7-aefe-422b-b642-5d8f664c415d.png)

其中:

  • len(M)是向量M的长度,即向量中元素的数量
  • max(Mi)是向量M中的最大元素

计算:

import math

def calculate_density(M):
    if all(isinstance(sub_list, list) for sub_list in M):  #检查 M 是否为二维列表
        densities = []
        for sub_list in M:
            len_M = len(sub_list)  #计算子列表的长度
            max_Mi = max(sub_list)  #找到子列表中的最大元素

            density = len_M / math.log2(max_Mi)
            densities.append(density)

        return densities
    else:
        len_M = len(M)  #计算列表的长度
        max_Mi = max(M)  #找到列表中的最大元素

        return len_M / math.log2(max_Mi)

#M_single = []
#M_multiple = [[],[],[]]
#计算单个背包问题的密度
density_single = calculate_density(M_single)
print(f"单个背包的密度是: {density_single}")

#计算多个背包问题的密度
densities_multiple = calculate_density(M_multiple)
for i, density in enumerate(densities_multiple):
    print(f"第 {i + 1} 个背包的密度是: {density}")

构造格:

  1. 定义公钥序列M:
    • 公钥序列<font style="color:rgb(44, 44, 54);">M=(M</font><sub><font style="color:rgb(44, 44, 54);">1</font></sub><font style="color:rgb(44, 44, 54);">,M</font><sub><font style="color:rgb(44, 44, 54);">2</font></sub><font style="color:rgb(44, 44, 54);">,…,M</font><sub><font style="color:rgb(44, 44, 54);">n</font></sub><font style="color:rgb(44, 44, 54);">)</font>,其中每个<font style="color:rgb(44, 44, 54);">M</font><sub><font style="color:rgb(44, 44, 54);">i</font></sub>是一个整数
  2. 构造格的基:
    • 格的基是一个矩阵,每一行代表一个向量;对于背包问题,可以构造如下矩阵:

- <font style="color:rgb(44, 44, 54);">这里</font>`<font style="color:rgb(44, 44, 54);">S</font>`<font style="color:rgb(44, 44, 54);">是目标值,即背包问题中需要达到的总重量</font>
  1. 理解每一行向量Vi:
    • 每一行向量<font style="color:rgb(44, 44, 54);">V</font><sub><font style="color:rgb(44, 44, 54);">i</font></sub>的形式为<font style="color:rgb(44, 44, 54);">(1,0,…,0,M</font><sub><font style="color:rgb(44, 44, 54);">i</font></sub><font style="color:rgb(44, 44, 54);">)</font>,表示在第i个位置有一个<font style="color:rgb(44, 44, 54);">M</font><sub><font style="color:rgb(44, 44, 54);">i</font></sub>,其余位置为<font style="color:rgb(44, 44, 54);">0</font>
  2. 明文序列x:
    • 明文序列<font style="color:rgb(44, 44, 54);">x=(x</font><sub><font style="color:rgb(44, 44, 54);">1</font></sub><font style="color:rgb(44, 44, 54);">,x</font><sub><font style="color:rgb(44, 44, 54);">2</font></sub><font style="color:rgb(44, 44, 54);">,…,x</font><sub><font style="color:rgb(44, 44, 54);">n</font></sub><font style="color:rgb(44, 44, 54);">)</font>,其中每个<font style="color:rgb(44, 44, 54);">x</font><sub><font style="color:rgb(44, 44, 54);">i</font></sub>只能取<font style="color:rgb(44, 44, 54);">0</font><font style="color:rgb(44, 44, 54);">1</font>,表示是否选择第<font style="color:rgb(6, 6, 7);">i</font>个物品
  3. 线性组合:
    • 对于线性组合<font style="color:rgb(44, 44, 54);">x</font><sub><font style="color:rgb(44, 44, 54);">1</font></sub><font style="color:rgb(44, 44, 54);">V</font><sub><font style="color:rgb(44, 44, 54);">1</font></sub><font style="color:rgb(44, 44, 54);">+x</font><sub><font style="color:rgb(44, 44, 54);">2</font></sub><font style="color:rgb(44, 44, 54);">V</font><sub><font style="color:rgb(44, 44, 54);">2</font></sub><font style="color:rgb(44, 44, 54);">+⋯+x</font><sub><font style="color:rgb(44, 44, 54);">n</font></sub><font style="color:rgb(44, 44, 54);">V</font><sub><font style="color:rgb(44, 44, 54);">n</font></sub><font style="color:rgb(44, 44, 54);">−V</font><sub><font style="color:rgb(44, 44, 54);">n+1</font></sub>,这个组合必然在格点上,因为<font style="color:rgb(44, 44, 54);">x</font><sub><font style="color:rgb(44, 44, 54);">i</font></sub>只能取<font style="color:rgb(44, 44, 54);">0</font><font style="color:rgb(44, 44, 54);">1</font>
    • 向量<font style="color:rgb(44, 44, 54);">t=x</font><sub><font style="color:rgb(44, 44, 54);">1</font></sub><font style="color:rgb(44, 44, 54);">V</font><sub><font style="color:rgb(44, 44, 54);">1</font></sub><font style="color:rgb(44, 44, 54);">+x</font><sub><font style="color:rgb(44, 44, 54);">2</font></sub><font style="color:rgb(44, 44, 54);">V</font><sub><font style="color:rgb(44, 44, 54);">2</font></sub><font style="color:rgb(44, 44, 54);">+⋯+x</font><sub><font style="color:rgb(44, 44, 54);">n</font></sub><font style="color:rgb(44, 44, 54);">V</font><sub><font style="color:rgb(44, 44, 54);">n</font></sub><font style="color:rgb(44, 44, 54);">−V</font><sub><font style="color:rgb(44, 44, 54);">n+1</font></sub>可以表示为<font style="color:rgb(44, 44, 54);">t=(x</font><sub><font style="color:rgb(44, 44, 54);">1</font></sub><font style="color:rgb(44, 44, 54);">,x</font><sub><font style="color:rgb(44, 44, 54);">2</font></sub><font style="color:rgb(44, 44, 54);">,…,x</font><sub><font style="color:rgb(44, 44, 54);">n</font></sub><font style="color:rgb(44, 44, 54);">,0)</font>
  4. 向量长度和格的体积:
    • 向量t的长度
    • 格的体积
  5. Hermite定理:
    • 根据Hermite定理,
  6. 最短向量:
    • 因此,向量<font style="color:rgb(44, 44, 54);">t</font>是格L的最短向量,可以用LLL算法来找到它

代码实现:

使用整数环**ZZ**来构造矩阵A

c=
pub=[]
nbit = len(pub)
A = Matrix(ZZ, nbit + 1, nbit + 1)
for i in range(nbit):
    A[i, i] = 1
    A[i, nbit] = pub[i]
A[nbit, nbit] = -c
res = A.LLL()
x= []
for i in range(len(res.rows())):
    row = res.row(i).list()
    is_binary = True
    for m in row:
        if m !=0 and m!=1:
            is_binary=False
            break
    if is_binary:
        print(i,row) #得到一组只有0和1的数组
        flag=''.join(str(j)for j in row[:-1])
        print(hex(int(flag,2)))

使用有理数域**QQ**来构造矩阵L

pubkey = []
c = 
L = matrix(QQ,len(pubkey) + 1,len(pubkey) + 1)
# N = nextprime(iroot(len(pubkey),2)[0]//2)
for i in range(len(pubkey)):
    L[i,i] = 1
    L[i,len(pubkey)] = pubkey[i]

for i in range(len(pubkey)):
    L[len(pubkey),i]=1/2
    
L[-1,-1] = c  #(L[len(pubkey),len(pubkey)]=-c)
L = L.LLL()
#print(L)
for i in range(len(pubkey) + 1):
    M = L.row(i).list()[:-1]
    flag = True
    for m in M:
        if m != 1/2 and m != -1/2: # 否定则为m = 1/2 或 -1/2,故此处and是合理的
            flag = False
            break
    if flag:
        m = ''
        print(i,M)
        for j in M:
            if j == -1/2: # 此处并不确定哪个代表二进制1
                m = '1' + m # 上面分析时说过,得出的是从低位到高位,故后面得出的数放前面可得正确m
            else:
                m = '0' + m
        print(hex(int(m,2)))
        break
posted @ 2025-03-12 00:07  sevensnight  阅读(47)  评论(0)    收藏  举报