我知道这个问题已被提出,但似乎我无法编写代码以使其有效。
假设我们有以下密钥对:
公钥(这是我想要生成的私钥 - 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;
}