您好,欢迎访问一九零五行业门户网

java/php/c#版rsa签字以及java验签实现

java/php/c#版rsa签名以及java验签实现
? ? ? ?在开放平台领域,需要给isv提供sdk,签名是sdk中需要提供的功能之一。由于isv使用的开发语言不是单一的,因此sdk需要提供多种语言的版本。譬如java、php、c#。另外,在电子商务尤其是支付领域,对安全性的要求比较高,所以会采用非对称密钥rsa
? ? ? ?本文主要介绍如何基于java、php、c#在客户端使用rsa签名,然后在服务端使用java验签。
?
基于openssl生成rsa公私钥对a)从网上下载openssl工具,最好是windows下免编译的版本,譬如:http://www.deanlee.cn/programming/openssl-for-windows/? b)生成私钥
进入到openssl的bin目录下,执行以下命令:
openssl genrsa -out rsa_private_key.pem 1024
会在bin目录下看到新生成的私钥文件rsa_private_key.pem,文件内容如下:
-----begin rsa private key-----miicxgibaakbgqdtd1lksx6ylsaewfi7e/ut8krjy9pq7sgykhim9tvidziq5xzyaw8nolzkz1k486mepyg4tsuoaxsbwuplwvuzyfvnuzo7awcigkn16uwtm4nxc/+dwce+bhckrllbtwi8l580lte7gxclth8z7ghq59ivhaogbk7fnxlufb4tsqidaqabaogbaigtk0x1j+hi8khmyppxojcopomi1s9ueewtd7fxab+4g5mbuv/dj62a7nadoki9iyuqe9l3ppvtolmfxcofkku0p4j7mejdz+cjvvgextkwa80nj/uzim1ool6yhwh4ztpty+pfctk1rdn3+070qbb9tnvntbn/jq0ld7f0t7unakea9ryi0kxjl9pupo9neewucuo4xcl9x/m9+mtkfy3vodddv1e/eujmotfanywrjcddiqro0mlyedootilpn77qowjbapzhtv/+pqmvtrlxwnvklz4zvtppgjqqkfdhwwylz7okzb3vbqrt/jlfxuycn2ecp7rglrxnaz7aybftf0ajhescqqddnfkequlqn0gpcddowkril1ppkhgwmwlg1ltetvjgei6kx/prl/vgeiz1dzgctujaoy9r1cefxm/paqh3+/f/akeazstcp6q2hlbldrewkq7ocdiiwkpr5dbgy/rqr6cd7eytdxyeh5gpu1wxkjy/mqaejv9gg/ls9h7mhkfbons6cqjadbeb5vlobdlcsqfdqo/vz9skfhcmhlxluhhiizykgzgf3oxegndsac3qy+ztnld3n5iyrvbk52uoilolhhnmqa==-----end rsa private key-----
? ?c)生成公钥
在bin目录下,执行以下命令:
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
会在bin目录下看到新生成的公钥文件rsa_public_key.pem,文件内容如下:
-----begin public key-----migfma0gcsqgsib3dqebaquaa4gnadcbiqkbgqdtd1lksx6ylsaewfi7e/ut8krjy9pq7sgykhim9tvidziq5xzyaw8nolzkz1k486mepyg4tsuoaxsbwuplwvuzyfvnuzo7awcigkn16uwtm4nxc/+dwce+bhckrllbtwi8l580lte7gxclth8z7ghq59ivhaogbk7fnxlufb4tsqidaqab-----end public key-----
?
?2.?客户端签名
? 2.1?java版签名实现
/** * rsa签名 * * @param content * 待签名的字符串 * @param privatekey * rsa私钥字符串 * @param charset * 字符编码 * @return 签名结果 * @throws exception * 签名失败则抛出异常 */ public string rsasign(string content, string privatekey, string charset) throws signatureexception { try { privatekey prikey = getprivatekeyfrompkcs8(rsa, new bytearrayinputstream(privatekey.getbytes())); signature signature = signature.getinstance(sha1withrsa); signature.initsign(prikey); if (stringutils.isempty(charset)) { signature.update(content.getbytes()); } else { signature.update(content.getbytes(charset)); } byte[] signed = signature.sign(); return new string(base64.encodebase64(signed)); } catch (exception e) { throw new signatureexception(rsacontent = + content + ; charset = + charset, e); } } public privatekey getprivatekeyfrompkcs8(string algorithm, inputstream ins) throws exception { if (ins == null || stringutils.isempty(algorithm)) { return null; } keyfactory keyfactory = keyfactory.getinstance(algorithm); byte[] encodedkey = streamutil.readtext(ins).getbytes(); encodedkey = base64.decodebase64(encodedkey); return keyfactory.generateprivate(new pkcs8encodedkeyspec(encodedkey)); }
?注意:参数privatekey是pem私钥文件中去除头(-----begin rsa private key-----)和尾(-----end rsa private key-----)以及换行符后的字符串。
? 2.2 php签名实现
function sign($content, $rsaprivatekeypem) { $prikey = file_get_contents($rsaprivatekeypem); $res = openssl_get_privatekey($prikey); openssl_sign($content, $sign, $res); openssl_free_key($res); $sign = base64_encode($sign); return $sign; }
?注意:$rsaprivatekeypem为pem私钥文件路径
? 2.3 c#签名实现(引用了国外某位仁兄的方案)
using system;using system.text;using system.security.cryptography;using system.web;using system.io;namespace aop.api.util{ /// /// rsa签名工具类。 /// public class rsautil { public static string rsasign(string data, string privatekeypem) { rsacryptoserviceprovider rsacsp = loadcertificatefile(privatekeypem); byte[] databytes = encoding.utf8.getbytes(data); byte[] signaturebytes = rsacsp.signdata(databytes, sha1); return convert.tobase64string(signaturebytes); } private static byte[] getpem(string type, byte[] data) { string pem = encoding.utf8.getstring(data); string header = string.format(-----begin {0}-----\\n, type); string footer = string.format(-----end {0}-----, type); int start = pem.indexof(header) + header.length; int end = pem.indexof(footer, start); string base64 = pem.substring(start, (end - start)); return convert.frombase64string(base64); } private static rsacryptoserviceprovider loadcertificatefile(string filename) { using (system.io.filestream fs = system.io.file.openread(filename)) { byte[] data = new byte[fs.length]; byte[] res = null; fs.read(data, 0, data.length); if (data[0] != 0x30) { res = getpem(rsa private key, data); } try { rsacryptoserviceprovider rsa = decodersaprivatekey(res); return rsa; } catch (exception ex) { } return null; } } private static rsacryptoserviceprovider decodersaprivatekey(byte[] privkey) { byte[] modulus, e, d, p, q, dp, dq, iq; // --------- set up stream to decode the asn.1 encoded rsa private key ------ memorystream mem = new memorystream(privkey); binaryreader binr = new binaryreader(mem); //wrap memory stream with binaryreader for easy reading byte bt = 0; ushort twobytes = 0; int elems = 0; try { twobytes = binr.readuint16(); if (twobytes == 0x8130) //data read as little endian order (actual data order for sequence is 30 81) binr.readbyte(); //advance 1 byte else if (twobytes == 0x8230) binr.readint16(); //advance 2 bytes else return null; twobytes = binr.readuint16(); if (twobytes != 0x0102) //version number return null; bt = binr.readbyte(); if (bt != 0x00) return null; //------ all private key components are integer sequences ---- elems = getintegersize(binr); modulus = binr.readbytes(elems); elems = getintegersize(binr); e = binr.readbytes(elems); elems = getintegersize(binr); d = binr.readbytes(elems); elems = getintegersize(binr); p = binr.readbytes(elems); elems = getintegersize(binr); q = binr.readbytes(elems); elems = getintegersize(binr); dp = binr.readbytes(elems); elems = getintegersize(binr); dq = binr.readbytes(elems); elems = getintegersize(binr); iq = binr.readbytes(elems); // ------- create rsacryptoserviceprovider instance and initialize with public key ----- cspparameters cspparameters = new cspparameters(); cspparameters.flags = cspproviderflags.usemachinekeystore; rsacryptoserviceprovider rsa = new rsacryptoserviceprovider(1024, cspparameters); rsaparameters rsaparams = new rsaparameters(); rsaparams.modulus = modulus; rsaparams.exponent = e; rsaparams.d = d; rsaparams.p = p; rsaparams.q = q; rsaparams.dp = dp; rsaparams.dq = dq; rsaparams.inverseq = iq; rsa.importparameters(rsaparams); return rsa; } catch (exception ex) { return null; } finally { binr.close(); } } private static int getintegersize(binaryreader binr) { byte bt = 0; byte lowbyte = 0x00; byte highbyte = 0x00; int count = 0; bt = binr.readbyte(); if (bt != 0x02) //expect integer return 0; bt = binr.readbyte(); if (bt == 0x81) count = binr.readbyte(); // data size in next byte else if (bt == 0x82) { highbyte = binr.readbyte(); // data size in next 2 bytes lowbyte = binr.readbyte(); byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; count = bitconverter.toint32(modint, 0); } else { count = bt; // we already have the data size } while (binr.readbyte() == 0x00) { //remove high order zeros in data count -= 1; } binr.basestream.seek(-1, seekorigin.current); //last readbyte wasn't a removed zero, so back up a byte return count; } }}
?
? 3. 服务端java验签
/** * rsa验签 * * @param content 被签名的内容 * @param sign 签名后的结果 * @param publickey rsa公钥 * @param charset 字符集 * @return 验签结果 * @throws signatureexception 验签失败,则抛异常 */ boolean docheck(string content, string sign, string publickey, string charset) throws signatureexception { try { publickey pubkey = getpublickeyfromx509(rsa, new bytearrayinputstream(publickey.getbytes())); signature signature = signature.getinstance(sha1withrsa); signature.initverify(pubkey); signature.update(getcontentbytes(content, charset)); return signature.verify(base64.decodebase64(sign.getbytes())); } catch (exception e) { throw new signatureexception(rsa验证签名[content = + content + ; charset = + charset + ; signature = + sign + ]发生异常!, e); } } private publickey getpublickeyfromx509(string algorithm, inputstream ins) throws nosuchalgorithmexception { try { keyfactory keyfactory = keyfactory.getinstance(algorithm); stringwriter writer = new stringwriter(); streamutil.io(new inputstreamreader(ins), writer); byte[] encodedkey = writer.tostring().getbytes(); // 先base64解码 encodedkey = base64.decodebase64(encodedkey); return keyfactory.generatepublic(new x509encodedkeyspec(encodedkey)); } catch (ioexception ex) { // 不可能发生 } catch (invalidkeyspecexception ex) { // 不可能发生 } return null; } private byte[] getcontentbytes(string content, string charset) throws unsupportedencodingexception { if (stringutil.isempty(charset)) { return content.getbytes(); } return content.getbytes(charset); }
?
其它类似信息

推荐信息