网工干货知识

超全学习笔记
当前位置:首页 > 干货知识

密码学中的背包加密算法

更新时间:2026年03月27日   作者:spoto   标签(Tag):

背包加密算法是最早出现的公钥加密方案之一,由Ralph Merkle和Martin Hellman在1978年共同开发出来。作为一种公钥加密系统,该算法使用两种不同的密钥:一个用于加密的公开密钥,另一个则用于解密。该算法的核心思想基于两个背包问题——一个简单版的问题和一个困难版的问题。

“简单背包”被选中作为超增序列,其中每个元素的值都大于前面所有元素的总和。这个“简单背包”就相当于私钥。而“困难背包”则是由“简单背包”衍生出来的,它构成了公钥,用于加密过程。

示例 –

{1, 2, 4, 10, 20, 40} 是一个“超级递增序列”。因为:1<2,1+2=3,1+2+4=7,1+2+4+10=17,1+2+4+10+20=30,而30<40。所以,这是一个超级递增序列。

推导出公钥

  • 步骤1:请选择一个不断增加的背包值集合:{1, 2, 4, 10, 20, 40},作为私钥。
  • 步骤2:请选择两个数字。n以及m以便/使得m 大于所有超增私钥元素的总和。还有gcd(n, m) = 1这样,就可以得到该模数的逆元了。n模数m将私钥的每个值相乘。n然后取结果除以模数。m
  • 步骤3:使用 m 和 n 来计算公钥的值。
1×31 mod(110) = 31  2×31 mod(110) = 62  4×31 mod(110) = 14  10×31 mod(110) = 90  20×31 mod(110) = 70  40×31 mod(110) = 30
  • 因此,我们的公钥为 {31, 62, 14, 90, 70, 30}。
    而私钥则分别是 {1, 2, 4, 10, 20, 40}。

现在,让我们通过一个例子来理解这个过程。加密与解密

例如——请将我们的纯文本设置为100100111100101110。

加密:由于我们的背包中包含了六个数值,因此我们将 plaintext数据分成六组来处理。

100100 111100 101110

将公钥中的每个数值与每个组中对应的数值相乘,然后将所得结果相加。

100100 {31, 62, 14, 90, 70, 30}  1×31 + 0×62 + 0×14 + 1×90 + 0×70 + 0×30 = 121  111100 {31, 62, 14, 90, 70, 30}  1×31 + 1×62 + 1×14 + 1×90 + 0×70 + 0×30 = 197  101110 {31, 62, 14, 90, 70, 30}  1×31 + 0×62 + 1×14 + 1×90 + 1×70 + 0×30 = 205

因此,我们的加密文本为121 197 205。

2. 解密:接收方接收到的是经过加密的文本,需要将其解密。此外,接收方还知道 m 和 n 的值。
所以,首先,我们需要找到……n^-1也就是 n 模 m 的乘法逆元,即…

n xn^-1mod(m) = 131 ×n^-1mod(110) = 1n^-1= 71

现在,我们必须将71与每个密码文本块相乘,然后再取模m。

121 × 71 ÷ 110 = 11

那么,我们需要用私钥 {1, 2, 4, 10, 20, 40} 中的数值来凑出 11 这个数值。也就是说,1 + 10 = 11。因此,对应的位应该为 1,其余位则为 0。最终得到的二进制数为 100100。

197 × 71 mod(110) = 17  1 + 2 + 4 + 10 = 17,即 111100  另外,205 × 71 mod(110) = 35  1 + 4 + 10 + 20 = 35,即 101110

在将它们合并之后,我们就得到了解码后的文本。
100100111100101110,这就是我们的明文。

例如:

以下是使用Knapsack加密算法的Python示例,同时附有详细的解释和输出结果:

Python
进口 随机的# 用于生成公钥的超级递增序列的函数def 生成一个不断增长的序列(n):    序列/顺序 = [随机的.随机数生成器(1, 100)]    当…的时候 长度(序列/顺序) < n:        下一个元素 = 总和(序列/顺序) + 随机的.随机数生成器(1, 10)        序列/顺序.附加(下一个元素)    返回 序列/顺序# 从公钥生成私钥的功能def 生成私有密钥(公钥, q, r):    私钥 = [(r * 元素) % q 为了 元素 in 公钥]    返回 私钥# 使用公钥对明文进行加密的功能def 背包加密(明文, 公钥):    加密后的消息 = 总和(公钥[i] 为了 i in 范围/幅度(长度(明文)) if 明文[i] == “1”)    返回 加密后的消息# 使用私钥对密文进行解密的函数def 背包解密(密文, 私钥, q):    r的反逆矩阵 = 功率(r, -1, q)  # r的模乘逆    解密后的消息 = ''    为了 元素 in 反转/颠倒(私钥):        if (密文 * r的反函数) % q >= 元素:            解密后的消息 = 1 + 解密后的消息            密文 -= 元素        否则:            解密后的消息 = ‘0’ + 解密后的消息    返回 解密后的消息# 使用示例if __name__ == __main__:    n = 8  # 超递增序列中元素的个数    q = 103  # 模数(应该大于该超增序列的总和)    r = 3  # 用于生成私钥的乘数    # 生成公钥和私钥    公钥 = 生成一个不断增加的序列(n)    私钥 = 生成私有密钥(公钥, q, r)    明文 = 11001010    密文 = 背包加密(明文, 公钥)    解密后的消息 = 背包解密(密文, 私钥, q)    打印(“原始消息:”, 明文)    打印(加密后的密文:, 密文)    打印(“解密后的消息:”, 解密后的消息)

说明:

  1. “The”generate_super_increasing_sequence()’该函数会生成一个不断增长的序列,这个序列就相当于公钥。该函数的操作是从一个随机元素开始,然后不断地向该元素添加随机数值,直到序列达到所需的长度为止。n.
  2. “The”generate_private_key()函数该功能是从…中生成私钥的。公钥使用以下公式:‘private_key[i] = (r * public_key[i]) % q.
  3. “那个”knapsack_encrypt()函数该函数以明文和公钥作为输入。它将明文转换为二进制形式,然后通过对公钥中对应于二进制表示中“1”位的元素进行求和来对其进行加密。明文.
  4. “那个”knapsack_decrypt()函数该函数接收密文、私钥以及模数作为输入参数。q作为输入。它使用私钥来重建原始二进制表示形式。具体做法是:在密文中找到那些“1”位,然后从私钥中减去这些“1”位所对应的数值。

输出结果:

原始消息:11001010  加密后的密文:426  解密后的消息:11001010

在这个例子中,明文“11001010”是通过以下方式被加密的:背包加密算法最终得到的密文为“426”。经过解密后,原始明文又恢复了原样。这表明该算法的正确性得到了验证。

              马上抢免费试听资格
意向课程:*必选
姓名:*必填
联系方式:*必填
QQ:
思博SPOTO在线咨询

相关资讯

即刻预约

免费试听-咨询课程-获取免费资料