Loading raw 64-byte long ECDSA public key in Java

后端 未结 5 1696
我寻月下人不归
我寻月下人不归 2020-11-29 09:37

I have a raw (r,s) format ECDSA NIST P-256 public key. It seems that there is no simple way to load it into an object that implements java.security.interfaces.ECPublicKey.

5条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-11-29 10:09

    The EC Public Key is a point that consists of x and y co-ordinate. I wrote the following code segment once to convert EC x, y point to publicKey object. Hope this will help you. For your information:

    rawPubKey = 04 + x co-ordinate + y co-ordinate (Hex String)

    curveName = P-256 (String)

    Example EC Public Key Point for P-256:

    rawPubKey = 04 6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296 4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5

    BC Provider: You need Bouncy Castle provider. I used bcprov-jdk15on-149.jar, but you can download the latest version from here.

    /**
     * This method converts the uncompressed raw EC public key into java.security.interfaces.ECPublicKey
     * @param rawPubKey 
     * @param curveName
     * @return java.security.interfaces.ECPublicKey
     */
    public ECPublicKey ucPublicKeyToPublicKey(String rawPubKey, String curveName) {
        byte[] rawPublicKey = Helper.toByte(rawPubKey); 
        ECPublicKey ecPublicKey = null;
        KeyFactory kf = null;
        
        ECNamedCurveParameterSpec ecNamedCurveParameterSpec = ECNamedCurveTable.getParameterSpec(curveName);
        ECCurve curve = ecNamedCurveParameterSpec.getCurve();
        EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, ecNamedCurveParameterSpec.getSeed());
        java.security.spec.ECPoint ecPoint = ECPointUtil.decodePoint(ellipticCurve, rawPublicKey);
        ECParameterSpec ecParameterSpec = EC5Util.convertSpec(ellipticCurve, ecNamedCurveParameterSpec);
        java.security.spec.ECPublicKeySpec publicKeySpec = new java.security.spec.ECPublicKeySpec(ecPoint, ecParameterSpec);
        
        kf = java.security.KeyFactory.getInstance("EC");
        
        try {
            ecPublicKey = (ECPublicKey) kf.generatePublic(publicKeySpec);
        } catch (Exception e) {
            System.out.println("Caught Exception public key: " + e.toString());
        }
        
        return ecPublicKey;
    }
    

    EDIT: Here is toByte() method:

    public static byte[] toByte(String hex) {
            if (hex == null)
                return null;
            hex = hex.replaceAll("\\s", "");
            byte[] buffer = null;
            if (hex.length() % 2 != 0) {
                hex = "0" + hex;
            }
            int len = hex.length() / 2;
            buffer = new byte[len];
            for (int i = 0; i < len; i++) {
                buffer[i] = (byte) Integer.parseInt(
                        hex.substring(i * 2, i * 2 + 2), 16);
            }
            return buffer;
        }
    

    But you can use your own implementation. Here is another one:

    import javax.xml.bind.DatatypeConverter;
    public static byte[] toByte(String hex) {{
        return DatatypeConverter.parseHexBinary(hex);
    }
    

提交回复
热议问题