Heim >Backend-Entwicklung >PHP-Tutorial >PHP和Java的RSA加密相通

PHP和Java的RSA加密相通

WBOY
WBOYOriginal
2016-06-13 12:15:051694Durchsuche

PHP和Java的RSA加密互通
一、利用OpenSSL生成RSA公私钥
1.生成RSA私钥
openssl genrsa -out rsa_private_key.pem 1024

示例:

-----BEGIN RSA PRIVATE KEY-----MIICXAIBAAKBgQC19+3Zkg8ko4S7XeAjGl2ps8dEVGx2prFAAsq9OeNjvI4zbUG2iw7fvk02VZuilYyspB/MR1nMEWreVj21FdnN/szIlC/stptlNMtmkZ28jv8QVvls8O2Zp97qDxSWbYwZFT1nmQVK1uSZV7wMEldWTSlFcLuOXoFGGXndO9062QIDAQABAoGASoBHkVyLdqS8Izo8GiMhVemVHBS0k5+L0nlSKEcbIiqAze1dii9E17ZCRoymO9qezdAkdK6BxVscNgt5GDrqAQvS6LmQ1KQfOF2mr3rNeCjz6RLl4ujl9mjwAikGHRWBev7Dz9q/YjKg4OaFTTT5HcgnuyLzO2DY8rKA1PM3gkECQQDlPtu0N4gZJe2/BSqEFwLLme+lQP8d1NNoICAP5U+GowUc885AMMWqOObOUVe/PzaSSObyAsRTht2HOCalqWh/AkEAyzSUXpThSShB6JQxDC52r+SS9342bEa6z3vSJ2gBfIZObxA25jHSF7pRh/vXpGXzcsV4fzIDGKz6tEPHfh3wpwJBANUwnrs7RWs1taKGWGKcz7Guh4nkJxyD9tKHxalitJFd+3xQU4eok7pYznQie3rUe5iRCY0Y+6E987gzhOVc5VsCQFNs4MT75on8ZyKvRHu1z7Bi7RuCy6EkYKmyMhNPldyj3yulwoQ7S//F1Jc5g8zQtmQWQmQmCjNlQQAlG4/hht0CQByUzQ2Vj9uB/RXMvPWtGimEENaAO5Q2wF5kWnoyfg8U8DjPPoFe0B9mWxAjPBCnI3UwW3P7B7TZKrAlf+GbtxE=-----END RSA PRIVATE KEY-----




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

示例:
-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC19+3Zkg8ko4S7XeAjGl2ps8dEVGx2prFAAsq9OeNjvI4zbUG2iw7fvk02VZuilYyspB/MR1nMEWreVj21FdnN/szIlC/stptlNMtmkZ28jv8QVvls8O2Zp97qDxSWbYwZFT1nmQVK1uSZV7wMEldWTSlFcLuOXoFGGXndO9062QIDAQAB-----END PUBLIC KEY-----



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

示例:
-----BEGIN PRIVATE KEY-----MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALX37dmSDySjhLtd4CMaXamzx0RUbHamsUACyr0542O8jjNtQbaLDt++TTZVm6KVjKykH8xHWcwRat5WPbUV2c3+zMiUL+y2m2U0y2aRnbyO/xBW+Wzw7Zmn3uoPFJZtjBkVPWeZBUrW5JlXvAwSV1ZNKUVwu45egUYZed073TrZAgMBAAECgYBKgEeRXIt2pLwjOjwaIyFV6ZUcFLSTn4vSeVIoRxsiKoDN7V2KL0TXtkJGjKY72p7N0CR0roHFWxw2C3kYOuoBC9LouZDUpB84Xaaves14KPPpEuXi6OX2aPACKQYdFYF6/sPP2r9iMqDg5oVNNPkdyCe7IvM7YNjysoDU8zeCQQJBAOU+27Q3iBkl7b8FKoQXAsuZ76VA/x3U02ggIA/lT4ajBRzzzkAwxao45s5RV78/NpJI5vICxFOG3Yc4JqWpaH8CQQDLNJRelOFJKEHolDEMLnav5JL3fjZsRrrPe9InaAF8hk5vEDbmMdIXulGH+9ekZfNyxXh/MgMYrPq0Q8d+HfCnAkEA1TCeuztFazW1ooZYYpzPsa6HieQnHIP20ofFqWK0kV37fFBTh6iTuljOdCJ7etR7mJEJjRj7oT3zuDOE5VzlWwJAU2zgxPvmifxnIq9Ee7XPsGLtG4LLoSRgqbIyE0+V3KPfK6XChDtL/8XUlzmDzNC2ZBZCZCYKM2VBACUbj+GG3QJAHJTNDZWP24H9Fcy89a0aKYQQ1oA7lDbAXmRaejJ+DxTwOM8+gV7QH2ZbECM8EKcjdTBbc/sHtNkqsCV/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 >> 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 <br><br><br><br><br>文档包中的key是配套key值,可直接使用,其他的文件有示例方法,可做参考。<br>网络参考地址:<br>http://blog.csdn.net/clh604/article/details/20224735<br>http://blog.csdn.net/chaijunkun/article/details/7275632<br><br><div class="clear">
                 
              
              
        
            </div>
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn