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

时间:2011-11-04 18:44:41

标签: java bouncycastle

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

编码:

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

解码:

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

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

- - - - EDIT ----------------------------------------- ----------------

好的,所以这就是我目前在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对象,并以编码的字节数组形式输出公钥。这是我在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(或者如果这甚至是问题开始)。还有其他建议吗?感谢!!!

1 个答案:

答案 0 :(得分:2)

您是否尝试过使用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);