我正在尝试使用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
}
供参考:生成我改编自this GitHub issue的Curve25519键的代码以及生成并导出我改编自this Bouncy Castle example的整个密钥环的代码。
但是,上面的代码可以使用ECNamedCurveTable
(例如prime256v1
)中的曲线导出一个可导入的密钥环(很好,不能导入到GnuPG中,因为SHA1仅受Bouncy Castle支持用于密钥校验和生成)。
对于使用Curve25519创建的密钥,为什么使用ECNamedCurveTable
规范创建的密钥,为什么JCA密钥对和OpenPGP密钥对之间的转换失败?我是否缺少某些东西?Bouncy Castle不支持OpenPGP密钥自定义曲线吗?