`
wj196
  • 浏览: 297767 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

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

分享到:
评论
3 楼 qq_24396407 2018-02-18  
博主,两个问题:
1.如上代码报错:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(Unknown Source)
at java.security.KeyFactory.generatePrivate(Unknown Source)
at com.awservice.unit.JsonEncodeUtil.sign(JsonEncodeUtil.java:89)
at com.awservice.unit.JsonEncodeUtil.main(JsonEncodeUtil.java:154)
Caused by: java.security.InvalidKeyException: invalid key format
at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(Unknown Source)
at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(Unknown Source)
at sun.security.rsa.RSAKeyFactory.generatePrivate(Unknown Source)
... 4 more
Exception in thread "main" java.lang.NullPointerException
at java.net.URLEncoder.encode(Unknown Source)
at com.awservice.unit.JsonEncodeUtil.main(JsonEncodeUtil.java:155)
2.Java签名时,使用16进制字符串有什么意义呢?
签名时传入priKey(需要16进制,然而priKey转16进制是通过UtilString.bytesToHexStr(privateKey.getBytes());)
然后签名方法中又将priKey从16进制转换了回来(UtilString.hexStrToBytes(xxx)),何必多此一举?
请博主解答
2 楼 wj196 2017-01-16  
u011690782 写道
楼主啊,怎么一直报错啊

什么报错啊?Java文件么?
1 楼 u011690782 2016-03-09  
楼主啊,怎么一直报错啊

相关推荐

    asp.net RSA 私钥加密公钥解密 能解 php Java 实现RSA加密互通

    要实现跨平台的RSA加密互通,如ASP.NET与PHP或Java,关键在于密钥格式和加密算法的一致性。PHP使用openssl扩展支持RSA,Java则有java.security包下的KeyPairGenerator和Cipher类。对于PKCS#8格式的私钥,PHP和Java都...

    PHP_JAVA_RSA互通加解密

    在压缩包中的"PHP_JAVA_RSA加密"文件中,应该包含了PHP和Java的示例代码,包括密钥的生成、数据的加解密以及密钥的交换逻辑。通过这些代码,开发者可以了解如何在实际项目中实现PHP和Java之间的RSA互通加解密。在...

    Ras加密解密,PHP和JAVA互通

    在PHP和Java之间实现RSA加密解密的互通,需要确保两个环境都正确地处理PEM格式的密钥,并使用相同的标准库进行加密和解密。PHP中,我们可以使用openssl扩展来操作RSA密钥,例如`openssl_pkey_new()`用于生成密钥对,...

    Delphi(delphi7-XE)标准RSA加密,解密,签名.与C,Java,php等通用

    RSA算法是一种非对称加密...总之,Delphi提供了丰富的工具和库来支持RSA加密和签名,使得开发者能够在各种环境中安全地处理敏感数据。了解并熟练掌握RSA算法及其在Delphi中的应用,对于开发跨平台的安全应用至关重要。

    Delphi RSA加密解密签名工具

    本仓库提供了一个Delphi编写的RSA加密、解密和签名工具,支持生成密钥对,并且能够与C、Java、PHP等语言进行互通加解密操作。 功能特点 RSA加密与解密:支持标准的RSA加密和解密操作,确保数据的安全传输。 签名与...

    Android RSA加密

    由于Android和PHP使用不同的库进行RSA加密,可能存在编码或格式差异。解决互通问题的关键在于保持一致的加密标准,如PKCS#1或OAEP填充方式,以及公钥和私钥的正确导入导出。在Android中,公钥通常以Base64编码的X....

    Rsa 私钥加密 公钥解密

    在JAVA中,可以使用`java.security`和`javax.crypto`包来实现RSA加密和解密。首先,你需要生成KeyPair,然后使用Private和Public Key进行操作。 在C#中,可以利用`System.Security.Cryptography....

    PhpToRsa.php

    phpRSA加密 javaRSA 解密 互通 , phpRSA加密与javaRSA解密加密, phpRSA安全加密

    私钥加密公钥解密JAVA、C#、PHP互通

    在Java、C#和PHP这三种编程语言中,实现私钥加密和公钥解密的关键库分别是Java的Java Cryptography Extension (JCE),C#的System.Security.Cryptography库,以及PHP的OpenSSL扩展。下面将分别介绍这三个平台如何实现...

    PHP、Java des加密解密实例

    总的来说,无论是PHP还是Java,对DES或其他对称加密算法的使用都需要谨慎,确保理解加密过程并正确配置参数,以确保数据的安全性和互通性。同时,随着技术的发展,考虑使用更新、更安全的加密算法,如AES-256,以...

Global site tag (gtag.js) - Google Analytics