PHP,C# 跟JAVARSA簽名及驗簽

來源:互聯網
上載者:User
PHP,C# 和JAVARSA簽名及驗簽

這個功能網上搜了好多資料。貢獻一下,轉載須註明並對卓二妹的無私奉獻表示感謝。

1)簽名演算法使用SHA1withRSA。

2)簽名後的資料位元base64編碼的密文字串。

3)三個環境進行簽名的私密金鑰的格式不同,需要openssl工具進行轉換。

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

JAVA簽名:

1)從包含公私密金鑰的pfx認證中取得.key私密金鑰:

F:\openssl-0.9.8k_WIN32\bin>openssl pkcs12 -in f:\certs\zhuo.pfx -out f:\certs\zhuo.pemEnter Import Password:(輸入匯出時的密碼)MAC verified OKEnter PEM pass phrase:(長度至少為4位的pem認證密碼)Verifying - Enter PEM pass phrase:(確認一次pem認證密碼) 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 -nocryptEnter pass phrase for f:\certs\zhuo.pem:(輸入pem認證密碼)
??

該步驟產生的.key檔案即為JAVA簽名所需私密金鑰檔案。

2)產生公開金鑰:直接從IE中匯出X.509格式二進位編碼的cer為尾碼的密鑰憑證即可。

?

?

3)簽名驗簽:

?

//簽名:/** *  * 函數功能說明: 簽名資料 * created by zhuoyueping 2013-8-17 * modified by zhuoyueping 2013-8-17  * 修改內容說明:  * @param @param content:簽名原文 * @param @param keyfile:私密金鑰檔案.key路徑 * @param @return * @param @throws Exception      * @return String :base64簽名 * @throws */public String sign(String content, String keyfile) throws Exception {File file = new File(keyfile); //keyfile key檔案的地址FileInputStream in;in = new FileInputStream(file);ByteArrayOutputStream bout = new ByteArrayOutputStream();byte[] tmpbuf = new byte[1024];int count = 0;while ((count = in.read(tmpbuf)) != -1) {bout.write(tmpbuf, 0, count);tmpbuf = new byte[1024];}in.close();KeyFactory keyFactory = KeyFactory.getInstance("RSA");EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(bout.toByteArray());RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec);Signature dsa = Signature.getInstance("SHA1withRSA"); //採用SHA1withRSA加密dsa.initSign(privateKey);dsa.update(content.getBytes("UTF-8")); //voucher需要加密的String必須變成byte類型的byte[] sig = dsa.sign();String rtnValue = new String(Base64.encode(sig));return rtnValue;}/** * 

* 驗證簽名 *

* * @param data 原文位元組 * @param sign 資料簽名[BASE64] * @param certificatePath 憑證存放區路徑 * @return * @throws Exception */public static boolean verifySign(byte[] data, String sign,String certificatePath) throws Exception {// 獲得認證X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);return verifySign(data,sign,x509Certificate);}private static boolean verifySign(byte[] data, String sign, X509Certificate x509Certificate)throws Exception {PublicKey publicKey = x509Certificate.getPublicKey();Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());signature.initVerify(publicKey);signature.update(data);return signature.verify(Base64.decode(sign.getBytes()));}

?

C#簽名:

1)從包含公私密金鑰的pfx認證中取得.key私密金鑰:

F:\openssl-0.9.8k_WIN32\bin> openssl rsa -in d:\\certs\\zhuo.pfx -nocerts -nodes -out d:\\certs\\zhuo.key該步驟產生的.key檔案即為C#簽名所需私密金鑰檔案。
?

2)公開金鑰產生:於java方式相同,都是二進位格式的x509認證3)簽名及驗簽:

using System;using System.Text;using System.Security.Cryptography;using System.Web;using System.IO;using System.Security.Cryptography.X509Certificates;  namespace Safe{    public class SafeUtil    {        ///         /// 驗證簽名        ///         /// 原文:UTF8編碼        /// 簽名:base64編碼的位元組        /// 公開金鑰路徑        ///  驗簽結果        public bool Verify(String OriginalString, String SignatureString,String publicKeyPath)        {               //將base64簽名資料轉碼為位元組                 byte[] signedBase64 = Convert.FromBase64String(SignatureString);                byte[] orgin = Encoding.UTF8.GetBytes(OriginalString);                 X509Certificate2 x509_Cer1 = new X509Certificate2(publicKeyPath);                RSACryptoServiceProvider oRSA = new RSACryptoServiceProvider();                oRSA.FromXmlString(x509_Cer1.PublicKey.Key.ToXmlString(false));                bool bVerify = oRSA.VerifyData(orgin, "SHA1", signedBase64);                return bVerify;        }        ///         /// 驗證簽名        ///         /// 原文:UTF8編碼        /// 憑證路徑:D:/certs/mycert.key        ///  驗簽        public string Sign(string data, string privateKeyPath)        {            RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPath);            byte[] dataBytes = Encoding.UTF8.GetBytes(data);            byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");            return Convert.ToBase64String(signatureBytes);        }        private  byte[] GetPem(string type, byte[] data)        {            string pem = Encoding.UTF8.GetString(data);            string header = String.Format("-----BEGIN {0}-----", 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  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  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  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;        }      }}

?

PHP簽名:

1)從包含公私密金鑰的pfx認證中取得.key私密金鑰:於C#的認證一致

2)公開金鑰產生:

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

?

3)簽名及驗簽:

/*簽名資料:data:utf-8編碼的訂單原文,privatekeyFile:私密金鑰路徑passphrase:私密金鑰密碼返回:base64轉碼的簽名資料*/function sign($data, $privatekeyFile,$passphrase){   $signature = '';$privatekey = openssl_pkey_get_private(file_get_contents($privatekeyFile), $passphrase);  $res=openssl_get_privatekey($privatekey);  openssl_sign($data, $signature, $res);  openssl_free_key($res);    return base64_encode($signature);}/*驗證簽名:data:原文signature:簽名publicKeyPath:公開金鑰路徑返回:簽名結果,true為驗簽成功,false為驗簽失敗*/function verity($data, $signature, $publicKeyPath){$pubKey = file_get_contents('D:/certs/test.pem');$res = openssl_get_publickey($pubKey);$result = (bool)openssl_verify($data, base64_decode($signature), $res);openssl_free_key($res);return $result;}

?* PHP需要注意版本和一些包的匯入,如果有報錯再google了~~

?

?

?

?

?

?

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.