Rsa.java
在某些场景下,你可能想自己接入api,下面提供了加密相关的逻辑代码。
在此提醒 : openssl 生成的私钥默认为pkcs1格式,java提供开箱即用的pkcs8格式,所以需要做转换,请参考“准备工作“一节。
package io.dabank.sdk;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class Rsa {
public static final String PKCS8_PRIVATE_PEM_START = "-----BEGIN PRIVATE KEY-----";
public static final String PKCS8_PRIVATE_PEM_END = "-----END PRIVATE KEY-----";
public static final String PUBLIC_KEY_BEGIN = "-----BEGIN PUBLIC KEY-----";
public static final String PUBLIC_KEY_END = "-----END PUBLIC KEY-----";
private static final String CHARSET = "utf-8";
private static final String RSA = "RSA";
private static final String HASH_ENCRYPTION_ALGORITHM = "SHA256withRSA";
/**
* 用公钥验证RSA签名是否正确
* @param message 原始明文
* @param publicKey 公钥
* @param sign 签名
*/
public static boolean verify(String message, String sign, PublicKey publicKey)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, UnsupportedEncodingException {
final Signature sig = Signature.getInstance(HASH_ENCRYPTION_ALGORITHM);
sig.initVerify(publicKey);
sig.update(message.getBytes(CHARSET));
final byte[] bytes = Base64.getDecoder().decode(sign);
return sig.verify(bytes);
}
/**
* 从pem格式解析RSA公钥
* @param key pem公钥
*/
public static RSAPublicKey getPublicKeyFromPEM(String key) throws IOException, GeneralSecurityException {
String publicKeyPEM = key.replace(PUBLIC_KEY_BEGIN, "")
.replace(PUBLIC_KEY_END, "")
.replaceAll("\n", "");
byte[] encoded = Base64.getDecoder().decode(publicKeyPEM);
KeyFactory kf = KeyFactory.getInstance(RSA);
return (RSAPublicKey) kf.generatePublic(new X509EncodedKeySpec(encoded));
}
/**
* 从PKCS8PEM 解析私钥
* @param pkcs8PEM pkcs8_pem 私钥
*/
public static RSAPrivateKey getPrivateKeyFromPKCS8PEM(String pkcs8PEM) throws Exception {
if (pkcs8PEM == null || pkcs8PEM.isEmpty()) {
throw new RuntimeException("Private key is null or empty");
}
if (pkcs8PEM.contains("RSA PRIVATE KEY")) {
throw new RuntimeException("Private key is PKCS1 format, not PKCS8, try this: \n openssl pkcs8 -topk8 -inform PEM -outform PEM -in app_private_key.pem -out priv8.pem -nocrypt");
}
pkcs8PEM = pkcs8PEM
.replaceAll(PKCS8_PRIVATE_PEM_START, "")
.replaceAll(PKCS8_PRIVATE_PEM_END, "")
.replaceAll("\n", "");
byte[] keyBytes = Base64.getDecoder().decode(pkcs8PEM);
return (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
}
/**
* sha256 rsa 然后用base64编码
* @param message 需要签名的数据,字符串使用 "".getBytes("UTF-8")
* @param privateKey 私钥
*/
public static String sha256withRSASign2base64(RSAPrivateKey privateKey, byte[] message) throws SignatureException, InvalidKeyException {
// System.out.println("[debug]message:" + Arrays.toString(message));
if (privateKey == null || message == null || message.length == 0) {
throw new RuntimeException("private key is null or message is empty");
}
Signature signer = null;
try {
signer = Signature.getInstance(HASH_ENCRYPTION_ALGORITHM);
} catch (NoSuchAlgorithmException e) { // this will not happen forever
e.printStackTrace();
}
signer.initSign(privateKey);
signer.update(message);
return Base64.getEncoder().encodeToString(signer.sign());
}
}