以下是php封裝好的類,引入即可使用
<?php
/**
* 作者:pjp
* 郵箱:vippjp@163.com
*/
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);
}
}
?>
php公鑰文件內容(php_public.pem)
公鑰和私鑰皆可自己重新生成
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCm1YchJdHVy9iXsDfQfMEB2mdO 5wuaEiqUEerHO7HbKKkvhuIfc7haQV5bKTiKZ76FnkkXJMF+onMrQrrqk4TiWlYZ oilesPM88jr01Z9MmhzKV7vWboVhYcd8cw2Mua0HwAMyl9TDt5OLWmT00C4/Lu72 lRL21avxRTvmDQoAqQIDAQAB -----END PUBLIC KEY-----
php私鑰文件內容(php_private.pem)
-----BEGIN PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKbVhyEl0dXL2Jew N9B8wQHaZ07nC5oSKpQR6sc7sdsoqS+G4h9zuFpBXlspOIpnvoWeSRckwX6icytC uuqThOJaVhmiKV6w8zzyOvTVn0yaHMpXu9ZuhWFhx3xzDYy5rQfAAzKX1MO3k4ta ZPTQLj8u7vaVEvbVq/FFO+YNCgCpAgMBAAECgYB1x4s1eJiyAc4wEITm2Bv+Lez/ BBfptmd+z0NbUiZW3VbLqcLbh3ufpERzwR8cfu8/L6bUAuvjddYutVZ2Ip0Nd7dG 5rrktH+7R8UT89fn87bUa5NlLee+egyoz/PJ63X4JjEg5OJbkXMbK4YrTypS0IAx nZv+7BeSsCrzNlpWAQJBANgmHMDNrIWvU3qVf7u8SS/g+WrlvKMWOXtYjH2OqWoO Vtmh4Or1PbaPIMnPAXFYiYYW8wcLYnVmVCez5qaysWkCQQDFl9XONZIMFAvdJ5S2 UFk63bEYtCroKZjddTlE6K/j+Vj2IaCFm94i4x1YzJR0KrykrtBTLRi7nuWmdJMJ r61BAkA7dxDGAk+KX9fJi8OedIh2AaDcxeOFwqGBy7Sq/kqhgNxn918XhOy7gtj0 bFzrP/5lw36M25b00XgpjBbSmaqxAkBnBN/TUHjh1T3OQ0m0uDWdjGI+KAlK3A04 QVrng43ZBXMNeMDRiE+Lzu/JEXjBDFsoXYB+LT/86j5/x721yiNBAkEAgi0F5BvA wYZQXqAx3iyuj8R9uUKpLePafyBRHnLNrFux2VD0ZX3pXCmfDDmtM/NMO491dI84 6NbVOvxWcNPQ/Q== -----END PRIVATE KEY-----
以下是java封裝好的方法
/**
* 作者:pjp
* 郵箱:vippjp@163.com
*/
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();
}
}
java公鑰文件內容(java_public.pem)
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCm1YchJdHVy9iXsDfQfMEB2mdO 5wuaEiqUEerHO7HbKKkvhuIfc7haQV5bKTiKZ76FnkkXJMF+onMrQrrqk4TiWlYZ oilesPM88jr01Z9MmhzKV7vWboVhYcd8cw2Mua0HwAMyl9TDt5OLWmT00C4/Lu72 lRL21avxRTvmDQoAqQIDAQAB
java私鑰文件內容(java_private.pem)
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKbVhyEl0dXL2Jew N9B8wQHaZ07nC5oSKpQR6sc7sdsoqS+G4h9zuFpBXlspOIpnvoWeSRckwX6icytC uuqThOJaVhmiKV6w8zzyOvTVn0yaHMpXu9ZuhWFhx3xzDYy5rQfAAzKX1MO3k4ta ZPTQLj8u7vaVEvbVq/FFO+YNCgCpAgMBAAECgYB1x4s1eJiyAc4wEITm2Bv+Lez/ BBfptmd+z0NbUiZW3VbLqcLbh3ufpERzwR8cfu8/L6bUAuvjddYutVZ2Ip0Nd7dG 5rrktH+7R8UT89fn87bUa5NlLee+egyoz/PJ63X4JjEg5OJbkXMbK4YrTypS0IAx nZv+7BeSsCrzNlpWAQJBANgmHMDNrIWvU3qVf7u8SS/g+WrlvKMWOXtYjH2OqWoO Vtmh4Or1PbaPIMnPAXFYiYYW8wcLYnVmVCez5qaysWkCQQDFl9XONZIMFAvdJ5S2 UFk63bEYtCroKZjddTlE6K/j+Vj2IaCFm94i4x1YzJR0KrykrtBTLRi7nuWmdJMJ r61BAkA7dxDGAk+KX9fJi8OedIh2AaDcxeOFwqGBy7Sq/kqhgNxn918XhOy7gtj0 bFzrP/5lw36M25b00XgpjBbSmaqxAkBnBN/TUHjh1T3OQ0m0uDWdjGI+KAlK3A04 QVrng43ZBXMNeMDRiE+Lzu/JEXjBDFsoXYB+LT/86j5/x721yiNBAkEAgi0F5BvA wYZQXqAx3iyuj8R9uUKpLePafyBRHnLNrFux2VD0ZX3pXCmfDDmtM/NMO491dI84 6NbVOvxWcNPQ/Q==
說明:
java和php的RSA加解密版本已全部通過測試。並且可以相互加解密。
私鑰是服務器保留,公鑰可以發放給對應的客戶端,甚至可以是公共的。
采用私鑰加密-》公鑰解密 和 公鑰加密-》私鑰解密 的加密方式。
但是如果客戶端是需要更高安全性的支付系統,那么應該采用兩對密鑰。
每一方分別是自己的私鑰和對方的公鑰,采用私鑰加密並簽名-》公鑰解密並驗簽的方式。
注意:給出的是兩個版本的兩對密鑰,實際上只是一對密鑰。區別是java的密鑰去掉了頭尾注釋。而PHP的密鑰保留了頭尾注釋。
from:https://blog.csdn.net/panjiapengfly/article/details/75318930
