Rsa加解密Java、C#、php通用代码 密钥转换工具

时间:2022-05-20 12:57:49

之前发了一篇"TripleDes的加解密Java、C#、php通用代码",后面又有项目用到了Rsa加解密,还是在不同系统之间进行交互,Rsa在不同语言的密钥格式不一样,所以过程中主要还是密钥转换问题,为方便密钥转换,写了一个XML和PEM格式的密钥转换工具,文章后面会提供密钥转换工具的下载地址,通过搜索参考和研究终于搞定了在Java、C#和Php都可以通用的加解密代码,整理了Rsa的加解密代码做个记录,以后可以参考,大家应该都知道Rsa算法,这里就不说明了,直接看代码(代码主要是公钥加密私钥解密,密文统一进行base64编码,密钥长度为2048):

Java版本:

package com.jaamy.common.util;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.Key;
import java.security.KeyFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; import org.apache.commons.codec.binary.Base64; public class RSACryptoUtil { /**
* 加密算法RSA
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* 填充方式
*/
public static final String CIPHER_TRANSFORMAT = "RSA/ECB/PKCS1Padding"; /**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 245; /**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 256; /**
* 公钥加密
* @param content 原文
* @param publicKey 公钥
* @param inputCharset 字符编码
* @return 加密后的字符串(base64)
* @throws Exception
*/
public static String encryptByPublicKey(String content, String publicKey, String inputCharset)
throws Exception { byte[] data = content.getBytes(inputCharset);
byte[] keyBytes = Base64.decodeBase64(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec); // 对数据加密
Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMAT);
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close(); return Base64.encodeBase64String(encryptedData);
} /**
* 私钥解密
* @param content 密文(base64)
* @param privateKey 私钥
* @param inputCharset 字符编码
* @return
* @throws Exception
*/
public static String decryptByPrivateKey(String content,
String privateKey, String inputCharset) throws Exception { byte[] encryptedData = Base64.decodeBase64(content);
byte[] keyBytes = Base64.decodeBase64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMAT);
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher
.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher
.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return new String(decryptedData, inputCharset);
} /**
* 从文件中加载密钥字符串
* @return 是否成功
* @throws Exception
*/
public static String loadKeyString(String keyFile){
String keyString="";
InputStream in=null;
BufferedReader br=null;
try {
in=RSACryptoUtil.class.getResourceAsStream("/"+keyFile);
br= new BufferedReader(new InputStreamReader(in));
String readLine= null;
StringBuilder sb= new StringBuilder();
while((readLine= br.readLine())!=null){
if(readLine.charAt(0)=='-'){
continue;
}else{
sb.append(readLine);
sb.append('\r');
}
}
keyString=sb.toString();
} catch (IOException e) {
} catch (Exception e) { }finally{
if(br!=null){
try {
br.close();
} catch (IOException e) {
}
}
if(in!=null){
try {
in.close();
} catch (IOException e) {
}
}
}
return keyString;
} /**
* 从文件中加载密钥字符串 根据文件路径加载
* @return 是否成功
* @throws Exception
*/
public static String loadKeyStringByPath(String keyFile){
String keyString="";
InputStream in=null;
BufferedReader br=null;
try {
in = new FileInputStream(keyFile);
br= new BufferedReader(new InputStreamReader(in));
String readLine= null;
StringBuilder sb= new StringBuilder();
while((readLine= br.readLine())!=null){
if(readLine.charAt(0)=='-'){
continue;
}else{
sb.append(readLine);
sb.append('\r');
}
}
keyString=sb.toString();
} catch (IOException e) {
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println(e.getMessage()); }finally{
if(br!=null){
try {
br.close();
} catch (IOException e) {
}
}
if(in!=null){
try {
in.close();
} catch (IOException e) {
}
}
}
return keyString;
} public static void main(String[] args) throws Exception {
String publicKey = RSAUtils.loadKeyStringByPath("D:/sso_public_key_test.pem");
System.out.println(RSACryptoUtil.encryptByPublicKey("123", publicKey, "utf-8"));
}
}

