尝试了解Java RSA密钥大小

11

密钥生成器被初始化为1024,那么为什么打印出的大小是635和162?

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

public class TEST {

    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
    keyPairGenerator.initialize(1024);
    return keyPairGenerator.generateKeyPair();
    }

    public static void main(String[] args) throws Exception {

    KeyPair keyPair = generateKeyPair();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

    System.out.println("Size = " + privateKey.getEncoded().length);
    System.out.println("Size = " + publicKey.getEncoded().length);

    }

}
2个回答

27

RSA密钥由模数和指数构成。密钥大小是指模数中的位数。因此,即使没有任何编码开销,存储1024位密钥需要超过128个字节。

getEncoded()返回ASN.1 DER编码的对象。私钥甚至包含CRT参数,因此非常大。

要获取密钥大小,请执行以下操作:

System.out.println("Key size = " + publicKey.getModulus().bitLength());

以下是相关的ASN.1对象:

RSAPrivateKey ::= SEQUENCE {
    version           Version,
    modulus           INTEGER,  -- n
    publicExponent    INTEGER,  -- e
    privateExponent   INTEGER,  -- d
    prime1            INTEGER,  -- p
    prime2            INTEGER,  -- q
    exponent1         INTEGER,  -- d mod (p-1)
    exponent2         INTEGER,  -- d mod (q-1)
    coefficient       INTEGER,  -- (inverse of q) mod p
    otherPrimeInfos   OtherPrimeInfos OPTIONAL
}


RSAPublicKey ::= SEQUENCE {
    modulus           INTEGER,  -- n
    publicExponent    INTEGER   -- e
}

对于未来在谷歌上找到此内容的其他人,类sun.security.util.KeyUtil有一个getKeySize函数,它接受一个密钥,并根据创建它的算法使用不同的函数返回适当的数字。对于OP的“RSA”密钥对,它使用getModulus().bitLength()。(我知道sun.security包不是为程序员而设计的,但是您可以查看最新版本的JDK的源代码作为示例。) - Ti Strga
不完全正确。JCE使用通用编码,可以处理多个算法——来自X.509/PKIX的SubjectPublicKeyInfo和来自PKCS8/rfc5208的PrivateKeyInfo,请参阅java.security.Key的javadoc——它们(两者)都包括AlgorithmIdentifier,指定RSA的OID以及您引用的PKCS1结构,分别包装在BIT STRING和OCTET STRING中。这会增加更多开销。 - dave_thompson_085

6

第一条提示:1024位 = 128字节

第二条提示:privateKey.getEncoded() 返回一个编码表示(即不是原始数据)。


3
“密钥大小”对于不同的编码人员意义不同,与密钥没有直接关系。在RSA算法中,它指的是模数的大小。(您应该使用getModulus()函数)。请参考ZZ Coder的回答。 - leonbloy
有些问题,getModulus返回了一个309位数的数字。如果这意味着大小为309,则仍不是我设置的大小(1024)。 - The Student
3
第三个提示:1024 * Log10(2) = 308.25 => 1024位 ~ 309个十进制数字。 - leonbloy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接