这是一个实现Merkle-Hellman背包密码系统的程序的代码片段。
// Generates keys based on input data size
private void generateKeys(int inputSize)
{
// Generating values for w
// This first value of the private key (w) is set to 1
w.addNode(new BigInteger("1"));
for (int i = 1; i < inputSize; i++)
{
w.addNode(nextSuperIncreasingNumber(w));
}
// Generate value for q
q = nextSuperIncreasingNumber(w);
// Generate value for r
Random random = new Random();
// Generate a value of r such that r and q are coprime
do
{
r = q.subtract(new BigInteger(random.nextInt(1000) + ""));
}
while ((r.compareTo(new BigInteger("0")) > 0) && (q.gcd(r).intValue() != 1));
// Generate b such that b = w * r mod q
for (int i = 0; i < inputSize; i++)
{
b.addNode(w.get(i).getData().multiply(r).mod(q));
}
}
请告诉我以下几行:
do
{
r = q.subtract(new BigInteger(random.nextInt(1000) + ""));
}
while ((r.compareTo(new BigInteger("0")) > 0) && (q.gcd(r).intValue() != 1));
(1)为什么用上限1000生成随机数?
(2)为什么从q中减去?
答案 0 :(得分:2)
代码正在搜索与已选择的值q
共存的值。在我看来,它的表现相当糟糕,但你提到它是一个模拟器?我不确定这意味着什么,但也许只是意味着代码快速而肮脏而不是缓慢而安全。
直接回答您的问题:
- 为什么使用上限1000生成随机数?
醇>
Merkle-Hellman algorithm 确实表明r
应该是'随机'。这样做的实施是非常随意的;这可能是什么让你失望。从技术上讲,代码不是算法,因为不保证循环终止。从理论上讲,r
的伪随机候选选择可能是一个任意长的数字序列,它不是q
的共同素数,导致无限循环。
1000的上限可以是确保所选的r
足够大。一般来说,大键比小键更容易破解,因此如果q
很大,那么此代码只能找到大的r
。
获得随机共素的更确定的方法是测试低于q
的每个数,生成一个联合素数列表并随机选择一个。这可能会更安全,因为攻击者知道q
和r
在彼此的1000之内会有显着缩小的搜索空间。
- 为什么从q中减去?
醇>
减法很重要,因为r
必须小于q
。 Merkle-Hellmen算法以这种方式指定它。我不相信它需要那样。公钥是通过将 w 中的每个元素乘以 r 并取模数 q 生成的。如果 r 非常大,大于 q ,它似乎会进一步混淆 q 和 w
另一方面,Merkle-Hellmen的解密步骤取决于每个加密字母的modular inverse x r -1 mod q 。 r
&gt;可能会妨碍此操作。 q
;好像它仍然可以解决。
但是,如果nextInt
可以返回0,那么循环的迭代就像q
一样浪费,r
必须不同(gcd(a,a)
只是{{1} }})。
分解代码:
a
至少尝试一次。在调用方法之前,do
可能为null或未定义。
r
查找 r = q.subtract(new BigInteger(random.nextInt(1000) + ""));
和q
之间的候选值。
q - 1000
继续,直到找到while ((r.compareTo(new BigInteger("0")) > 0) && (q.gcd(r).intValue() != 1));
为止:
r
和r.compareTo(new BigInteger("0")) > 0
,q
合作。显然,随机选择的数字不能保证与另一个其他数字共同使用,因此随机生成的候选者可能不适用于此q.gcd(r).intValue() != 1
。那清除了吗?我不得不承认我不是Merkle-Hellman的专家。