php,java间rsa加解密处理

java和php的RSA加解密版本已全部通过测试。并且可以相互加解密。

私钥是服务器保留,公钥可以发放给对应的客户端,甚至可以是公共的。

采用私钥加密-》公钥解密 和 公钥加密-》私钥解密 的加密方式。

但是如果客户端是需要更高安全性的支付系统,那么应该采用两对密钥。

每一方分别是自己的私钥和对方的公钥,采用私钥加密并签名-》公钥解密并验签的方式。


PHP版代码:

<?php

class RSA
{
    private $privateKey = '';//私钥(用于用户加密)
    private $publicKey = '';//公钥(用于服务端数据解密)

    public function __construct()
    {
        $this->privateKey = openssl_pkey_get_private(file_get_contents('php_private.pem'));//私钥,用于加密
    $this->publicKey = openssl_pkey_get_public(file_get_contents('php_public.pem'));//公钥,用于解密
    }

    /**
     * 私钥加密
     * @param 原始数据 $data
     * @return 密文结果 string
     */
    public function encryptByPrivateKey($data)
    {
        openssl_private_encrypt($data, $encrypted, $this->privateKey, OPENSSL_PKCS1_PADDING);//私钥加密
        $encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的
        return $encrypted;
    }

    /**
     * 私钥解密
     * @param 密文数据 $data
     * @return 原文数据结果 string
     */
    public function decryptByPrivateKey($data)
    {
        $data = base64_decode($data);
        openssl_private_decrypt($data, $encrypted, $this->privateKey, OPENSSL_PKCS1_PADDING);//私钥解密
        return $encrypted;
    }

    /**
     * 私钥签名
     * @param unknown $data
     */
    public function signByPrivateKey($data)
    {
        openssl_sign($data, $signature, $this->privateKey);
        $encrypted = base64_encode($signature);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的
        return $encrypted;
    }

    /**
     * 公钥加密
     * @param 原文数据 $data
     * @return 加密结果 string
     */
    public function encryptByPublicKey($data)
    {
        openssl_public_encrypt($data, $decrypted, $this->publicKey, OPENSSL_PKCS1_PADDING);//公钥加密
        return base64_encode($decrypted);
    }

    /**
     * 公钥解密
     * @param 密文数据 $data
     * @return 原文结果 string
     */
    public function decryptByPublicKey($data)
    {
        $data = base64_decode($data);
        openssl_public_decrypt($data, $decrypted, $this->publicKey, OPENSSL_PKCS1_PADDING);//公钥解密
        return $decrypted;
    }

    /**
     * 公钥验签
     * @param unknown $data
     * @param unknown $sign
     */
    public function verifyByPublicKey($data, $sign)
    {
        $sign = base64_decode($sign);
        return openssl_verify($data, $sign, $this->publicKey);
    }

    public function __destruct()
    {
        openssl_free_key($this->privateKey);
        openssl_free_key($this->publicKey);
    }
}


JAVA版:

package crypt;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

public class Rsa {
	private String priKey;
	private String pubKey;

	public static void main(String[] args) {
		Rsa rsa = new Rsa();
		String str = "我要加密这段文字。";
		System.out.println("原文:"+"我要加密这段文字。");
		String crypt = rsa.encryptByPrivateKey(str);
		System.out.println("私钥加密密文:"+crypt);
		String result = rsa.decryptByPublicKey(crypt);
		System.out.println("原文:"+result);

		System.out.println("—");

		str = "我要加密这段文字。";
		System.out.println("原文:"+"我要加密这段文字。");
		crypt = rsa.encryptByPublicKey(str);
		System.out.println("公钥加密密文:"+crypt);
		result = rsa.decryptByPrivateKey(crypt);
		System.out.println("原文:"+result);

		System.out.println("—");

		str = "我要签名这段文字。";
		System.out.println("原文:"+str);
		String str1 = rsa.signByPrivateKey(str);
		System.out.println("签名结果:"+str1);
		if(rsa.verifyByPublicKey(str1, str)){
			System.out.println("成功");
		} else {
			System.out.println("失败");
		}
	}

	public Rsa(){
		priKey = readStringFromFile("java_private.pem");
		pubKey = readStringFromFile("java_public.pem");
	}