C#版本:

/// <summary>
/// RSA加密+base64
/// </summary>
/// <param name="publickey">公钥</param>
/// <param name="content">原文</param>
/// <returns>加密后的密文字符串</returns>
public static string RSAEncrypt(string publickey, string content)
{
//最大文件加密块
int MAX_ENCRYPT_BLOCK = ; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.FromXmlString(publickey);
byte[] contentByte = Encoding.UTF8.GetBytes(content);
int inputLen = contentByte.Length; int offSet = ;
byte[] cache;
int i = ;
System.IO.MemoryStream aMS = new System.IO.MemoryStream();
// 对数据分段加密
while (inputLen - offSet > )
{
byte[] temp = new byte[MAX_ENCRYPT_BLOCK];
if (inputLen - offSet > MAX_ENCRYPT_BLOCK)
{
Array.Copy(contentByte, offSet, temp, , MAX_ENCRYPT_BLOCK);
cache = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);
}
else
{
Array.Copy(contentByte, offSet, temp, , inputLen - offSet);
cache = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);
}
aMS.Write(cache, , cache.Length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
} cipherbytes = aMS.ToArray();
return Convert.ToBase64String(cipherbytes);
} /// <summary>
/// RSA解密
/// </summary>
/// <param name="privatekey">私钥</param>
/// <param name="content">密文(RSA+base64)</param>
/// <returns>解密后的字符串</returns>
public static string RSADecrypt(string privatekey, string content)
{
//最大文件解密块
int MAX_DECRYPT_BLOCK = ; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.FromXmlString(privatekey);
byte[] contentByte = Convert.FromBase64String(content);
int inputLen = contentByte.Length; // 对数据分段解密
int offSet = ;
int i = ;
byte[] cache;
System.IO.MemoryStream aMS = new System.IO.MemoryStream();
while (inputLen - offSet > )
{
byte[] temp = new byte[MAX_DECRYPT_BLOCK];
if (inputLen - offSet > MAX_DECRYPT_BLOCK)
{
Array.Copy(contentByte, offSet, temp, , MAX_DECRYPT_BLOCK);
cache = rsa.Decrypt(temp, false);
}
else
{
Array.Copy(contentByte, offSet, temp, , inputLen - offSet);
cache = rsa.Decrypt(temp, false);
}
aMS.Write(cache, , cache.Length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
cipherbytes = aMS.ToArray(); return Encoding.UTF8.GetString(cipherbytes);
}

Php版本:

<?php
#私钥
$private_key = '-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCocmvQIWD2L9TW
N1uKpLONwHcdy2oaKoW1CtI8PB+S+UjdEuLl3usWEuh3ZgLYloPyD9553SJFn7an
fOplHITBqASOIXt9pi0CkahUPgwCPj4Dke5cT3fsp2i243/FX3afzrcf7FfTrEv/
LT22wF3csqrGt/UhqMcmpWIpPaL8edoCwGRBhghzEWaRwPZ2x5RPg+9qTSy0M7QG
u+8EwYDnNkGGuuIwzNxklclic9Unp96eVp33vOP/LNvz90OcuqGQQcABh+e2ttv6
VzqlRcD1GRhxqkT3erXmgbQAVm6JQHArK1Up10No+lth1tri5TGcL0BEF7PetDIj
jYh+aCLpAgMBAAECggEAPjFI1yaLyzmrxo/Xz5+x36NxF2IUQabziP1+09iK+9Po
cB9aAO9GMvc2N2dFo7wm6Uesp6fa0IQAh2RakoxuA6ZKUEPSeXjSY4Ft+fSSsH1U
njLSI+j/aTQCOIxUj4YIoUZMXJABeVjDEmscvw3VWffpj8c5zXyoUv9696kXNUoa
uHOuphe1UNc3ghFIpWK+7ScxkPB6KtmAFwD4LSbT9OwhPozavBqouQvhLt1bXO8C
ycKq4f1Pzhtt3sq3BRsPwqGhWt1NK95upKQuDnk1kJHjNzScH1FZxhsBHLxwOJ6E
M7HP5Ywh78umusaNPVLMM6+YVWbENg+WZZcXd/XspQKBgQDRIhIukY7m7fRBH0CP
mHi20gUmn7HzXgLxlbcU5n2PMDHHOg8D+Nmz1MnYPRQNwqxJdH8HOk8YQDC2uA+h
BpyCpvPbp6y6SnZw8bhqiNfSHBjEftmg7lUU5xzBiBo6SyCyLkWD2xa/O8Vyh6ut
/G1mQpNNJWWt5b+g5c4i0/fIhwKBgQDOMjGcLS8zHnZ30ZsWUS39iZ5TZXPCldTl
Q9JB5PnB4CajYmQEdw3n9C6mOO42b+3M04mmqo1r0HiNyA9lZQQNsM3KqG+ngGvE
0DM1cAyuz3Fi3XTIhAbRyXXyVbqBp5Yh2/O2lvrsInusJrimDRgwglquu2GsdVrj
+++b2DFFDwKBgQCkfXLlk/FdK44xZn5mM1vHGBubDIJv0+Lm14Yf90aMyDBu7fh/
fEznSBfWb/wE8riGMg3zxmYNwfdO0Cji04torB4kB5cxE35jSYxupuFxzk2gx9Eu
5iafgUQ56G4QqaS24PQmSL10fnPHqHRdLa1ygCzRwfdettVpnTbsZ+J9owKBgQDF
o2Tb3o9sPxmsdVNiy8L6TstcAlU3wOfELQK+uFwQ0eoXFvrpMLg6iVmhZ9YkhZp4
hpZdEwLkwXib5ZOkS3PcL4jBZDtJYRVrG2jKIrF1aU60RbJnc+0ZbjHIaxWOqvSD
VdE/RW4TomXKN38rYke6T2feLatMY1wQRG6BgXKQTwKBgQDKfK9Xuqzx+WI4AohT
EwKrQEZUMD+6DTESHHG9As4zMJ9zU+6iPpM4Gw4CzfJZHhPP4dD+TC9NcvvR+GC9
UkwxmZrvP1+6KNFp0DZNk6M9wPZuYM/E63Vy0sFEA+/gFp4vQh8k7N8n/n7DhR3v
kLuPdicfsKcz0thxzyDjv6oR2g==
-----END PRIVATE KEY-----'; #公钥
$public_key = '-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqHJr0CFg9i/U1jdbiqSz
jcB3HctqGiqFtQrSPDwfkvlI3RLi5d7rFhLod2YC2JaD8g/eed0iRZ+2p3zqZRyE
wagEjiF7faYtApGoVD4MAj4+A5HuXE937KdotuN/xV92n863H+xX06xL/y09tsBd
3LKqxrf1IajHJqViKT2i/HnaAsBkQYYIcxFmkcD2dseUT4Pvak0stDO0BrvvBMGA
5zZBhrriMMzcZJXJYnPVJ6fenlad97zj/yzb8/dDnLqhkEHAAYfntrbb+lc6pUXA
9RkYcapE93q15oG0AFZuiUBwKytVKddDaPpbYdba4uUxnC9ARBez3rQyI42Ifmgi
6QIDAQAB
-----END PUBLIC KEY-----'; $pi_key = openssl_pkey_get_private($private_key);
$pu_key = openssl_pkey_get_public($public_key); #公钥加密数据 rsa+base64
$data = "hello world!";
openssl_public_encrypt($data,$encrypted,$pu_key);
$base64_encrypted = base64_encode($encrypted);
echo $base64_encrypted."\n"; #私钥解密数据
openssl_private_decrypt(base64_decode($base64_encrypted),$decrypted_data,$pi_key); echo $decrypted_data; ?>

Rsa加解密C#和Java、php使用的密钥格式不一样,这里提供一个密钥转换工具:Rsa密钥转换工具v2.0.zip