无法通过Bounce Castle使用Curve25519生成DSA / ECDH密钥用作OpenPGP密钥

时间:2019-12-10 15:22:24

标签: java bouncycastle openpgp ecdh

我正在尝试使用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密钥自定义曲线吗?

0 个答案:

没有答案