如何生成有效的ECDSA EC密钥对?

sne*_*tMs 2 bouncycastle elliptic-curve dsa ecdsa spongycastle

我正在尝试使用Android中的SpongyCastle生成ECDSA密钥对。这是代码:

static {
    Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
}

public static KeyPair generate() {
        ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("prime256v1");
        KeyPairGenerator generator = KeyPairGenerator.getInstance("ECDSA", "SC");
        generator.initialize(ecSpec, new SecureRandom());
        KeyPair keyPair = g.generateKeyPair();
        Log.i(TAG, "EC Pub Key generated: " + utils.bytesToHex(keyPair.getPublic().getEncoded()));
        Log.i(TAG, "EC Private Key generated: " + utils.bytesToHex(keyPair.getPrivate().getEncoded()));            
       return generator.generateKeyPair();
}
Run Code Online (Sandbox Code Playgroud)

出现错误是因为我总是得到类似公钥的示例:

3059301306072A8648CE3D020106082A8648CE3D03010703420004483ABA9F322240010ECF00E818C041A60FE71A2BD64C64CD5A60519985F110AEDE6308027D2730303F5E2478F083C7F5BB683DCAC22BFEB62F3A48BD01009F40

和私钥:

308193020100301306072A8648CE3D020106082A8648CE3D030107047930770201010420219AB4B3701630973A4B2917D53F69A4BE6DAD61F48016BFEF147B2999575CB2A00A06082A8648CE3D030107A14403420004483ABA9F322240010ECF00E818C041A60FE71A2BD64C64CD5A60519985F110AEDE6308027D2730303F5E2478F083C7F5BB683DCAC22BFEB62F3A48BD01009F40

站点ECDSA样本给了我“无效的ECDSA签名消息”,它们似乎与那个较小的私有密钥有很大不同,并且总是以在同一站点中生成的“ 04”公共密钥开头。

另外,我的后端验证给我错误“无效点编码0x30”

后端Java方法检查为:

public ECPublicKey getPublicKeyFromHex(String publicKeyHex)
        throws NoSuchAlgorithmException, DecoderException, ApplicationGenericException {
    byte[] rawPublicKey = Hex.decodeHex(publicKeyHex.toCharArray());
    ECPublicKey ecPublicKey = null;
    KeyFactory kf = null;

    ECNamedCurveParameterSpec ecNamedCurveParameterSpec = ECNamedCurveTable.getParameterSpec("prime256v1");
    ECCurve curve = ecNamedCurveParameterSpec.getCurve();
    EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, ecNamedCurveParameterSpec.getSeed());
    java.security.spec.ECPoint ecPoint = ECPointUtil.decodePoint(ellipticCurve, rawPublicKey);
    java.security.spec.ECParameterSpec ecParameterSpec = EC5Util.convertSpec(ellipticCurve,
            ecNamedCurveParameterSpec);
    java.security.spec.ECPublicKeySpec publicKeySpec = new java.security.spec.ECPublicKeySpec(ecPoint,
            ecParameterSpec);

    kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());

    try {
        ecPublicKey = (ECPublicKey) kf.generatePublic(publicKeySpec);
    } catch (Exception e) {
        throw new ApplicationGenericException(e.getMessage(), e.getCause());
    }

    return ecPublicKey;
}
Run Code Online (Sandbox Code Playgroud)

dav*_*085 5

Java对a的默认编码PublicKey"X.509",不仅是EC点。它是一个ASN.1结构,用于标识算法(EC)和参数(此处为prime256v1),外加一个包含该点的BIT STRING;参见rfc5280第4.2.1.7节rfc3279第2.3.5节

类似地编码默认PrivateKey"PKCS#8"(未加密),其是含有在AlgorithmIdentifier加上OCTET STRING包裹在这种情况下包含私钥值和公钥的副本两者的数据的结构,请参阅rfc5208部5和C.4 http://www.secg.org上的SEC 1文档,其中[0]省略了标签,但[1]存在标签。

要将它们(或全部或两者)读回到Java中,请获取KeyFactory.getInstance("EC")并分别generate{Public,Private}X509EncodedKeySpecPKCS8EncodedKeySpec上使用。ECDSA和ECDH(以及ECMQV等)使用相同的密钥结构,这与经典整数DSA和DH使用相同的数学结构($ Z_p ^ * $)但表示形式略有不同。

PS:javadoc可以java.security.Key告诉您大多数情况。