【问题标题】:How to DER encode an ECDH Public Key in BouncyCastle Java如何在 BouncyCastle Java 中对 ECDH 公钥进行 DER 编码
【发布时间】:2011-11-04 18:44:40
【问题描述】:

所以我知道如何将 BouncyCastle C# 库中的公钥编码/解码为字节数组:

编码:

PublicKey = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(p1.Public).GetDerEncoded();

解码:

ECPublicKeyParameters pubKey = (ECPublicKeyParameters)PublicKeyFactory.CreateKey(OtherPublicKey);

我似乎无法弄清楚如何在 Java 版本的 BouncyCastle 库中执行此操作,因为在 Java 版本的库中似乎没有 SubjectPublicKeyInfoFactory 对象。但是,Java 中似乎有一个 PublicKeyFactory 类,所以看起来我可以使用相同的代码,但我不知道如何在 Java 库中对公钥进行 DER 编码。有人可以帮忙吗??谢谢!

--编辑------------------------------------------ ----------------

好的,这就是我目前在 C# 中的内容:

创建 ECDH 实例:

public static ECDHBasicAgreement CreateECDHInstance(out byte[] PublicKey)
    {
        IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDH");

        FpCurve curve = new FpCurve(
            new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
            new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
            new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b

        ECDomainParameters ecSpec = new ECDomainParameters(
            curve,
            curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
            new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307"), // n
            BigInteger.One); // h

        g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));

        AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair();
        ECDHBasicAgreement aKeyAgreeBasic = new ECDHBasicAgreement();
        aKeyAgreeBasic.Init(aKeyPair.Private);

        PublicKey = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(aKeyPair.Public).GetDerEncoded();

        return aKeyAgreeBasic;
    }

这将完美地创建并返回一个 ECDHBasicAgreement 对象,并以 der 编码的字节数组形式输出一个公钥。这是我在 java 中所拥有的:

public void testECDH() throws Exception
{
    AsymmetricCipherKeyPairGenerator g = new ECKeyPairGenerator();

    Fp curve = new Fp(
        new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
        new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
        new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b

    ECDomainParameters ecSpec = new ECDomainParameters(
        curve,
        curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
        new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307"), // n
        BigInteger.ONE); // h

    g.init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));

    AsymmetricCipherKeyPair aKeyPair = g.generateKeyPair();
    ECDHBasicAgreement aKeyAgreeBasic = new ECDHBasicAgreement();
    aKeyAgreeBasic.init(aKeyPair.getPrivate());

    // The part that doesn't work
    //byte[] publickey = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(aKeyPair.getPublic()).GetDerEncoded();
}

在 java 中,似乎没有 SubjectPublicKeyInfoFactory 类或可以采用 aKeyPair.getPublic() 并能够生成 DER 编码字节数组的等效类。有人可以帮忙吗!??!!?我快要崩溃了!谢谢!!!!

---------编辑 2 ----------------------------------- --------------------------------------------------

好的,这就是我现在的位置:

