【问题标题】:How to get the size of a RSA key in Java如何在 Java 中获取 RSA 密钥的大小
【发布时间】:2010-05-27 15:47:27
【问题描述】:

给定一个 java.security.interfaces.RSAKey,我如何获得它的大小?

【问题讨论】:

标签: java rsa


【解决方案1】:

你可以试试这个:

key.getModulus().bitLength();

【讨论】:

  • 请注意,如果您的密钥有八个前导零,则此策略可能会失败。不幸的是,在某些互操作情况下,需要选择 2 的幂。如果您尝试将 Java 生成的公钥导入 .Net 并使用它来加密数据,除非密钥长度符合预期,否则它将不会在 Java 中解密。如果您生成了 2048 位密钥,则不能为 .Net 提供 2040 位(密钥情况下为 8 个前导零)或 2052 位(如果将 BigInteger 转换为十六进制字符串,您可以获得额外的前导 0)的密钥。您必须准确地给它 2048 位。它会影响 OAEP 填充方案。
【解决方案2】:

(编辑:我在理解为 RSA 密钥生成的素数整数的限制之前写了这个回复。http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf我现在相信任何好的密钥生成器都应该确保模数在 2^(n -1) 和 2^n-1。因此,模的最小二进制补码表示将始终具有在创建密钥时为密钥长度指定的位数。因此,例如,如果您创建一个 2048 位的密钥,那么 key.getModulus().bitLength() 将始终返回 2048。)

对不起,当模数的最高有效位为 0 时,key.getModulus().bitLength() 不会返回不正确的值吗?例如,对于 2048 位密钥,如果模数的最高有效位为 0,则key.getModulus().bitLength() 将返回 2047(如果更多位为 0,则返回更少)。我认为在这种情况下所需的结果实际上是 2048 年。

BigInteger.bitLength() 的文档内容如下:

返回此 BigInteger 的最小二进制补码表示中的位数,不包括符号位。对于正 BigInteger,这相当于普通二进制表示中的位数。 (计算 (ceil(log2(this

恐怕需要对密钥的大小做出一些假设。例如,您必须假设您只会看到 1024、2048 或 4096 位密钥,然后执行以下操作:

int keySize;
int bitLength = key.getModulus().bitLength();
if (bitLength <= 512) {
  throw new IllegalArgumentException(...)
}
else if (bitLength <= 1024) {
  keySize = 1024;
}
else if (bitLength <= 2048) {
  keySize = 2048;
}
else if (bitLength <= 4096) {
  keySize = 4096;
}
else {
  throw new IllegalArgumentException(...)
}
return keySize;

此代码在(非常罕见的)场合仍然可能出错,例如,当 2048 位密钥的前 1048 位全为 0 时。不过,我认为这不必担心。

【讨论】:

  • 这段代码在任何情况下都是错误的。 key.getModulus().bitLength() 是由“密钥大小”或“密钥长度”术语定义的值。用任意选择的值替换它是完全错误的。
  • 奥列格,你是对的,当然。我添加了 EDIT 以解释我对密钥生成的主要因素的限制的误解。
  • 如果仍然偏执于糟糕的密钥生成器,可以使用向上取整:keySize = ((bitLength + 127)/128)*128。比猜测好。高 128 位全为零的可能性是 2^128 中的 1。
  • 不幸的是,在某些互操作情况下,需要选择 2 的幂。如果您尝试将 Java 生成的公钥导入 .Net 并使用它来加密数据,除非密钥长度符合预期,否则它将不会在 Java 中解密。如果您生成了 2048 位密钥,则不能为 .Net 提供 2040 位(密钥情况下为 8 个前导零)或 2052 位(如果将 BigInteger 转换为十六进制字符串,您可以获得额外的前导 0)的密钥。您必须准确地给它 2048 位。这并不总是会导致错误,但会影响 OAEP 填充方案。
【解决方案3】:

RSA 密钥的大小是其模数中的位数,因此您希望 myRSAKey.getModulus().bitLength().

【讨论】:

  • 晚了 4 分钟,该死! :P
【解决方案4】:

我同意 Wheezil 在接受的答案中提到的担忧。具有 8 个前导 0 位的模数将破坏该方法。这有 0.4% 的机会发生,在我看来这是不可接受的。所以我个人改用这个:

Cipher rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.ENCRYPT_MODE, yourKey);
int keyBitSize = rsa.getOutputSize(0) * Byte.SIZE;

...因为 RSA 输出大小始终与密钥的模数大小相同,即使输入长度为 0。

【讨论】:

    猜你喜欢
    • 2020-04-07
    • 2012-09-21
    • 1970-01-01
    • 1970-01-01
    • 2014-02-21
    • 2011-12-10
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    相关资源
    最近更新 更多