MyException - 我的异常网
当前位置:我的异常网» PHP » PHP和Java的RSA加密相通

PHP和Java的RSA加密相通

www.MyException.Cn  网友分享于:2015-02-11  浏览:0次
PHP和Java的RSA加密互通
一、利用OpenSSL生成RSA公私钥
1.生成RSA私钥
openssl genrsa -out rsa_private_key.pem 1024

示例:

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC19+3Zkg8ko4S7XeAjGl2ps8dEVGx2prFAAsq9OeNjvI4zbUG2
iw7fvk02VZuilYyspB/MR1nMEWreVj21FdnN/szIlC/stptlNMtmkZ28jv8QVvls
8O2Zp97qDxSWbYwZFT1nmQVK1uSZV7wMEldWTSlFcLuOXoFGGXndO9062QIDAQAB
AoGASoBHkVyLdqS8Izo8GiMhVemVHBS0k5+L0nlSKEcbIiqAze1dii9E17ZCRoym
O9qezdAkdK6BxVscNgt5GDrqAQvS6LmQ1KQfOF2mr3rNeCjz6RLl4ujl9mjwAikG
HRWBev7Dz9q/YjKg4OaFTTT5HcgnuyLzO2DY8rKA1PM3gkECQQDlPtu0N4gZJe2/
BSqEFwLLme+lQP8d1NNoICAP5U+GowUc885AMMWqOObOUVe/PzaSSObyAsRTht2H
OCalqWh/AkEAyzSUXpThSShB6JQxDC52r+SS9342bEa6z3vSJ2gBfIZObxA25jHS
F7pRh/vXpGXzcsV4fzIDGKz6tEPHfh3wpwJBANUwnrs7RWs1taKGWGKcz7Guh4nk
JxyD9tKHxalitJFd+3xQU4eok7pYznQie3rUe5iRCY0Y+6E987gzhOVc5VsCQFNs
4MT75on8ZyKvRHu1z7Bi7RuCy6EkYKmyMhNPldyj3yulwoQ7S//F1Jc5g8zQtmQW
QmQmCjNlQQAlG4/hht0CQByUzQ2Vj9uB/RXMvPWtGimEENaAO5Q2wF5kWnoyfg8U
8DjPPoFe0B9mWxAjPBCnI3UwW3P7B7TZKrAlf+GbtxE=
-----END RSA PRIVATE KEY-----






2.生成RSA公钥
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

示例:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC19+3Zkg8ko4S7XeAjGl2ps8dE
VGx2prFAAsq9OeNjvI4zbUG2iw7fvk02VZuilYyspB/MR1nMEWreVj21FdnN/szI
lC/stptlNMtmkZ28jv8QVvls8O2Zp97qDxSWbYwZFT1nmQVK1uSZV7wMEldWTSlF
cLuOXoFGGXndO9062QIDAQAB
-----END PUBLIC KEY-----





3.将RSA私钥转换成PKCS8格式
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt

示例:
-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALX37dmSDySjhLtd
4CMaXamzx0RUbHamsUACyr0542O8jjNtQbaLDt++TTZVm6KVjKykH8xHWcwRat5W
PbUV2c3+zMiUL+y2m2U0y2aRnbyO/xBW+Wzw7Zmn3uoPFJZtjBkVPWeZBUrW5JlX
vAwSV1ZNKUVwu45egUYZed073TrZAgMBAAECgYBKgEeRXIt2pLwjOjwaIyFV6ZUc
FLSTn4vSeVIoRxsiKoDN7V2KL0TXtkJGjKY72p7N0CR0roHFWxw2C3kYOuoBC9Lo
uZDUpB84Xaaves14KPPpEuXi6OX2aPACKQYdFYF6/sPP2r9iMqDg5oVNNPkdyCe7
IvM7YNjysoDU8zeCQQJBAOU+27Q3iBkl7b8FKoQXAsuZ76VA/x3U02ggIA/lT4aj
BRzzzkAwxao45s5RV78/NpJI5vICxFOG3Yc4JqWpaH8CQQDLNJRelOFJKEHolDEM
Lnav5JL3fjZsRrrPe9InaAF8hk5vEDbmMdIXulGH+9ekZfNyxXh/MgMYrPq0Q8d+
HfCnAkEA1TCeuztFazW1ooZYYpzPsa6HieQnHIP20ofFqWK0kV37fFBTh6iTuljO
dCJ7etR7mJEJjRj7oT3zuDOE5VzlWwJAU2zgxPvmifxnIq9Ee7XPsGLtG4LLoSRg
qbIyE0+V3KPfK6XChDtL/8XUlzmDzNC2ZBZCZCYKM2VBACUbj+GG3QJAHJTNDZWP
24H9Fcy89a0aKYQQ1oA7lDbAXmRaejJ+DxTwOM8+gV7QH2ZbECM8EKcjdTBbc/sH
tNkqsCV/4Zu3EQ==
-----END PRIVATE KEY-----





注:php中使用openssl方法,签名和验签,不需要第三步,Java的私钥需要做第三步。

二、PHP的RSA签名和验签方法
1. 签名方法
openssl_sign($msg, $sign, $ key, OPENSSL_ALGO_SHA1);
$msg:要签名的字符串。
$sign:做好签名字符串。

不可以写成 $sign = openssl_sign($msg, $sign, $ key, OPENSSL_ALGO_SHA1);
$ key:密钥,密钥格式,必须为rsa_private_key.pem的格式。
OPENSSL_ALGO_SHA1:密钥算法,如果与Java等交互,必须相互配对。
2. 验签方法
$result= openssl_verify($msg, $sign, $key);
$msg:签名的原字符串。
$sign:签名字符串。
$ key:密钥,密钥格式,必须为rsa_private_key.pem的格式。
$result:验签结果;为1时,验签正确;其余失败。