public void test2() throws Exception
{
    ECKeyPairGenerator g = new ECKeyPairGenerator();

    Fp curve = new Fp(
            new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
            new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
            new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b

    ECDomainParameters ecP = new ECDomainParameters(
            curve,
            curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
            new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307"), // n
            BigInteger.ONE); // h

    g.init(new ECKeyGenerationParameters(ecP, new SecureRandom()));

    // Generate key pair
    AsymmetricCipherKeyPair aKeys = g.generateKeyPair();

    JCEECPublicKey jpub = new JCEECPublicKey("EC", (ECPublicKeyParameters)aKeys.getPublic());
    JCEECPrivateKey jpriv = new JCEECPrivateKey("EC", (ECPrivateKeyParameters)aKeys.getPrivate());

    KeyPair aKeyPair = new KeyPair(jpub, jpriv);

    ECDHBasicAgreement aKeyAgree = new ECDHBasicAgreement();

    aKeyAgree.init(aKeys.getPrivate());

    byte[] encoded = aKeyPair.getPublic().getEncoded();
    // The part that breaks now (Exception DERNull)
    ECPublicKeyParameters decoded = decodeECPublicKeyParameters(encoded);
}

public static ECPublicKeyParameters decodeECPublicKeyParameters(byte[] pkByte) throws IOException {
    return (ECPublicKeyParameters) PublicKeyFactory.createKey(pkByte);
    }

所以我已经能够将公钥/私钥放入 JCEEC Key 对象中,并且能够对它们进行编码。当我尝试解码它们时,我得到一个 DERNull 异常。我使用常规的本机 java KeyPairGenerator 运行了一些其他测试并生成了密钥,并且能够对密钥进行编码/解码,所以我知道这种方法确实有效。我认为当我将 AsymmetricCipherKeys 转换为 JCEEC 密钥时缺少一些东西。我确实注意到 JCEECPublicKey 构造中还有另一个参数,即 ECKeySpec 的第三个参数。唯一的麻烦是,我不确定如何从我目前拥有的代码中获取 ECKeySpec(或者如果这甚至是开始的问题)。还有其他建议吗?谢谢!!!

【问题讨论】:

    标签: java bouncycastle


    【解决方案1】:

    您是否尝试过使用 Bouncycastle SubjectPublicKeyInfo 类?比如:

    byte [] derEncoded;
    //... 
    SubjectPublicKeyInfo pkInfo = new SubjectPublicKeyInfo((ASN1Sequence)ASN1Object.fromByteArray(derEncoded))
    

    编辑:

    有一个简单但有点不满意的方法。您可以使用 JCEPublicKey 类,它有一个 getEncoded() 方法,可以产生(我认为)正确答案。

    编辑 2:

    我边走边学 :) 事实证明,您必须在算法参数中识别椭圆曲线,这是有道理的。这是一个细微的变化。

        g.init(new ECKeyGenerationParameters(ecP, new SecureRandom()));
    
        // Generate key pair
        AsymmetricCipherKeyPair aKeys = g.generateKeyPair();
    
        ECParameterSpec ecSpec = new ECParameterSpec(ecP.getCurve(), ecP.getG(), ecP.getN());
        JCEECPublicKey jpub = new JCEECPublicKey("EC",
                (ECPublicKeyParameters) aKeys.getPublic(), ecSpec);
        JCEECPrivateKey jpriv = new JCEECPrivateKey("EC",
                (ECPrivateKeyParameters) aKeys.getPrivate(), jpub,  ecSpec);
    

    【讨论】:

    • 感谢 GregS 的回复。是的,这很有帮助,但我试图弄清楚如何获取一个公钥对象并将其编码为一个字节数组。此代码将采用字节数组并将其解码为公钥对象。
    • @hobeau 你知道我也不知道该怎么做。我还在找。您总是可以“手工”完成,这有点难看。
    • 好的,所以 Java BouncyCastle 确实有 SubjectPublicKeyInfo 类,并且对象有 getDEREncoded(),但是,我不知道如何将我的 KeyPair.getPublic() 这是一个 CipherParameters 放入 SubjectPublicKeyInfo 对象。有什么想法吗?
    • 嘿 GregS,非常感谢您一直关注我以及迄今为止的所有帮助。我尝试了您的代码,它似乎可以工作,但是当我尝试使用以下方法对其进行解码时: return (ECPublicKeyParameters) PublicKeyFactory.createKey(pkByte);它返回了一个 DERNull 异常。我查看了 PublicKeyFactory.createKey ,它看起来像是试图使用 ASN1Object.fromByteArray 解码编码的密钥以创建一个 SubjectPublicKeyInfo 对象并且它以某种方式失败。关于如何将 JCEECPublicKey 对象转换为 SubjectPublicKeyInfo 对象的任何想法?
    • 格雷格,我真的欠你一杯啤酒。非常感谢,你救了我的命。
    猜你喜欢
    • 2014-10-16
    • 2019-06-24
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 2018-09-30
    • 2012-10-24
    • 2017-04-16
    • 2012-05-09
    相关资源
    最近更新 更多