生成密钥对只有两行代码,但默认值、边界和耗时都有细节。这篇用多个 JDK 版本和 OpenSSL 量出:默认参数怎么随版本变化,RSA 与 EC 能接受什么参数,生成耗时的波动,以及固定种子能不能重现密钥。
[JDK 17]
RSA 不 initialize 直接 generateKeyPair():2048 位模数;公钥编码 294 字节、私钥编码 1217 字节;提供者 SunRsaSign
DSA 不 initialize 直接 generateKeyPair():2048 位素数 p;公钥编码 838 字节、私钥编码 608 字节;提供者 SUN
EC 不 initialize 直接 generateKeyPair():曲线阶 256 位;公钥编码 91 字节、私钥编码 67 字节;提供者 SunEC
DH 不 initialize 直接 generateKeyPair():2048 位素数 p;公钥编码 556 字节、私钥编码 327 字节;提供者 SunJCE
Ed25519 不 initialize 直接 generateKeyPair():EdDSA;公钥编码 44 字节、私钥编码 48 字节;提供者 SunEC
X25519 不 initialize 直接 generateKeyPair():XDH;公钥编码 44 字节、私钥编码 48 字节;提供者 SunEC
RSASSA-PSS 不 initialize 直接 generateKeyPair():2048 位模数;公钥编码 292 字节、私钥编码 1217 字节;提供者 SunRsaSign
[JDK 21]
RSA 不 initialize 直接 generateKeyPair():3072 位模数;公钥编码 422 字节、私钥编码 1794 字节;提供者 SunRsaSign
DSA 不 initialize 直接 generateKeyPair():2048 位素数 p;公钥编码 838 字节、私钥编码 608 字节;提供者 SUN
EC 不 initialize 直接 generateKeyPair():曲线阶 384 位;公钥编码 120 字节、私钥编码 80 字节;提供者 SunEC
DH 不 initialize 直接 generateKeyPair():3072 位素数 p;公钥编码 813 字节、私钥编码 459 字节;提供者 SunJCE
Ed25519 不 initialize 直接 generateKeyPair():EdDSA;公钥编码 44 字节、私钥编码 48 字节;提供者 SunEC
X25519 不 initialize 直接 generateKeyPair():XDH;公钥编码 44 字节、私钥编码 48 字节;提供者 SunEC
RSASSA-PSS 不 initialize 直接 generateKeyPair():3072 位模数;公钥编码 420 字节、私钥编码 1791 字节;提供者 SunRsaSign
[JDK 27]
RSA 不 initialize 直接 generateKeyPair():3072 位模数;公钥编码 422 字节、私钥编码 1793 字节;提供者 SunRsaSign
DSA 不 initialize 直接 generateKeyPair():2048 位素数 p;公钥编码 838 字节、私钥编码 609 字节;提供者 SUN
EC 不 initialize 直接 generateKeyPair():曲线阶 384 位;公钥编码 120 字节、私钥编码 80 字节;提供者 SunEC
DH 不 initialize 直接 generateKeyPair():3072 位素数 p;公钥编码 812 字节、私钥编码 459 字节;提供者 SunJCE
Ed25519 不 initialize 直接 generateKeyPair():EdDSA;公钥编码 44 字节、私钥编码 48 字节;提供者 SunEC
X25519 不 initialize 直接 generateKeyPair():XDH;公钥编码 44 字节、私钥编码 48 字节;提供者 SunEC
RSASSA-PSS 不 initialize 直接 generateKeyPair():3072 位模数;公钥编码 420 字节、私钥编码 1792 字节;提供者 SunRsaSignRSA initialize(511):InvalidParameterException:java.security.InvalidAlgorithmParameterException: Invalid key sizes RSA initialize(512):成功,模数 512 位 RSA initialize(1023):成功,模数 1023 位 RSA initialize(1024):成功,模数 1024 位 RSA initialize(2048):成功,模数 2048 位 RSA initialize(4097):成功,模数 4097 位 RSA initialize(16384):成功(未实际生成,只检查参数) RSA initialize(16385):InvalidParameterException:java.security.InvalidAlgorithmParameterException: Invalid key sizes 默认公钥指数 e = 65537 RSAKeyGenParameterSpec(2048, e = 3):成功,公钥指数 3 RSAKeyGenParameterSpec(2048, e = 17):成功,公钥指数 17 RSAKeyGenParameterSpec(2048, e = 65537):成功,公钥指数 65537 RSAKeyGenParameterSpec(2048, e = 65539):成功,公钥指数 65539 RSAKeyGenParameterSpec(2048, e = 2):InvalidAlgorithmParameterException:Public exponent must be an odd number RSAKeyGenParameterSpec(2048, e = 4):InvalidAlgorithmParameterException:Public exponent must be an odd number RSAKeyGenParameterSpec(2048, e = 1):InvalidAlgorithmParameterException:Public exponent must be 3 or larger 私钥是 RSAPrivateCrtKey:p 1024 位,q 1024 位,p×q = n true,d 2045 位,保存了 CRT 参数 dP、dQ、qInv 生成 200 把 initialize(2048) 的 RSA 密钥:模数恰好 2048 位的有 200 把
EC initialize(192):ProviderException:Curve not supported: secp192r1 [NIST P-192,X9.62 prime192v1] (1.2.840.10045.3.1.1)
EC initialize(224):ProviderException:Curve not supported: secp224r1 [NIST P-224] (1.3.132.0.33)
EC initialize(255):InvalidParameterException:No EC parameters available for key size 255 bits
EC initialize(256):成功,曲线 secp256r1 [NIST P-256,阶 256 位
EC initialize(384):成功,曲线 secp384r1 [NIST P-384] (1.3.132.0.34),阶 384 位
EC initialize(521):成功,曲线 secp521r1 [NIST P-521] (1.3.132.0.35),阶 521 位
EC initialize(522):InvalidParameterException:No EC parameters available for key size 522 bits
ECGenParameterSpec("secp256r1"):成功,阶 256 位
ECGenParameterSpec("secp384r1"):成功,阶 384 位
ECGenParameterSpec("secp521r1"):成功,阶 521 位
ECGenParameterSpec("secp256k1"):InvalidAlgorithmParameterException:Curve not supported: secp256k1 (1.3.132.0.10)
ECGenParameterSpec("secp224r1"):InvalidAlgorithmParameterException:Curve not supported: secp224r1 [NIST P-224] (1.3.132.0.33)
ECGenParameterSpec("brainpoolP256r1"):InvalidAlgorithmParameterException:Curve not supported: brainpoolP256r1 (1.3.36.3.3.2.8.1.1.7)
ECGenParameterSpec("prime256v1"):InvalidAlgorithmParameterException:Unknown curve name: prime256v1
ECGenParameterSpec("NIST P-256"):成功,阶 256 位
ECGenParameterSpec("X9.62 prime256v1"):成功,阶 256 位
ECGenParameterSpec("1.2.840.10045.3.1.7"):成功,阶 256 位
所有提供者里注册的 KeyPairGenerator 算法:[DSA, DiffieHellman, EC, Ed25519, Ed448, EdDSA, RSA, RSASSA-PSS, X25519, X448, XDH]RSA 2048 30 次:最快 28.51 ms,中位数 65.21 ms,最慢 294.14 ms(最慢 / 中位数 = 4.5) RSA 3072 30 次:最快 99.32 ms,中位数 275.19 ms,最慢 786.68 ms(最慢 / 中位数 = 2.9) RSA 4096 12 次:最快 724.95 ms,中位数 1226.56 ms,最慢 2275.17 ms(最慢 / 中位数 = 1.9) EC 256 200 次:最快 0.12 ms,中位数 0.14 ms,最慢 0.25 ms(最慢 / 中位数 = 1.8) EC 384 200 次:最快 0.66 ms,中位数 0.73 ms,最慢 1.58 ms(最慢 / 中位数 = 2.2) EC 521 200 次:最快 1.17 ms,中位数 1.48 ms,最慢 2.19 ms(最慢 / 中位数 = 1.5) Ed25519 200 次:最快 0.22 ms,中位数 0.27 ms,最慢 0.80 ms(最慢 / 中位数 = 2.9) X25519 200 次:最快 0.11 ms,中位数 0.18 ms,最慢 0.29 ms(最慢 / 中位数 = 1.6) DH 2048 6 次:最快 0.31 ms,中位数 0.34 ms,最慢 0.38 ms(最慢 / 中位数 = 1.1) DSA 2048 6 次:最快 0.33 ms,中位数 0.34 ms,最慢 0.36 ms(最慢 / 中位数 = 1.1)
SHA1PRNG:用 setSeed(12345) 的 SecureRandom 各生成一把 RSA 1024 密钥,两次的模数完全相同(密钥可重现):[88e453ac7d8e84fdc67b82c9, 88e453ac7d8e84fdc67b82c9] DRBG:用 setSeed(12345) 的 SecureRandom 各生成一把 RSA 1024 密钥,两次的模数不同:[801b409b5ada23633e8839c4, c017bb169cff4ac17c038a51] NativePRNG:用 setSeed(12345) 的 SecureRandom 各生成一把 RSA 1024 密钥,两次的模数不同:[9368ab1444a2ffc035dd3588, 8ac7ef1e04d9fb29d4ea3cb4] SHA1PRNG + setSeed(1):EC P-256 私钥相同 = true 默认 new SecureRandom() 的算法 NativePRNG,提供者 SUN;KeyPairGenerator 不传 SecureRandom 时使用 JDK 内部的默认实例(与它相同类型) SHA1PRNG:先 setSeed(42) 再取字节 d50ac288b90ede2e;先取字节再 setSeed(42)(补充种子而不是替换)得到 986aadeb165af734(两者不同:setSeed 在第一次取字节之后只是追加熵)
RSA:私钥 getFormat() = PKCS#8,公钥 getFormat() = X.509,私钥 1217 字节 EC:私钥 getFormat() = PKCS#8,公钥 getFormat() = X.509,私钥 67 字节 Ed25519:私钥 getFormat() = PKCS#8,公钥 getFormat() = X.509,私钥 48 字节 openssl pkey 读取 RSA.priv.der:Private-Key: (2048 bit, 2 primes);读取 RSA.pub.der:Public-Key: (2048 bit) openssl pkey 读取 EC.priv.der:Private-Key: (256 bit field, 128 bit security level);读取 EC.pub.der:Public-Key: (256 bit field, 128 bit security level) openssl pkey 读取 Ed25519.priv.der:ED25519 Private-Key:;读取 Ed25519.pub.der:ED25519 Public-Key: