如何在BouncyCastle Java中编码ECDH公钥?

时间:2022-12-13 20:48:05

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. 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. Can anyone help?? Thanks!

我似乎不知道如何在BouncyCastle库的java版本中实现这一点,因为在java版本的库中似乎没有一个subject - publickeyinfofactory对象。但是,在Java中似乎有一个PublicKeyFactory类,所以看起来我可以使用相同的代码,但是我不知道如何在Java库中对公钥进行编码。谁能帮忙吗? ?谢谢!

-----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. Here is what I have in java:

这将完美地创建并返回一个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();
}

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. Can anyone please help!??!!? I'm about at my wits end! Thanks!!!!

在java中,似乎没有一个主题是publickeyinfofactory类,或者类似的东西可以使用aKeyPair.getPublic(),并能够生成编码的字节数组。谁能请帮助! ! ! ?我快疯了!谢谢! ! ! !

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

编辑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. When I attempt to decode them I get a DERNull exception. 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. I think there is just something missing when I convert the AsymmetricCipherKeys into the JCEEC Keys. I did notice there is another parameter in the JCEECPublicKey construct, the third parameter of 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). Any other suggestions? Thanks!!!

因此,我已经能够将公共/私有密钥转换为JCEEC密钥对象,并能够对它们进行编码。当我试图解码它们时,我得到一个DERNull异常。我使用常规的本地java KeyPairGenerator运行了一些其他的测试和生成的密钥,并且能够对密钥进行编码/解码,所以我知道这种方法是有效的。我认为,当我将不对称密码转换为JCEEC密钥时,会遗漏一些东西。我确实注意到了JCEECPublicKey构造中的另一个参数,ECKeySpec的第三个参数。唯一的问题是,我并不是很确定如何从我目前的代码中获得一个ECKeySpec(或者如果这就是问题的开始)。还有其他的建议吗?谢谢! ! !

1 个解决方案

#1


2  

Have you tried using the Bouncycastle SubjectPublicKeyInfo class? Something like:

你试过使用Bouncycastle subject ectpublickeyinfo类吗?喜欢的东西:

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类,它有一个getencode()方法,它产生(我认为)正确的答案。

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

#1


2  

Have you tried using the Bouncycastle SubjectPublicKeyInfo class? Something like:

你试过使用Bouncycastle subject ectpublickeyinfo类吗?喜欢的东西:

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类,它有一个getencode()方法,它产生(我认为)正确的答案。

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