简体   繁体   English

如何在BouncyCastle Java中对ECDH公钥进行DER编码

[英]How to DER encode an ECDH Public Key in BouncyCastle Java

So I know how to encode/decode a public key in the BouncyCastle C# library into a byte array: 所以我知道如何将BouncyCastle C#库中的公钥编码/解码为字节数组:

Encode: 编码:

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

Decode: 解码:

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

I can't seem to figure out how to do this in the java version of the BouncyCastle Library since there doesn't seem to be a SubjectPublicKeyInfoFactory object in the Java version of the library. 我似乎无法弄清楚如何在Java版本的BouncyCastle库中做到这一点,因为在Java版本的库中似乎没有SubjectPublicKeyInfoFactory对象。 There does, however, seem to be a PublicKeyFactory class in Java so it looks like I can just use the same code but I don't know how to DER encode the public key in the java library. 但是,在Java中似乎有一个PublicKeyFactory类,所以看起来我可以使用相同的代码,但我不知道如何对Java库中的公钥进行DER编码。 Can anyone help?? 谁能帮忙? Thanks! 谢谢!

-----EDIT--------------------------------------------------------- - - -编辑 - - - - - - - - - - - - - - - - - - - - - - -------------

Ok, so here is what I have so far in C#: 好的,所以这就是我目前在C#中所拥有的:

Create the ECDH instance: 创建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;
    }

This creates and returns a ECDHBasicAgreement object perfectly and outputs a public key in der encoded byte array form. 这将完美地创建并返回ECDHBasicAgreement对象,并以编码的字节数组形式输出公钥。 Here is what I have in java: 这是我在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();
}

In java, there doesn't seem to be a SubjectPublicKeyInfoFactory class or the equivalent that can take the aKeyPair.getPublic() and be able to generate a DER encoded byte array. 在java中,似乎没有SubjectPublicKeyInfoFactory类或可以采用aKeyPair.getPublic()并且能够生成DER编码的字节数组的等价物。 Can anyone please help!??!!? 任何人都可以帮忙!?? !!? I'm about at my wits end! 我的智慧结束了! Thanks!!!! 谢谢!!!!

----------EDIT 2 ------------------------------------------------------------------------- ---------- EDIT 2 -------------------------------------- -----------------------------------

Ok, so here's where I'm at now: 好的,所以这就是我现在所处的位置:

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);
    }

So I've been able to get the public/private keys into JCEEC Key objects and have been able to encode them. 所以我已经能够将公钥/私钥放入JCEEC Key对象中并且能够对它们进行编码。 When I attempt to decode them I get a DERNull exception. 当我尝试解码它们时,我得到了一个DERNull异常。 I ran some other tests and generated keys using the regular native java KeyPairGenerator and was able to encode/decode the keys so I know that this method does work. 我使用常规的原生Java KeyPairGenerator运行了一些其他测试并生成了密钥,并且能够对密钥进行编码/解码,因此我知道这种方法确实有效。 I think there is just something missing when I convert the AsymmetricCipherKeys into the JCEEC Keys. 我认为将AsymmetricCipherKeys转换为JCEEC密钥时会出现一些缺失。 I did notice there is another parameter in the JCEECPublicKey construct, the third parameter of ECKeySpec. 我注意到JCEECPublicKey构造中有另一个参数,ECKeySpec的第三个参数。 Only trouble is, I'm not exactly sure how to get an ECKeySpec out of the code I have so far (or if thats even the problem to begin with). 唯一的麻烦是,我不确定如何从我到目前为止的代码中获取ECKeySpec(或者如果这甚至是问题开始)。 Any other suggestions? 还有其他建议吗? Thanks!!! 谢谢!!!

Have you tried using the Bouncycastle SubjectPublicKeyInfo class? 您是否尝试过使用Bouncycastle SubjectPublicKeyInfo类? Something like: 就像是:

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

EDIT: 编辑:

There is an easy if somewhat unsatisfying way. 有一种简单但不太令人满意的方式。 You can use the JCEPublicKey class and it has a getEncoded() method that produces (I think) the correct answer. 您可以使用JCEPublicKey类,它有一个getEncoded()方法,可以生成(我认为)正确的答案。

EDIT 2: 编辑2:

I'm learning as I go :) It turns out you must identify the elliptic curve in the algorithm parameters, which makes sense. 我正在学习,但事实证明你必须在算法参数中识别椭圆曲线,这是有道理的。 Here is a slight change that does that. 这是一个微小的变化。

    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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM