使用给定私钥在椭圆曲线算法中生成公钥

时间:2017-01-31 17:16:49

标签: java android cryptography private-key android-pay

我知道这个问题已被提出,但似乎我无法编写代码以使其有效。

假设我们有以下密钥对:

公钥(这是我想要生成的私钥 - base64编码字符串作为用于Android Pay的公钥): BKmbVIGwZw3TUITg1NIppTrWXCGuXt1YdfAnY0ToqYaNzxdkY5ZUNO0WN8Q35rcnrQavsAfRtWYKKoXAcZ7MOVQ =

私钥(已知):

----- BEGIN PRIVATE KEY -----

MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgTA / wqrlbeVddorTlaT1AqhALrIBwS + DUdV3N1K1gImqhRANCAASpm1SBsGcN01CE4NTSKaU61lwhrl7dWHXwJ2NE6KmGjc8XZGOWVDTtFjfEN + a3J60Gr7AH0bVmCiqFwHGezDlU

----- END PRIVATE KEY -----

以下是我用来生成java.security.PrivateKey的代码:

private static final Logger logger = LoggerFactory.getLogger(AndroidPayDecodingUtils.class);

private static final String SECURITY_PROVIDER = "BC";
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private static final String KEY_AGREEMENT_ALGORITHM = "ECDH";
// OpenSSL name of the NIST P-126 Elliptic Curve
private static final String EC_CURVE = "prime256v1";
private static final String SYMMETRIC_KEY_TYPE = "AES";
private static final String SYMMETRIC_ALGORITHM = "AES/CTR/NoPadding";
private static final byte[] SYMMETRIC_IV = Hex.decode("00000000000000000000000000000000");
private static final int SYMMETRIC_KEY_BYTE_COUNT = 16;
private static final String MAC_ALGORITHM = "HmacSHA256";
private static final int MAC_KEY_BYTE_COUNT = 16;
private static final byte[] HKDF_INFO = "Android".getBytes(DEFAULT_CHARSET);
private static final byte[] HKDF_SALT = null /* equivalent to a zeroed salt of hashLen */;

public static final String EC_ASYMMETRIC_KEY_TYPE = "EC";


public static PrivateKey generatePrivateKey(String privateKey) {

    try {
        String pkcs8Pem = formatKey(privateKey);
        // Base64 decode the result
        byte[] pkcs8EncodedBytes = BaseEncoding.base64().decode(pkcs8Pem);
        // extract the private key
        KeyFactory asymmetricKeyFactory = KeyFactory.getInstance(EC_ASYMMETRIC_KEY_TYPE, SECURITY_PROVIDER);

        return asymmetricKeyFactory.generatePrivate(new PKCS8EncodedKeySpec(pkcs8EncodedBytes));

    } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeySpecException | NullPointerException e) {
        logger.error("Failed to create private key");
    }
    return null;
}

private static String formatKey(String key) {

    try {
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader rdr = new BufferedReader(new StringReader(key));

        String line;
        while ((line = rdr.readLine()) != null) {
            stringBuilder.append(line);
        }

        // Remove the "BEGIN" and "END" lines, as well as any whitespace
        String toReturn = stringBuilder.toString();
        // unix generated EC private key
        toReturn = toReturn.replace("-----BEGIN PRIVATE KEY-----", "");
        toReturn = toReturn.replace("-----END PRIVATE KEY-----", "");
        // mac generated EC private key
        toReturn = toReturn.replace("-----BEGIN EC PRIVATE KEY-----", "");
        toReturn = toReturn.replace("-----END EC PRIVATE KEY-----", "");
        //whitespace
        toReturn = toReturn.replaceAll("\\s+", "");

        return toReturn;

    } catch (IOException | NullPointerException e) {
        logger.error("Failed to read the key");
    }
    return null;
}

这是我用来生成Base64编码字符串的公钥的代码,但似乎我做错了,因为我没有得到所需的结果:

public static String generatePublicKeyFromPrivateKey(String privateKeyStr) {

    ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec(EC_CURVE);
    ECDomainParameters ecDomainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(),
            parameterSpec.getN(), parameterSpec.getH(), parameterSpec.getSeed());

    ECPrivateKey privateKey = (ECPrivateKey) generatePrivateKey(privateKeyStr);

    byte[] privateKeyBytes = privateKey.getS().toByteArray();

    ECPoint ecPoint = ecDomainParameters.getG().multiply(new BigInteger(privateKeyBytes));

    String toReturn = new String(Base64.encode(ecPoint.getEncoded(true)));

    return toReturn;
}

0 个答案:

没有答案