How can I generate a valid ECDSA EC key pair?

前端 未结 2 1742
面向向阳花
面向向阳花 2021-01-14 18:28

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

static {
    Security.insertProviderAt(new org.spongycastle.jce.provi         


        
相关标签:
2条回答
  • 2021-01-14 18:52

    More practical example. Convert generated public key to decoded bytes array or hex string:

    public String getPublicKeyAsHex(PublicKey publicKey){
    
        ECPublicKey ecPublicKey = (ECPublicKey)publicKey;
        ECPoint ecPoint = ecPublicKey.getW();
    
        byte[] publicKeyBytes = new byte[PUBLIC_KEY_LENGTH];
        writeToStream(publicKeyBytes, 0, ecPoint.getAffineX(), PRIVATE_KEY_LENGTH);
        writeToStream(publicKeyBytes, PRIVATE_KEY_LENGTH, ecPoint.getAffineY(), PRIVATE_KEY_LENGTH);
    
        String hex = Hex.toHexString(publicKeyBytes);
    
        logger.debug("Public key bytes: " + Arrays.toString(publicKeyBytes));
        logger.debug("Public key hex: " + hex);
    
        return hex;
    }
    
    private void writeToStream(byte[] stream, int start, BigInteger value, int size) {
        byte[] data = value.toByteArray();
        int length = Math.min(size, data.length);
        int writeStart = start + size - length;
        int readStart = data.length - length;
        System.arraycopy(data, readStart, stream, writeStart, length);
    }
    

    Convert decoded bytes array back to PublicKey:

    KeyFactory factory = KeyFactory.getInstance(ALGORITHM, ALGORITHM_PROVIDER);
    
    ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(CURVE);
    
    ECNamedCurveSpec params = new ECNamedCurveSpec(CURVE, spec.getCurve(), spec.getG(), spec.getN());
    
    BigInteger xCoordinate = new BigInteger(1, Arrays.copyOfRange(decodedPublicKey, 0, PRIVATE_KEY_LENGTH));
    BigInteger yCoordinate = new BigInteger(1, Arrays.copyOfRange(decodedPublicKey, PRIVATE_KEY_LENGTH, PUBLIC_KEY_LENGTH));
    java.security.spec.ECPoint w = new java.security.spec.ECPoint(xCoordinate, yCoordinate);
    
    PublicKey encodedPublicKey = factory.generatePublic(new java.security.spec.ECPublicKeySpec(w, params));
    
    0 讨论(0)
  • 2021-01-14 19:13

    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.

    0 讨论(0)
提交回复
热议问题