PHP,C# 和JAVARSA签名及验签

这个功能网上搜了好多资料。贡献一下,转载须注明并对卓二妹的无私奉献表示感谢。

1)签名算法使用SHA1withRSA。

2)签名后的数据位base64编码的密文字符串。

3)三个环境进行签名的私钥的格式不同,需要openssl工具进行转换。

——————————————————————————————————————————

JAVA签名:

1)从包含公私钥的pfx证书中取得.key私钥:

Bat代码  收藏代码

  1. F:\openssl-0.9.8k_WIN32\bin>openssl pkcs12 -in f:\certs\zhuo.pfx -out f:\certs\zhuo.pem  

  2. Enter Import Password:(输入导出时的密码)  

  3. MAC verified OK  

  4. Enter PEM pass phrase:(长度至少为4位的pem证书密码)  

  5. Verifying - Enter PEM pass phrase:(确认一次pem证书密码)  

  6.    

  7. F:\openssl-0.9.8k_WIN32\bin>openssl pkcs8 -topk8 -inform PEM -outform DER -in f:\certs\zhuo.pem -out f:\certs\zhuo_der.key -nocrypt  

  8. Enter pass phrase for f:\certs\zhuo.pem:(输入pem证书密码)  

  

该步骤生成的.key文件即为JAVA签名所需私钥文件。

2)生成公钥:直接从IE中导出X.509格式二进制编码的cer为后缀的公钥证书即可。

 

 

3)签名验签:

 

Java代码  收藏代码

  1. //签名:  

  2. /** 

  3.      *  

  4.      * 函数功能说明: 签名数据 

  5.      * created by zhuoyueping 2013-8-17 

  6.      * modified by zhuoyueping 2013-8-17  

  7.      * 修改内容说明:  

  8.      * @param @param content:签名原文 

  9.      * @param @param keyfile:私钥文件.key路径 

  10.      * @param @return 

  11.      * @param @throws Exception      

  12.      * @return String :base64签名 

  13.      * @throws 

  14.      */  

  15.     public String sign(String content, String keyfile) throws Exception {  

  16.         File file = new File(keyfile); //keyfile key文件的地址  

  17.         FileInputStream in;  

  18.         in = new FileInputStream(file);  

  19.   

  20.         ByteArrayOutputStream bout = new ByteArrayOutputStream();  

  21.         byte[] tmpbuf = new byte[1024];  

  22.         int count = 0;  

  23.         while ((count = in.read(tmpbuf)) != -1) {  

  24.             bout.write(tmpbuf, 0, count);  

  25.             tmpbuf = new byte[1024];  

  26.         }  

  27.         in.close();  

  28.   

  29.         KeyFactory keyFactory = KeyFactory.getInstance("RSA");  

  30.         EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(bout  

  31.                 .toByteArray());  

  32.         RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory  

  33.                 .generatePrivate(privateKeySpec);  

  34.   

  35.         Signature dsa = Signature.getInstance("SHA1withRSA"); //采用SHA1withRSA加密  

  36.         dsa.initSign(privateKey);  

  37.         dsa.update(content.getBytes("UTF-8")); //voucher需要加密的String必须变成byte类型的  

  38.         byte[] sig = dsa.sign();  

  39.   

  40.         String rtnValue = new String(Base64.encode(sig));  

  41.   

  42.         return rtnValue;  

  43.     }  

  44.   

  45.     /** 

  46.      * <p> 

  47.      * 验证签名 

  48.      * </p> 

  49.      * 

  50.      * @param data 原文字节 

  51.      * @param sign 数据签名[BASE64] 

  52.      * @param certificatePath 证书存储路径 

  53.      * @return 

  54.      * @throws Exception 

  55.      */  

  56. public static boolean verifySign(byte[] data, String sign,  

  57.             String certificatePath) throws Exception {  

  58.         // 获得证书  

  59.         X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);  

  60.         return verifySign(data,sign,x509Certificate);  

  61.     }  

  62.   

  63. private static boolean verifySign(byte[] data, String sign, X509Certificate x509Certificate)throws Exception {  

  64.         PublicKey publicKey = x509Certificate.getPublicKey();  

  65.         Signature signature = Signature.getInstance(x509Certificate  

  66.                 .getSigAlgName());  

  67.         signature.initVerify(publicKey);  

  68.         signature.update(data);  

  69.         return signature.verify(Base64.decode(sign.getBytes()));  

  70.     }  

 

C#签名:

1)从包含公私钥的pfx证书中取得.key私钥:

Bat代码  收藏代码

  1. F:\openssl-0.9.8k_WIN32\bin> openssl rsa -in d:\\certs\\zhuo.pfx -nocerts -nodes -out d:\\certs\\zhuo.key  

  2.   

  3. 该步骤生成的.key文件即为C#签名所需私钥文件。  

 

2)公钥生成:于java方式相同,都是二进制格式的x509证书3)签名及验签:

C#代码  收藏代码

  1. using System;  

  2. using System.Text;  

  3. using System.Security.Cryptography;  

  4. using System.Web;  

  5. using System.IO;  

  6. using System.Security.Cryptography.X509Certificates;    

  7.   

  8. namespace Safe  

  9. {  

  10.     public class SafeUtil  

  11.     {  

  12.         /// <summary>  

  13.         /// 验证签名  

  14.         /// </summary>  

  15.         /// <param name="OriginalString">原文:UTF8编码</param>  

  16.         /// <param name="SignatureString">签名:base64编码的字节</param>  

  17.         /// <param name="publicKeyPath">公钥路径</param>  

  18.         /// <returns> 验签结果</returns>  

  19.         public bool Verify(String OriginalString, String SignatureString,String publicKeyPath)  

  20.         {  

  21.                //将base64签名数据转码为字节   

  22.                 byte[] signedBase64 = Convert.FromBase64String(SignatureString);  

  23.                 byte[] orgin = Encoding.UTF8.GetBytes(OriginalString);  

  24.    

  25.                 X509Certificate2 x509_Cer1 = new X509Certificate2(publicKeyPath);  

  26.   

  27.                 RSACryptoServiceProvider oRSA = new RSACryptoServiceProvider();  

  28.                 oRSA.FromXmlString(x509_Cer1.PublicKey.Key.ToXmlString(false));  

  29.   

  30.                 bool bVerify = oRSA.VerifyData(orgin, "SHA1", signedBase64);  

  31.                 return bVerify;  

  32.   

  33.         }  

  34.   

  35.         /// <summary>  

  36.         /// 验证签名  

  37.         /// </summary>  

  38.         /// <param name="data">原文:UTF8编码</param>  

  39.         /// <param name="privateKeyPath">证书路径:D:/certs/mycert.key</param>  

  40.         /// <returns> 验签</returns>  

  41.         public string Sign(string data, string privateKeyPath)  

  42.         {  

  43.             RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPath);  

  44.             byte[] dataBytes = Encoding.UTF8.GetBytes(data);  

  45.             byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");  

  46.             return Convert.ToBase64String(signatureBytes);  

  47.         }  

  48.   

  49.         private  byte[] GetPem(string type, byte[] data)  

  50.         {  

  51.             string pem = Encoding.UTF8.GetString(data);  

  52.             string header = String.Format("-----BEGIN {0}-----", type);  

  53.             string footer = String.Format("-----END {0}-----", type);  

  54.             int start = pem.IndexOf(header) + header.Length;  

  55.             int end = pem.IndexOf(footer, start);  

  56.    

  57.             string base64 = pem.Substring(start, (end - start));  

  58.      

  59.             return Convert.FromBase64String(base64);  

  60.         }  

  61.   

  62.         private  RSACryptoServiceProvider LoadCertificateFile(string filename)  

  63.         {  

  64.             using (System.IO.FileStream fs = System.IO.File.OpenRead(filename))  

  65.             {  

  66.                 byte[] data = new byte[fs.Length];  

  67.                 byte[] res = null;  

  68.                 fs.Read(data, 0, data.Length);  

  69.                 if (data[0] != 0x30)  

  70.                 {  

  71.                     res = GetPem("RSA PRIVATE KEY", data);  

  72.                 }  

  73.                 try  

  74.                 {  

  75.                     RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res);  

  76.                     return rsa;  

  77.                 }  

  78.                 catch (Exception ex)  

  79.                 {  

  80.                 }  

  81.                 return null;  

  82.             }  

  83.         }  

  84.   

  85.         private  RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)  

  86.         {  

  87.             byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;  

  88.                

  89.             // --------- Set up stream to decode the asn.1 encoded RSA private key ------    

  90.             MemoryStream mem = new MemoryStream(privkey);  

  91.             BinaryReader binr = new BinaryReader(mem);  //wrap Memory Stream with BinaryReader for easy reading    

  92.             byte bt = 0;  

  93.             ushort twobytes = 0;  

  94.             int elems = 0;  

  95.             try  

  96.             {  

  97.                 twobytes = binr.ReadUInt16();  

  98.                 if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)    

  99.                     binr.ReadByte();    //advance 1 byte    

  100.                 else if (twobytes == 0x8230)  

  101.                     binr.ReadInt16();    //advance 2 bytes    

  102.                 else  

  103.                     return null;  

  104.   

  105.                 twobytes = binr.ReadUInt16();  

  106.                 if (twobytes != 0x0102) //version number    

  107.                     return null;  

  108.                 bt = binr.ReadByte();  

  109.                 if (bt != 0x00)  

  110.                     return null;  

  111.   

  112.   

  113.                 //------ all private key components are Integer sequences ----    

  114.                 elems = GetIntegerSize(binr);  

  115.                 MODULUS = binr.ReadBytes(elems);  

  116.   

  117.                 elems = GetIntegerSize(binr);  

  118.                 E = binr.ReadBytes(elems);  

  119.   

  120.                 elems = GetIntegerSize(binr);  

  121.                 D = binr.ReadBytes(elems);  

  122.   

  123.                 elems = GetIntegerSize(binr);  

  124.                 P = binr.ReadBytes(elems);  

  125.   

  126.                 elems = GetIntegerSize(binr);  

  127.                 Q = binr.ReadBytes(elems);  

  128.   

  129.                 elems = GetIntegerSize(binr);  

  130.                 DP = binr.ReadBytes(elems);  

  131.   

  132.                 elems = GetIntegerSize(binr);  

  133.                 DQ = binr.ReadBytes(elems);  

  134.   

  135.                 elems = GetIntegerSize(binr);  

  136.                 IQ = binr.ReadBytes(elems);  

  137.   

  138.   

  139.                 // ------- create RSACryptoServiceProvider instance and initialize with public key -----    

  140.                 CspParameters CspParameters = new CspParameters();  

  141.                 CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;  

  142.                 RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);  

  143.                 RSAParameters RSAparams = new RSAParameters();  

  144.                 RSAparams.Modulus = MODULUS;  

  145.                 RSAparams.Exponent = E;  

  146.                 RSAparams.D = D;  

  147.                 RSAparams.P = P;  

  148.                 RSAparams.Q = Q;  

  149.                 RSAparams.DP = DP;  

  150.                 RSAparams.DQ = DQ;  

  151.                 RSAparams.InverseQ = IQ;  

  152.                 RSA.ImportParameters(RSAparams);  

  153.                 return RSA;  

  154.             }  

  155.             catch (Exception ex)  

  156.             {  

  157.                   

  158.                 return null;  

  159.             }  

  160.             finally  

  161.             {  

  162.                 binr.Close();  

  163.             }  

  164.         }  

  165.   

  166.         private  int GetIntegerSize(BinaryReader binr)  

  167.         {  

  168.             byte bt = 0;  

  169.             byte lowbyte = 0x00;  

  170.             byte highbyte = 0x00;  

  171.             int count = 0;  

  172.             bt = binr.ReadByte();  

  173.             if (bt != 0x02)     //expect integer    

  174.                 return 0;  

  175.             bt = binr.ReadByte();  

  176.   

  177.             if (bt == 0x81)  

  178.                 count = binr.ReadByte();    // data size in next byte    

  179.             else  

  180.                 if (bt == 0x82)  

  181.                 {  

  182.                     highbyte = binr.ReadByte(); // data size in next 2 bytes    

  183.                     lowbyte = binr.ReadByte();  

  184.                     byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };  

  185.                     count = BitConverter.ToInt32(modint, 0);  

  186.                 }  

  187.                 else  

  188.                 {  

  189.                     count = bt;     // we already have the data size    

  190.                 }  

  191.   

  192.             while (binr.ReadByte() == 0x00)  

  193.             {   //remove high order zeros in data    

  194.                 count -= 1;  

  195.             }  

  196.             binr.BaseStream.Seek(-1, SeekOrigin.Current);       //last ReadByte wasn't a removed zero, so back up a byte    

  197.             return count;  

  198.         }    

  199.     }  

  200. }  

 