3. 判断私钥是否是可用
$pi_key =  openssl_pkey_get_private($private_key);
这个函数可用来判断私钥是否是可用的,可用返回

4. 判断公钥是否是可用
$pu_key = openssl_pkey_get_public($public_key);
这个函数可用来判断公钥是否是可用的 

5. 私钥加密 
openssl_private_encrypt($data,$encrypted,$pi_key);
$data :要签名的字符串。
$encrypted:签名后的字符串。
$pi_key:私钥。

6.公钥解密
openssl_public_decrypt($encrypted,$decrypted,$pu_key);
$encrypted:签名字符串。
$decrypted:解签后的字符串。
$pu_key:公钥。
注:3,4,5,6需要联合使用,5,6的这种加解密存在原串过长,加密失败的问题,请谨慎使用。所有使用到的key,请保证是原始串的格式。


三、JAVA的RSA签名和验签方法
1.签名方法
PS: 本方法中使用的密钥需要转换成PKCS8格式

/**
	 * 本方法使用SHA1withRSA签名算法产生签名
	 * @param String priKey 签名时使用的私钥(16进制编码)
	 * @param String src	签名的原字符串
	 * @return String 		签名的返回结果(16进制编码)。当产生签名出错的时候,返回null。
	 */
	public static String generateSHA1withRSASigature(String priKey, String src)
	{
		try
		{
			Signature sigEng = Signature.getInstance("SHA1withRSA");
			byte[] pribyte = UtilString.hexStrToBytes(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 UtilString.bytesToHexStr(signature);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}




2.验签方法

/**
	 * 本方法使用SHA1withRSA签名算法验证签名
	 * @param String pubKey 验证签名时使用的公钥(16进制编码)
	 * @param String sign 	签名结果(16进制编码)
	 * @param String src	签名的原字符串
	 * @return String 		签名的返回结果(16进制编码)
	 */
	public static boolean verifySHA1withRSASigature(String pubKey, String sign, String src)
	{
		try
		{
			Signature sigEng = Signature.getInstance("SHA1withRSA");
			byte[] pubbyte = UtilString.hexStrToBytes(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 = UtilString.hexStrToBytes(sign);
			return sigEng.verify(sign1);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			//LogMan.log("[NeteaseSignUtil][verifySHA1withRSASigature]"+e);
			return false;
		}
	}





PS:解签和验签时签名算法(如SHA1withRSA)一定要使用配套的,
JAVA与PHP互通时也一定要用配套的。


十六进制转换方法:

package com.nloan.cmis.pub.utils;


public class UtilString {
	
	
	private static final char[] bcdLookup =
		{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
	
    
    
	/**
	 * 将字节数组转换为16进制字符串的形式.
	 */
	public static final String bytesToHexStr(byte[] bcd){
		StringBuffer s = new StringBuffer(bcd.length * 2);

		for (int i = 0; i < bcd.length; i++)
		{
			s.append(bcdLookup[(bcd[i] >>> 4) & 0x0f]);
			s.append(bcdLookup[bcd[i] & 0x0f]);
		}

		return s.toString();
	}
    
	
    
	/**
	 * 将16进制字符串还原为字节数组.
	 */
	public static final byte[] hexStrToBytes(String s)	{
		
		byte[] bytes;

		bytes = new byte[s.length() / 2];

		for (int i = 0; i < bytes.length; i++){
			bytes[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2), 16);
		}

		return bytes;
	}
	
	public static void main(String[] args) {
		String str = "aa人民";
//		str = URLEncoder.encode(str);
//		byte[] aa = UtilString.hexStrToBytes(str);
//		String nstr =new String(aa);
//		System.out.println(nstr);
//		System.out.println(UtilString.HexToString(nstr));
		
		//字符串先byte 再十六进制,再字符串
		str=bytesToHexStr(str.getBytes());
		System.out.println(str);
		
		//将16进制字符串还原为字节数组.
		byte[] bb=hexStrToBytes(str);
		System.out.println(new String(hexStrToBytes(str)));
		
	}
}







文档包中的key是配套key值,可直接使用,其他的文件有示例方法,可做参考。
网络参考地址:
http://blog.csdn.net/clh604/article/details/20224735
http://blog.csdn.net/chaijunkun/article/details/7275632

文章评论

Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
老程序员的下场
老程序员的下场
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
程序员都该阅读的书
程序员都该阅读的书
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
那些争议最大的编程观点
那些争议最大的编程观点
代码女神横空出世
代码女神横空出世
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
我是如何打败拖延症的
我是如何打败拖延症的
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
旅行,写作,编程
旅行,写作,编程
每天工作4小时的程序员
每天工作4小时的程序员
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
 程序员的样子
程序员的样子
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
程序员和编码员之间的区别
程序员和编码员之间的区别
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
程序员必看的十大电影
程序员必看的十大电影
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
Java程序员必看电影
Java程序员必看电影
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
中美印日四国程序员比较
中美印日四国程序员比较
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
我的丈夫是个程序员
我的丈夫是个程序员
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
如何成为一名黑客
如何成为一名黑客
漫画:程序员的工作
漫画:程序员的工作
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
一个程序员的时间管理
一个程序员的时间管理
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
程序员应该关注的一些事儿
程序员应该关注的一些事儿
程序员的鄙视链
程序员的鄙视链
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
鲜为人知的编程真相
鲜为人知的编程真相
10个调试和排错的小建议
10个调试和排错的小建议
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有