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