PHP签名:

1)从包含公私钥的pfx证书中取得.key私钥:于C#的证书一致

2)公钥生成:

Bat代码  收藏代码

  1. F:\openssl-0.9.8k_WIN32\bin>openssl pkcs12 -in f:\certs\zhuo.pfx -out f:\certs\zhuo.pem  

 

3)签名及验签:

Php代码  收藏代码

  1. /* 

  2. 签名数据: 

  3. data:utf-8编码的订单原文, 

  4. privatekeyFile:私钥路径 

  5. passphrase:私钥密码 

  6. 返回:base64转码的签名数据 

  7. */  

  8. function sign($data$privatekeyFile,$passphrase)  

  9. {   

  10.   $signature = '';  

  11.     $privatekey = openssl_pkey_get_private(file_get_contents($privatekeyFile), $passphrase);  

  12.   $res=openssl_get_privatekey($privatekey);  

  13.   openssl_sign($data$signature$res);  

  14.   openssl_free_key($res);    

  15.   

  16.   return base64_encode($signature);  

  17. }  

  18.   

  19. /* 

  20. 验证签名: 

  21. data:原文 

  22. signature:签名 

  23. publicKeyPath:公钥路径 

  24. 返回:签名结果,true为验签成功,false为验签失败 

  25. */  

  26. function verity($data$signature$publicKeyPath)  

  27. {  

  28.     $pubKey = file_get_contents('D:/certs/test.pem');  

  29.     $res = openssl_get_publickey($pubKey);  

  30.     $result = (bool)openssl_verify($data, base64_decode($signature), $res);  

  31.     openssl_free_key($res);  

  32.   

  33.     return $result;  

  34. }  

 * PHP需要注意版本和一些包的导入,如果有报错再google了~~


你可能感兴趣的:(PHP,C# 和JAVARSA签名及验签)