我正在尝试使用 Bouncy Castle 的 Java API 使用 DSA 和 ECDH 密钥对组合生成 OpenPGP 密钥环。为了不依赖 NIST 曲线,我选择了 Curve25519 作为我想要使用的函数。但是,在密钥环导出后,我得到一个IllegalArgumentException
:
java.lang.IllegalArgumentException: illegal object in getInstance: org.bouncycastle.asn1.DLSequence at: org.bouncycastle.asn1.ASN1ObjectIdentifier.getInstance(Unknown Source) at: org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyConverter.getPGPPublicKey(Unknown Source) at: org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyConverter.getPGPPublicKey(Unknown Source) at: org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair.getPublicKey(Unknown Source) at: org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair.(Unknown Source)
我用来生成两个密钥对的代码如下:
String identity, passphrase; // User input
OutputStream secretOut, publicOut; // File streams
try {
KeyPairGenerator dsaKeygen = KeyPairGenerator.getInstance ("DSA", "BC");
KeyPairGenerator ecdhKeygen = KeyPairGenerator.getInstance ("ECDH", "BC");
dsaKeygen.initialize (2048);
KeyPair dsaKeypair = dsaKeygen.generateKeyPair ();
X9ECParameters ecParams = CustomNamedCurves.getByName ("Curve25519");
ECParameterSpec ecSpecs = new ECParameterSpec (
ecParams.getCurve (),
ecParams.getG (),
ecParams.getN (),
ecParams.getH (),
ecParams.getSeed ()
);
ecdhKeygen.initialize (ecSpecs, new SecureRandom ());
KeyPair ecdhKeypair = ecdhKeygen.generateKeyPair ();
PGPKeyPair dsaPgpKeypair = new JcaPGPKeyPair (PGPPublicKey.DSA, dsaKeypair, new Date ());
PGPKeyPair ecdhPgpKeypair = new JcaPGPKeyPair (PGPPublicKey.ECDH, ecdhKeypair, new Date ()); // Fails
PGPSignatureSubpacketGenerator flagsGen = new PGPSignatureSubpacketGenerator ();
flagsGen.setKeyFlags (
true,
KeyFlags.CERTIFY_OTHER |
KeyFlags.SIGN_DATA |
KeyFlags.ENCRYPT_COMMS |
KeyFlags.ENCRYPT_STORAGE
);
PGPDigestCalculator sha1Calculator = new JcaPGPDigestCalculatorProviderBuilder ()
.build ()
.get (HashAlgorithmTags.SHA1);
PGPKeyRingGenerator keyRingGenerator = new PGPKeyRingGenerator (
PGPSignature.POSITIVE_CERTIFICATION,
dsaPgpKeypair,
identity,
sha1Calculator,
flagsGenerator.generate (),
null,
new JcaPGPContentSignerBuilder (dsaPgpKeypair.getPublicKey ().getAlgorithm (), AlgorithmTags.SHA1),
new JcePBESecretKeyEncryptorBuilder (PGPEncryptedDate.AES_256, sha1Calculator)
.setProvider ("BC")
.build (passphrase.toCharArray ())
);
keyRingGenerator.addSubKey (ecdhPgpKeypair);
keyRingGenerator.generateSecretKeyRing ().encode (secretOut);
secretOut.close ();
keyRingGenerator.generatePublicKeyRing ().encode (publicOut);
publicOut.close ();
} catch (Exception e) {
// obligatory exception handling
}
供参考:生成 Curve25519 密钥的代码我改编自这个 GitHub 问题,以及生成和导出整个密钥环的代码我改编自这个 Bouncy Castle 示例。
但是,上面的代码使用ECNamedCurveTable
来自prime256v1
.
为什么 JCA 密钥对和 OpenPGP 密钥对之间的转换对于使用 Curve25519 创建的密钥失败,而不是使用来自 的规范创建的密钥ECNamedCurveTable
?我是否遗漏了某些东西,或者 Bouncy Castle 不支持 OpenPGP 键的自定义曲线?