如何生成有效的ECDSA EC密钥对? [英] How can I generate a valid ECDSA EC key pair?

查看:2023
本文介绍了如何生成有效的ECDSA EC密钥对?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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();
}

有些事情是错误的,因为我总是得到类似这样的例子 公钥:

3059301306072A8648CE3D020106082A8648CE3D03010703420004483ABA9F322240010ECF00E818C041A60FE71A2BD64C64CD5A60519985F110AEDE6308027D2730303F5E2478F083C7F5BB683DCAC22BFEB62F3A48BD010094040

和私钥:

308193020100301306072A8648CE3D020106082A8648CE3D030107047930770201010420219AB4B3701630973A4B2917D53F69A4BE6DAD61F48016BFEF147B2999575CB2A00A06082A8648CE3D030107A14403420004483ABA9F322240010ECF00E818C041A60FE71A2BD64C64CD5A60519985F110AEDE6308027D2730303F5E2478F083C7F5BB683DCAC22BFEB62F3A48BD01009F40

网站此外,我的后端验证给我错误无效点编码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;
}

解决方案

Java对PublicKey的默认编码是"X.509",这不仅是EC点.它是一个ASN.1结构,用于标识算法(EC)和参数(此处为prime256v1),外加一个包含该点的BIT STRING;请参阅 rfc5280节4.2.1.7 (未加密),它是一个结构,其中包含AlgorithmIdentifier以及一个OCTET STRING,该数据包装了在这种情况下既包含私钥值又包含公钥副本的数据,请参阅省略了带有标签[0]的"http://www.secg.org" rel ="noreferrer"> http://www.secg.org .

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

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

I am trying to generate ECDSA key pair using SpongyCastle in Android. This is the code:

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

Something is wrong since I always get something like that example of Public Key:

3059301306072A8648CE3D020106082A8648CE3D03010703420004483ABA9F322240010ECF00E818C041A60FE71A2BD64C64CD5A60519985F110AEDE6308027D2730303F5E2478F083C7F5BB683DCAC22BFEB62F3A48BD01009F40

and Private Key:

308193020100301306072A8648CE3D020106082A8648CE3D030107047930770201010420219AB4B3701630973A4B2917D53F69A4BE6DAD61F48016BFEF147B2999575CB2A00A06082A8648CE3D030107A14403420004483ABA9F322240010ECF00E818C041A60FE71A2BD64C64CD5A60519985F110AEDE6308027D2730303F5E2478F083C7F5BB683DCAC22BFEB62F3A48BD01009F40

The site ECDSA sample give me "Invalid ECDSA signature message", and them seems really very different from that smaller Private Key and always starting with "04" Public Key generated in the same site.

Also, my backend verification gives me the error "Invalid point encoding 0x30"

The backend Java method check is:

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

解决方案

Java's default encoding for a PublicKey is "X.509" which is not just the EC point; it is an ASN.1 structure identifying the algorithm (EC) and parameters (here prime256v1) PLUS a BIT STRING wrapping the point; see rfc5280 section 4.2.1.7 and rfc3279 section 2.3.5.

Similarly the default encoding for PrivateKey is "PKCS#8" (unencrypted) which is a structure containing an AlgorithmIdentifier plus an OCTET STRING wrapping the data which in this case contains both the private key value and a copy of the public key, see rfc5208 section 5 and C.4 of document SEC 1 at http://www.secg.org with tag [0] omitted but tag [1] present.

To read (either or both of) them back in to Java, get a KeyFactory.getInstance("EC") and use generate{Public,Private} on an X509EncodedKeySpec or PKCS8EncodedKeySpec respectively. ECDSA and ECDH (and ECMQV etc) use the same key structures, unlike classic integer DSA and DH which use the same mathematical structure ($Z_p^*$) but slightly different representations.

PS: the javadoc for java.security.Key tells you most of this.

这篇关于如何生成有效的ECDSA EC密钥对?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