Rsa加解密Java、C#、php通用代码 密钥转换工具
之前发了一篇”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 = 245;
- RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
- byte[] cipherbytes;
- rsa.FromXmlString(publickey);
- byte[] contentByte = Encoding.UTF8.GetBytes(content);
- int inputLen = contentByte.Length;
- int offSet = 0;
- byte[] cache;
- int i = 0;
- System.IO.MemoryStream aMS = new System.IO.MemoryStream();
- // 对数据分段加密
- while (inputLen - offSet > 0)
- {
- byte[] temp = new byte[MAX_ENCRYPT_BLOCK];
- if (inputLen - offSet > MAX_ENCRYPT_BLOCK)
- {
- Array.Copy(contentByte, offSet, temp, 0, MAX_ENCRYPT_BLOCK);
- cache = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);
- }
- else
- {
- Array.Copy(contentByte, offSet, temp, 0, inputLen - offSet);
- cache = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);
- }
- aMS.Write(cache, 0, 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 = 256;
- RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
- byte[] cipherbytes;
- rsa.FromXmlString(privatekey);
- byte[] contentByte = Convert.FromBase64String(content);
- int inputLen = contentByte.Length;
- // 对数据分段解密
- int offSet = 0;
- int i = 0;
- byte[] cache;
- System.IO.MemoryStream aMS = new System.IO.MemoryStream();
- while (inputLen - offSet > 0)
- {
- byte[] temp = new byte[MAX_DECRYPT_BLOCK];
- if (inputLen - offSet > MAX_DECRYPT_BLOCK)
- {
- Array.Copy(contentByte, offSet, temp, 0, MAX_DECRYPT_BLOCK);
- cache = rsa.Decrypt(temp, false);
- }
- else
- {
- Array.Copy(contentByte, offSet, temp, 0, inputLen - offSet);
- cache = rsa.Decrypt(temp, false);
- }
- aMS.Write(cache, 0, 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