续上篇的PFX加密使用,继续CER的使用。
对数据进行加密之后还需要对加密的数据解密操作,一般这种解密的操作发生在合作方,我们需要把生成的公钥以邮件的方式发送给合作方,合作方在收到公钥之后就可以对加密的数据进行解密操作了,示例如下:
/**
* 指定Cer公钥路径解密
*
* @param src
* @param pubCerPath
* @return
*/
public static String decryptByPubCerFile(String src, String pubCerPath) {
PublicKey publicKey = getPublicKeyFromFile(pubCerPath);
if (publicKey == null) {
return null;
}
return decryptByPublicKey(src, publicKey);
}
/**
* 根据Cer文件读取公钥
*
* @param pubCerPath
* @return
*/
public static PublicKey getPublicKeyFromFile(String pubCerPath) {
FileInputStream pubKeyStream = null;
try {
pubKeyStream = new FileInputStream(pubCerPath);
byte[] reads = new byte[pubKeyStream.available()];
pubKeyStream.read(reads);
return getPublicKeyByText(new String(reads));
} catch (FileNotFoundException e) {
// //log.error("公钥文件不存在:", e);
} catch (IOException e) {
// log.error("公钥文件读取失败:", e);
} finally {
if (pubKeyStream != null) {
try {
pubKeyStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
/**
* 根据公钥Cer文本串读取公钥
*
* @param pubKeyText
* @return
*/
public static PublicKey getPublicKeyByText(String pubKeyText) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance(RsaConst.KEY_X509);
BufferedReader br = new BufferedReader(new StringReader(pubKeyText));
String line = null;
StringBuilder keyBuffer = new StringBuilder();
while ((line = br.readLine()) != null) {
if (!line.startsWith("-")) {
keyBuffer.append(line);
}
}
Certificate certificate = certificateFactory.generateCertificate(new ByteArrayInputStream(new BASE64Decoder().decodeBuffer(keyBuffer.toString())));
return certificate.getPublicKey();
} catch (Exception e) {
// log.error("解析公钥内容失败:", e);
}
return null;
}
/**
* 根据公钥解密
*
* @param src
* @param publicKey
* @return
*/
public static String decryptByPublicKey(String src, PublicKey publicKey) {
try {
byte[] destBytes = rsaByPublicKey(FormatUtil.hex2Bytes(src), publicKey, Cipher.DECRYPT_MODE);
if (destBytes == null) {
return null;
}
return new String(destBytes, RsaConst.ENCODE);
} catch (UnsupportedEncodingException e) {
// //log.error("解密内容不是正确的UTF8格式:", e);
}
return null;
}
/**
* 公钥算法
*
* @param srcData
* 源字节
* @param publicKey
* 公钥
* @param mode
* 加密 OR 解密
* @return
*/
public static byte[] rsaByPublicKey(byte[] srcData, PublicKey publicKey, int mode) {
try {
Cipher cipher = Cipher.getInstance(RsaConst.RSA_CHIPER);
cipher.init(mode, publicKey);
// 分段加密
int blockSize = (mode == Cipher.ENCRYPT_MODE) ? cipher.getOutputSize(srcData.length)-11 : cipher.getOutputSize(srcData.length);
byte[] encryptedData = null;
for (int i = 0; i < srcData.length; i += blockSize) {
// 注意要使用2的倍数,否则会出现加密后的内容再解密时为乱码
byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize));
encryptedData = addAll(encryptedData, doFinal);
}
return encryptedData;
} catch (NoSuchAlgorithmException e) {
System.out.println("公钥算法-不存在的解密算法:");
} catch (NoSuchPaddingException e) {
System.out.println("公钥算法-无效的补位算法:");
} catch (IllegalBlockSizeException e) {
System.out.println("公钥算法-无效的块大小:");
} catch (BadPaddingException e) {
System.out.println("公钥算法-补位算法异常:");
e.printStackTrace();
} catch (InvalidKeyException e) {
System.out.println("公钥算法-无效的私钥:");
}
return null;
}
示例中的 subarray和addAll方法已经在上篇示例中。
配合PFX的加密整体使用为:
public static void main(String[] args) throws CertificateException {
System.out.println("加密前:111");
String origData = new String(SecurityUtil.Base64Encode("111"));
String encryptData = RsaCodingUtil.encryptByPriPfxFile(origData,
"D:/home/user1/keyfile/Prv.pfx", "123456");
System.out.println("加密后:"+encryptData);
String reslut = RsaCodingUtil.decryptByPubCerFile(encryptData, "D:/home/user1/keyfile/puk.cer");
reslut = SecurityUtil.Base64Decode(reslut);
System.out.println("解密后:"+reslut);
}
输出结果:
已经完成对数据的加解密工作了。