How does one convert a public EC code point and curve name into a PublicKey?

时光总嘲笑我的痴心妄想 提交于 2019-11-27 03:34:58

问题


I have two 32 byte long byte arrays representing the X and Y values for an EC Public Key. I know that the curve is the named curve "prime256v1".

How can I turn that into a Java PublicKey object?

The JCE appears to provide no facilities whatsoever to use named curves.

Bouncycastle's example code does not appear to compile with any version of bouncycastle I can find.

WTF?


回答1:


I don't see any way in JCE to use a named curve directly for a key, but it can be used for key generation, and the parameters can then be extracted from that key:

    // generate bogus keypair(!) with named-curve params
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
    ECGenParameterSpec gps = new ECGenParameterSpec ("secp256r1"); // NIST P-256 
    kpg.initialize(gps); 
    KeyPair apair = kpg.generateKeyPair(); 
    ECPublicKey apub  = (ECPublicKey)apair.getPublic();
    ECParameterSpec aspec = apub.getParams();
    // could serialize aspec for later use (in compatible JRE)
    //
    // for test only reuse bogus pubkey, for real substitute values 
    ECPoint apoint = apub.getW();
    BigInteger x = apoint.getAffineX(), y = apoint.getAffineY();
    // construct point plus params to pubkey
    ECPoint bpoint = new ECPoint (x,y); 
    ECPublicKeySpec bpubs = new ECPublicKeySpec (bpoint, aspec);
    KeyFactory kfa = KeyFactory.getInstance ("EC");
    ECPublicKey bpub = (ECPublicKey) kfa.generatePublic(bpubs);
    //
    // for test sign with original key, verify with reconstructed key
    Signature sig = Signature.getInstance ("SHA256withECDSA");
    byte [] data = "test".getBytes();
    sig.initSign(apair.getPrivate());
    sig.update (data);
    byte[] dsig = sig.sign();
    sig.initVerify(bpub);
    sig.update(data);
    System.out.println (sig.verify(dsig));

You do get the parameters, but apparently no longer linked to the OID, which might make a difference. In particular it may be treated as "arbitrary" or "explicit" in TLS and not work even though the TLS parties support that same curve by name.

Note that openssl uses the name prime256v1 but not everyone does. Java (sun.) uses secp256r1, or the OID. If you are actually getting this pubkey from openssl, note that JCE can directly read the X.509 SubjectPublicKeyInfo format, which openssl calls PUBKEY, including the named (OID) form.




回答2:


It turns out that there is, in fact, another way to do this. The AlgorithmParameters class can apparently be used to translate an ECGenParameterSpec, with a named curve, into an ECParameterSpec object that you can use with a KeyFactory to generate a PublicKey object:

            ECPoint pubPoint = new ECPoint(new BigInteger(1, x),new BigInteger(1, y));
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC", "SunEC");
            parameters.init(new ECGenParameterSpec("secp256r1"));
            ECParameterSpec ecParameters = parameters.getParameterSpec(ECParameterSpec.class);
            ECPublicKeySpec pubSpec = new ECPublicKeySpec(pubPoint, ecParameters);
            KeyFactory kf = KeyFactory.getInstance("EC");
            return (ECPublicKey)kf.generatePublic(pubSpec);


来源:https://stackoverflow.com/questions/22646792/how-does-one-convert-a-public-ec-code-point-and-curve-name-into-a-publickey

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!