	/**
	* 使用私钥加密
	* @see decByPriKey
	*/
	public String encryptByPrivateKey(String data) {
		// 加密
		String str = "";
		try {
			byte[] pribyte = base64decode(priKey.trim());
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pribyte);
			KeyFactory fac = KeyFactory.getInstance("RSA");
			RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
			Cipher c1 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			c1.init(Cipher.ENCRYPT_MODE, privateKey);
			str = base64encode(c1.doFinal(data.getBytes()));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return str;
	}

	/**
	* 使用私钥解密
	* @see decByPriKey
	*/
	public String decryptByPrivateKey(String data) {
		// 加密
		String str = "";
		try {
			byte[] pribyte = base64decode(priKey.trim());
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pribyte);
			KeyFactory fac = KeyFactory.getInstance("RSA");
			RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
			Cipher c1 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			c1.init(Cipher.DECRYPT_MODE, privateKey);
			byte[] temp = c1.doFinal(base64decode(data));
			str = new String(temp);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return str;
	}
	/**
	* 使用公钥加密
	* @see decByPriKey
	*/
	public String encryptByPublicKey(String data) {
		// 加密
		String str = "";
		try {
			byte[] pubbyte = base64decode(pubKey.trim());
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubbyte);
			KeyFactory fac = KeyFactory.getInstance("RSA");
			RSAPublicKey rsaPubKey = (RSAPublicKey) fac.generatePublic(keySpec);
			Cipher c1 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			c1.init(Cipher.ENCRYPT_MODE, rsaPubKey);
			str = base64encode(c1.doFinal(data.getBytes()));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return str;
	}

	/**
	* 使用公钥解密
	* @see decByPriKey
	*/
	public String decryptByPublicKey(String data) {
		// 加密
		String str = "";
		try {
			byte[] pubbyte = base64decode(pubKey.trim());
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubbyte);
			KeyFactory fac = KeyFactory.getInstance("RSA");
			RSAPublicKey rsaPubKey = (RSAPublicKey) fac.generatePublic(keySpec);
			Cipher c1 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			c1.init(Cipher.DECRYPT_MODE, rsaPubKey);
			byte[] temp = c1.doFinal(base64decode(data));
			str = new String(temp);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return str;
	}
	/**
	* 本方法使用SHA1withRSA签名算法产生签名
	* @param String src 签名的原字符串
	* @return String 签名的返回结果(16进制编码)。当产生签名出错的时候,返回null。
	*/
	public String signByPrivateKey(String src) {
		try {
			Signature sigEng = Signature.getInstance("SHA1withRSA");
			byte[] pribyte = base64decode(priKey.trim());
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pribyte);
			KeyFactory fac = KeyFactory.getInstance("RSA");
			RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
			sigEng.initSign(privateKey);
			sigEng.update(src.getBytes());
			byte[] signature = sigEng.sign();
			return base64encode(signature);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	* 使用共钥验证签名
	* @param sign
	* @param src
	* @return
	*/
	public boolean verifyByPublicKey(String sign, String src) {
		try {
			Signature sigEng = Signature.getInstance("SHA1withRSA");
			byte[] pubbyte = base64decode(pubKey.trim());
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubbyte);
			KeyFactory fac = KeyFactory.getInstance("RSA");
			RSAPublicKey rsaPubKey = (RSAPublicKey) fac.generatePublic(keySpec);
			sigEng.initVerify(rsaPubKey);
			sigEng.update(src.getBytes());
			byte[] sign1 = base64decode(sign);
			return sigEng.verify(sign1);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	* base64加密
	* @param bstr
	* @return
	*/
	@SuppressWarnings("restriction")
	private String base64encode(byte[] bstr) {
		String str = new sun.misc.BASE64Encoder().encode(bstr);
		str = str.replaceAll("\r\n", "").replaceAll("\r", "").replaceAll("\n", "");
		return str;
	}

	/**
	* base64解密
	* @param str
	* @return byte[]
	*/
	@SuppressWarnings("restriction")
	private byte[] base64decode(String str) {
		byte[] bt = null;
		try {
			sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
			bt = decoder.decodeBuffer(str);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return bt;
	}

	/**
	* 从文件中读取所有字符串
	* @param fileName
	* @return String
	*/
	private String readStringFromFile(String fileName){
		StringBuffer str = new StringBuffer();
		try {
			File file = new File(fileName);
			FileReader fr = new FileReader(file);
			char[] temp = new char[1024];
			while (fr.read(temp) != -1) {
				str.append(temp);
			}
			fr.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return str.toString();
	}
}