之前发了一篇"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

 

posted on 2016-12-02 10:01  jaamy  阅读(7262)  评论(0编辑  收藏  举报