几个需要注意的地方
1、安卓的KeyFactory如果要支持EC加密,必须使用Java11的JDK版本(SpringBoot开发可以支持Java8,亲测),源码说明如下图:
2、publicKey和privateKey的编码格式不一样,在传递过程中如果需要反序列化得到钥匙切记注意(本人踩坑):
(1)publicKey的编码为:X509EncodedKeySpec
(2)privateKey的编码为:PKCS8EncodedKeySpec
3、代码如下:若SpringBoot开发也需要,也可使用该套代码,将@UniJSMethod注解和callback参数去掉即可。
/**
* 生成ECDHE密钥对
*
* @return 密钥对
* @throws NoSuchAlgorithmException
*/
@UniJSMethod
public void generateECKeyPair(UniJSCallback callback) throws Exception {
final KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
generator.initialize(256); // Set p=256
KeyPair keyPair = generator.generateKeyPair();
ECPublicKey ecPublicKey = (ECPublicKey) keyPair.getPublic();
ECPrivateKey ecPrivateKey = (ECPrivateKey) keyPair.getPrivate();
String publicKeyString = Base64.encodeBase64String(ecPublicKey.getEncoded());
String privateKeyString = Base64.encodeBase64String(ecPrivateKey.getEncoded());
ECKeyPair ecKeyPair = new ECKeyPair(publicKeyString, privateKeyString);
Log.i(TAG, "===============TestModule============生成的EC秘钥对:" + ecKeyPair);
callback.invoke(new JSONObject() {{
put("code", 2000);
put("result", ecKeyPair);
}});
}
/**
* 生成共享密钥
*
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws InvalidKeyException
*/
@UniJSMethod
public void deriveSharedSecret(JSONObject json, UniJSCallback callback) throws NoSuchAlgorithmException, InvalidKeyException {
String otherPublicKeyStr = json.getString("otherPublicKey");
String yourPrivateKeyStr = json.getString("yourPrivateKey");
byte[] otherKeys = Base64.decodeBase64(otherPublicKeyStr);
byte[] yourKeys = Base64.decodeBase64(yourPrivateKeyStr);
final KeyFactory ec = KeyFactory.getInstance("EC");
final X509EncodedKeySpec keySpecPb = new X509EncodedKeySpec(otherKeys);
final PKCS8EncodedKeySpec keySpecPr = new PKCS8EncodedKeySpec(yourKeys);
Log.i(TAG, "===================================================================下面开始反序列化生成钥匙");
PublicKey publicKey = null;
try {
publicKey = ec.generatePublic(keySpecPb);
Log.i(TAG, "===================================================================公钥生成成功");
} catch (InvalidKeySpecException e) {
Log.e(TAG, "===================================================================公钥生成失败", e);
}
PrivateKey privateKey = null;
try {
privateKey = ec.generatePrivate(keySpecPr);
Log.i(TAG, "===================================================================私钥生成成功");
} catch (InvalidKeySpecException e) {
Log.e(TAG, "===================================================================私钥生成失败", e);
}
Log.i(TAG, "===================================================================成功获得了反序列化的钥匙");
KeyAgreement ecdh = KeyAgreement.getInstance("ECDH");
Log.i(TAG, "===================================================================下面开始ECDH生成器");
ecdh.init(privateKey);
ecdh.doPhase(publicKey, true);
byte[] shareKey = ecdh.generateSecret();
String finalShareKey = Base64.encodeBase64String(shareKey);
callback.invoke(new JSONObject() {{
put("code", 2000);
put("result", finalShareKey);
}});
}
/**
* DH密钥对对象
*/
public class ECKeyPair {
private String ecPublicKey;
private String ecPrivateKey;
public ECKeyPair(String ecPublicKey, String ecPrivateKey) {
this.ecPublicKey = ecPublicKey;
this.ecPrivateKey = ecPrivateKey;
}
public String getEcPublicKey() {
return ecPublicKey;
}
public String getEcPrivateKey() {
return ecPrivateKey;
}
}