【问题标题】:Is this way of generating a securerandom biginteger secure?这种生成安全随机大整数的方式安全吗?
【发布时间】:2021-06-21 01:27:47
【问题描述】:

所以我在java中尝试了这行代码,它生成一个40字节长的随机整数。我不知道它是否安全,我想知道是否有比我更有经验的人能解释一下。

我想知道这在密码学上是否安全。意思是这是一种生成 BigInteger 随机数的安全方法。如果它不安全,那么生成完整的加密随机 BigInteger 的好方法是什么。

SecureRandom random = new SecureRandom();
BigInteger key_limit = new BigInteger("10000000000000000000000000000000000000000");
int key_length = key_limit.bitLength();
BigInteger key_1 = new BigInteger(key_length, random);

【问题讨论】:

  • 只要new BigInteger(8 * 40, random),既然您使用的是SecureRandom,为什么它不具有密码安全性?
  • @Andreas 我只是想知道它是否安全,因为我的方法 xD。所以我不知道这是不是个好主意

标签: java security random biginteger


【解决方案1】:

您正在滚动自己的加密货币。

做好失败的准备。您最终编写的代码实际上是安全的可能性是无限大的。非常、非常、非常很容易出错。这些错误几乎总是极难测试(例如,您的算法可能会根据处理不同输入所需的时间来泄漏信息,从而让攻击者在几个小时内找出密钥。您是否打算编写一个检查是否所有尝试解码任何内容的测试,无论是实际密文、损坏的密文、密文的一半、专门设计用于通过检查处理所需时间来尝试获取关键信息的精心设计的输入,以及随机 gobbledygook 都需要完全相同的时间? 你知道你需要测试什么样的精心设计的输入吗?)

关于定时攻击,具体来说,一旦你写了BigInteger,你几乎肯定输了。编写一个不受时间攻击影响的基于 BI 的算法几乎是不可能的。

专家会将所有密钥和加密算法中间体保存为byte[] 形式。

所以,你做错了。不要滚动你自己的加密货币,你会搞砸的。使用现有算法。

如果你真的,真的,真的想走这条路,你需要在开始之前学习,很多。首先分析大量现有实现。试着去摸索每一行,试着去摸索每一个动作。例如,密码哈希检查算法可能包含以下代码:

public boolean isEqual(byte[] a, byte[] b) {
    if (a.length != b.length) throw new IllegalArgumentException("mismatched lengths");
    int len = a.length;
    boolean pass = true;
    for (int i = 0; i < len; i++) {
        if (a[i] != b[i]) pass = false;
    }
    return pass;
}

你可能会简单地得出结论:嗯。诡异的。我猜他们是从 C 或其他东西中复制它的,或者他们只是不知道他们可以完全删除该方法并用java.util.Arrays.equals(a, b); 替换它。哦,好吧,没关系。

你会错的 - 这就是我理解这一切的意思。假设没有错误。 Arrays.equals 可以受到时间攻击(它运行所花费的时间告诉你一些事情:不匹配越早,它返回的速度越快。这个方法需要相同的时间,但只有在两个输入是长度相等,因此如果发生这种情况,它会抛出而不是返回看似明显的false)。

如果您花这么多时间分析它们,那么您将多次讨论这个问题。

因此,在所有上下文中:

这个答案是火箭筒。你会炸掉你的脚。您不想编写此代码。你不想做你想做的事。 BigInteger 是错误的方法

new BigInteger(8 * 40, secureRandom); 将正确完成工作:生成一个介于 (0 和 2^320-1) 之间的随机数,包括 40 个字节。不多也不少。

可以按如下方式生成 40 字节的随机性:

byte[] key = new byte[40];
secureRandom.nextBytes(key);

但这仍然是一个严重的错误,除非你真的,真的,真的知道你在做什么(尝试找到一个有可靠作者或经过专家审查的现有实现)。

【讨论】:

  • 我只把它放入一个大整数中,用密码处理。密码是 US-ASCII 字节,然后转换为大整数,因为 java 不喜欢具有大 boi 数字的普通整数。
  • 有大量的开源加密实现。例如,bouncycastle 是开源的,有很多值得一看的地方。密码不是“US-ASCII 字节”。 “密码”的意思是“算法”,所以这没有意义。如果您的意思是:“钥匙” - 不,它不会。这将是原始字节。如果您的意思是:“加密的结果”,不,它不会。这将是原始字节。如果您看到文本,那些原始字节在 base64d 或诸如此类的位置。如果通过密码输入密钥,则会运行一个算法,将该密码转换为原始字节作为密钥。
  • 我理解密码不是“US-ASCII 字节”,我是说我的算法在加密过程中使用了 us-ascii 字节。对不起,如果我不清楚。如果你想查看我的加密算法,你可以在这里找到:github.com/N0tA1dan/Krypton
【解决方案2】:

您将获得一个BigInteger,其中包含一个安全生成的随机数。

但是,这种计算位长的方法(至少可以说)很奇怪。我不了解你,但大多数程序员会发现很难计算出该字符串中有多少个零。然后,计算将为您提供一个位数,使得 2bits 小于该数字。

(对我而言)直接指定位数并对其进行编码并添加注释来解释它会更有意义。

第一个近似值1 2(10*N) 是 1000N。但是,前者略大于后者。这意味着如果您的代码打算为您提供 40 字节的随机密钥,那么您计算出的密钥长度将减一。


1 - 有经验的程序员记得……没有经验的程序员可以使用程序员的计算器。

【讨论】:

  • 这个大数字正好是 40 位数字。 OP 认为这就是“40 字节的关键数据”的含义。 OP 在他们的木屋和竹屋里有一只讨厌的麝鼠出没,并要求您提供火箭筒。我不知道在这些问题上的 SO 政策是什么,但从道德/教育上讲,“把它交给他们,而不表明这可能不是最好的计划”不可能是正确的举措。
  • 您正在得出关于 OP 正在做什么的结论,而这实际上是不合理的。这个问题只是询问数字是否安全生成。它没有说明这个数字的用途(nadda)。
  • 你错过了我关于大十进制数字字符串的观点。普通程序员如何计算零? OP 已经告诉我们代码试图做什么这一事实并不能帮助一个必须在 6 个月内阅读代码的程序员的可怜草皮。
  • 你得出的结论是关于 OP 所做的事情实际上是不合理的 - 很明显,几乎是不言而喻的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
  • 1970-01-01
  • 2012-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
相关资源
最近更新 更多