【发布时间】:2012-05-22 03:13:43
【问题描述】:
如果我想加密 26 个字符的字母集,希尔密码中使用的密钥与加密 35 个字母集的密钥是否不同?
【问题讨论】:
-
最好在crypto.stackexchange.com问,这样问它不包含任何与编程相关的...
标签: algorithm matrix linear-algebra encryption
如果我想加密 26 个字符的字母集,希尔密码中使用的密钥与加密 35 个字母集的密钥是否不同?
【问题讨论】:
标签: algorithm matrix linear-algebra encryption
想法没有改变,只是计算略有不同。我记得您在 Hill Cipher 上的最后一个问题是您实际上想为其实现 CBC 模式。我建议您选择计算 mod 256,而不是计算 mod 26 - 这样您就可以轻松地来回映射到密钥、IV 和生成的密文的字节表示。此外,它还允许您使用空格和其他标点符号,您甚至可以为您的消息使用 UTF-8 或类似编码。
密钥的概念不会改变 mod 256,但计算方式会有所不同。与其选择在 Z^n/26 中可逆的 n x n 矩阵,不如选择在 Z^n/256 中可逆的矩阵。假设您选择了一个 3 x 3 矩阵,它仍然很容易可逆,然后您可以通过检查非零行列式模 256 来检查您选择的键(矩阵)是否可逆,如Wikipedia article 中所述。然后,您的键的字节数组表示将只是一个长度为 9 的数组,从矩阵到数组的直接映射:元素 (1,2)(假设从零开始索引)将是数组的第五个元素( 1*3 + 2) 等。
然后,您会将消息拆分为 3 字节块(如果最后一个块未与三个字节对齐,则使用某种形式的填充),这些块表示要与键矩阵相乘的向量,再次产生 3 字节输出块。
如您所见,使用 mod 256 表示非常简洁,因为这种方式加密/解密可以与相同的接口一起使用,该接口也可用于 AES 等最先进的分组密码,即您通过对消息应用基于字节数组密钥的加密/解密函数来加密消息,该消息分为适当大小的块/块。
生成加密矩阵只需要创建一个随机 3x3 矩阵,其元素来自 Z256,直到找到具有非零行列式(mod 256)和模逆元素 mod 256(我们将使用扩展欧几里得算法计算)的矩阵)。然后,计算逆矩阵遵循与计算常规 3x3 矩阵逆相同的规则,除了所有计算都需要在 Z256 中进行。有一个用于计算 3x3 矩阵逆的封闭公式,如 here 所示。我们可以使用 Z256 中的模运算来计算完全相同的东西,以得到 Z^n/256 中的逆。
这里有一些 Ruby 代码可以生成一个键矩阵及其逆矩阵:
require 'matrix'
class Integer
def modinv(modulus)
a, b = modulus, self
q, r = a / b, a % b
t0, t1 = 0, 1
while r > 0
t0, t1 = t1, (t0 - q * t1) % modulus
a, b = b, r
q, r = a / b, a % b
end
raise RuntimeError.new("#{self} has no inverse modulo #{modulus}") unless b == 1
t1
end
end
while true
m = Matrix.build(3) { rand(0..256) }
mod_det = m.determinant % 256
next if mod_det == 0
begin
det_inv = mod_det.modinv(256)
break
rescue RuntimeError => e
next
end
end
inv = Matrix[
[ (m[2,2]*m[1,1] - m[2,1]*m[1,2]), -(m[2,2]*m[0,1] - m[2,1]*m[0,2]), (m[1,2]*m[0,1] - m[1,1]*m[0,2])],
[-(m[2,2]*m[1,0] - m[2,0]*m[1,2]), (m[2,2]*m[0,0] - m[2,0]*m[0,2]), -(m[1,2]*m[0,0] - m[1,0]*m[0,2])],
[ (m[2,1]*m[1,0] - m[2,0]*m[1,1]), -(m[2,1]*m[0,0] - m[2,0]*m[0,1]), (m[1,1]*m[0,0] - m[1,0]*m[0,1])]
].map { |e| e * det_inv % 256 }
p m #=> encryption matrix
p inv #=> decryption matrix
identity = (inv * m).map { |e| e % 256 }
p identity #=> living proof that m * inv is the identity matrix
示例输出:
m = Matrix[[167, 8, 48], [54, 107, 25], [170, 184, 107]]
inv = Matrix[[119, 152, 136], [184, 235, 231], [174, 120, 59]]
【讨论】: