首頁 微信小程式 微信開發 微信開發之訊息體簽名與加解密

微信開發之訊息體簽名與加解密

May 09, 2017 am 09:33 AM

  前幾篇主要是微信開發的準備工作,也沒有什麼技術含量。在第一篇和第二篇中,我主要講的是使用花生殼來配合vs進行代碼調試,也一度被園友吐槽本人是花生殼請來的逗比,沒辦法,為了和花生殼劃清界限,在本篇進入正文前,為大家介紹一個比花生殼更好用的工具ngrok,ngrok的好處我就不在此具體說明了,畢竟不是本文的重點

   出於安全考慮,微信公眾平台在10月份的時候加入了訊息體的加解密功能,首先,需要先驗證簽名,用於公眾平台和公眾帳號驗證訊息體的正確性,其次,針對推送給公眾號的普通訊息和事件訊息,以及推播給裝置公眾帳號的裝置進行加密,最後,公眾號對密文訊息的回覆也需要加密。啟用加解密功能後,公眾平台伺服器在向公眾號伺服器配置位址推播訊息時,url將新增加上兩個參數,一個是加密類型一個是訊息體簽名,並以此體現新功能。加密演算法採用AES。關於明文模式,相容模式,安全模式的說明,大家請參考官方文件.

驗證訊息真實性和加解密的幫助類官方提供的有demo,再次不詳細講述了,下載下來可以直接調用,下面請看代碼:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Security.Cryptography;using System.IO;using System.Net;namespace WxApi
{    public class Cryptography
    {        public static UInt32 HostToNetworkOrder(UInt32 inval)
        {
            UInt32 outval = 0;            for (int i = 0; i < 4; i++)
                outval = (outval << 8) + ((inval >> (i * 8)) & 255);            return outval;
        }        public static Int32 HostToNetworkOrder(Int32 inval)
        {
            Int32 outval = 0;            for (int i = 0; i < 4; i++)
                outval = (outval << 8) + ((inval >> (i * 8)) & 255);            return outval;
        }        /// <summary>
        /// 解密方法        /// </summary>
        /// <param name="Input">密文</param>
        /// <param name="EncodingAESKey"></param>
        /// <returns></returns>
        /// 
        public static string AES_decrypt(String Input, string EncodingAESKey, ref string appid)
        {            byte[] Key;
            Key = Convert.FromBase64String(EncodingAESKey + "=");            byte[] Iv = new byte[16];
            Array.Copy(Key, Iv, 16);            byte[] btmpMsg = AES_decrypt(Input, Iv, Key);            int len = BitConverter.ToInt32(btmpMsg, 16);
            len = IPAddress.NetworkToHostOrder(len);            byte[] bMsg = new byte[len];            byte[] bAppid = new byte[btmpMsg.Length - 20 - len];
            Array.Copy(btmpMsg, 20, bMsg, 0, len);
            Array.Copy(btmpMsg, 20 + len, bAppid, 0, btmpMsg.Length - 20 - len);            string oriMsg = Encoding.UTF8.GetString(bMsg);
            appid = Encoding.UTF8.GetString(bAppid);            return oriMsg;
        }        public static String AES_encrypt(String Input, string EncodingAESKey, string appid)
        {            byte[] Key;
            Key = Convert.FromBase64String(EncodingAESKey + "=");            byte[] Iv = new byte[16];
            Array.Copy(Key, Iv, 16);            string Randcode = CreateRandCode(16);            byte[] bRand = Encoding.UTF8.GetBytes(Randcode);            byte[] bAppid = Encoding.UTF8.GetBytes(appid);            byte[] btmpMsg = Encoding.UTF8.GetBytes(Input);            byte[] bMsgLen = BitConverter.GetBytes(HostToNetworkOrder(btmpMsg.Length));            byte[] bMsg = new byte[bRand.Length + bMsgLen.Length + bAppid.Length + btmpMsg.Length];

            Array.Copy(bRand, bMsg, bRand.Length);
            Array.Copy(bMsgLen, 0, bMsg, bRand.Length, bMsgLen.Length);
            Array.Copy(btmpMsg, 0, bMsg, bRand.Length + bMsgLen.Length, btmpMsg.Length);
            Array.Copy(bAppid, 0, bMsg, bRand.Length + bMsgLen.Length + btmpMsg.Length, bAppid.Length);            return AES_encrypt(bMsg, Iv, Key);

        }        private static string CreateRandCode(int codeLen)
        {            string codeSerial = "2,3,4,5,6,7,a,c,d,e,f,h,i,j,k,m,n,p,r,s,t,A,C,D,E,F,G,H,J,K,M,N,P,Q,R,S,U,V,W,X,Y,Z";            if (codeLen == 0)
            {
                codeLen = 16;
            }            string[] arr = codeSerial.Split(&#39;,&#39;);            string code = "";            int randValue = -1;
            Random rand = new Random(unchecked((int)DateTime.Now.Ticks));            for (int i = 0; i < codeLen; i++)
            {
                randValue = rand.Next(0, arr.Length - 1);
                code += arr[randValue];
            }            return code;
        }        private static String AES_encrypt(String Input, byte[] Iv, byte[] Key)
        {            var aes = new RijndaelManaged();            //秘钥的大小,以位为单位
            aes.KeySize = 256;            //支持的块大小
            aes.BlockSize = 128;            //填充模式
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;
            aes.Key = Key;
            aes.IV = Iv;            var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);            byte[] xBuff = null;            using (var ms = new MemoryStream())
            {                using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
                {                    byte[] xXml = Encoding.UTF8.GetBytes(Input);
                    cs.Write(xXml, 0, xXml.Length);
                }
                xBuff = ms.ToArray();
            }
            String Output = Convert.ToBase64String(xBuff);            return Output;
        }        private static String AES_encrypt(byte[] Input, byte[] Iv, byte[] Key)
        {            var aes = new RijndaelManaged();            //秘钥的大小,以位为单位
            aes.KeySize = 256;            //支持的块大小
            aes.BlockSize = 128;            //填充模式            //aes.Padding = PaddingMode.PKCS7;
            aes.Padding = PaddingMode.None;
            aes.Mode = CipherMode.CBC;
            aes.Key = Key;
            aes.IV = Iv;            var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);            byte[] xBuff = null;            #region 自己进行PKCS7补位,用系统自己带的不行            byte[] msg = new byte[Input.Length + 32 - Input.Length % 32];
            Array.Copy(Input, msg, Input.Length);            byte[] pad = KCS7Encoder(Input.Length);
            Array.Copy(pad, 0, msg, Input.Length, pad.Length);            #endregion

            #region 注释的也是一种方法,效果一样            //ICryptoTransform transform = aes.CreateEncryptor();            //byte[] xBuff = transform.TransformFinalBlock(msg, 0, msg.Length);
            #endregion

            using (var ms = new MemoryStream())
            {                using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
                {
                    cs.Write(msg, 0, msg.Length);
                }
                xBuff = ms.ToArray();
            }

            String Output = Convert.ToBase64String(xBuff);            return Output;
        }        private static byte[] KCS7Encoder(int text_length)
        {            int block_size = 32;            // 计算需要填充的位数
            int amount_to_pad = block_size - (text_length % block_size);            if (amount_to_pad == 0)
            {
                amount_to_pad = block_size;
            }            // 获得补位所用的字符
            char pad_chr = chr(amount_to_pad);            string tmp = "";            for (int index = 0; index < amount_to_pad; index++)
            {
                tmp += pad_chr;
            }            return Encoding.UTF8.GetBytes(tmp);
        }        /**
         * 将数字转化成ASCII码对应的字符,用于对明文进行补码
         * 
         * @param a 需要转化的数字
         * @return 转化得到的字符         */
        static char chr(int a)
        {            byte target = (byte)(a & 0xFF);            return (char)target;
        }        private static byte[] AES_decrypt(String Input, byte[] Iv, byte[] Key)
        {
            RijndaelManaged aes = new RijndaelManaged();
            aes.KeySize = 256;
            aes.BlockSize = 128;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.None;
            aes.Key = Key;
            aes.IV = Iv;            var decrypt = aes.CreateDecryptor(aes.Key, aes.IV);            byte[] xBuff = null;            using (var ms = new MemoryStream())
            {                using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
                {                    byte[] xXml = Convert.FromBase64String(Input);                    byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
                    Array.Copy(xXml, msg, xXml.Length);
                    cs.Write(xXml, 0, xXml.Length);
                }
                xBuff = decode2(ms.ToArray());
            }            return xBuff;
        }        private static byte[] decode2(byte[] decrypted)
        {            int pad = (int)decrypted[decrypted.Length - 1];            if (pad < 1 || pad > 32)
            {
                pad = 0;
            }            byte[] res = new byte[decrypted.Length - pad];
            Array.Copy(decrypted, 0, res, 0, decrypted.Length - pad);            return res;
        }
    }
}
登入後複製
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Xml;using System.Collections;//using System.Web;using System.Security.Cryptography;//-40001 : 签名验证错误//-40002 :  xml解析失败//-40003 :  sha加密生成签名失败//-40004 :  AESKey 非法//-40005 :  appid 校验错误//-40006 :  AES 加密失败//-40007 : AES 解密失败//-40008 : 解密后得到的buffer非法//-40009 :  base64加密异常//-40010 :  base64解密异常namespace WxApi
{   public class MsgCrypt
    {        string m_sToken;        string m_sEncodingAESKey;        string m_sAppID;        enum WXBizMsgCryptErrorCode
        {
            WXBizMsgCrypt_OK = 0,
            WXBizMsgCrypt_ValidateSignature_Error = -40001,
            WXBizMsgCrypt_ParseXml_Error = -40002,
            WXBizMsgCrypt_ComputeSignature_Error = -40003,
            WXBizMsgCrypt_IllegalAesKey = -40004,
            WXBizMsgCrypt_ValidateAppid_Error = -40005,
            WXBizMsgCrypt_EncryptAES_Error = -40006,
            WXBizMsgCrypt_DecryptAES_Error = -40007,
            WXBizMsgCrypt_IllegalBuffer = -40008,
            WXBizMsgCrypt_EncodeBase64_Error = -40009,
            WXBizMsgCrypt_DecodeBase64_Error = -40010
        };        //构造函数        // @param sToken: 公众平台上,开发者设置的Token        // @param sEncodingAESKey: 公众平台上,开发者设置的EncodingAESKey        // @param sAppID: 公众帐号的appid
        public MsgCrypt(string sToken, string sEncodingAESKey, string sAppID)
        {
            m_sToken = sToken;
            m_sAppID = sAppID;
            m_sEncodingAESKey = sEncodingAESKey;
        }        // 检验消息的真实性,并且获取解密后的明文        // @param sMsgSignature: 签名串,对应URL参数的msg_signature        // @param sTimeStamp: 时间戳,对应URL参数的timestamp        // @param sNonce: 随机串,对应URL参数的nonce        // @param sPostData: 密文,对应POST请求的数据        // @param sMsg: 解密后的原文,当return返回0时有效        // @return: 成功0,失败返回对应的错误码
        public int DecryptMsg(string sMsgSignature, string sTimeStamp, string sNonce, string sPostData, ref string sMsg)
        {            if (m_sEncodingAESKey.Length != 43)
            {                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
            }
            XmlDocument doc = new XmlDocument();
            XmlNode root;            string sEncryptMsg;            try
            {
                doc.LoadXml(sPostData);
                root = doc.FirstChild;
                sEncryptMsg = root["Encrypt"].InnerText;
            }            catch (Exception)
            {                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ParseXml_Error;
            }            //verify signature
            int ret = 0;
            ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEncryptMsg, sMsgSignature);            if (ret != 0)                return ret;            //decrypt
            string cpid = "";            try
            {
                sMsg = Cryptography.AES_decrypt(sEncryptMsg, m_sEncodingAESKey, ref cpid);
            }            catch (FormatException)
            {                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecodeBase64_Error;
            }            catch (Exception)
            {                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecryptAES_Error;
            }            if (cpid != m_sAppID)                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateAppid_Error;            return 0;
        }        //将企业号回复用户的消息加密打包        // @param sReplyMsg: 企业号待回复用户的消息,xml格式的字符串        // @param sTimeStamp: 时间戳,可以自己生成,也可以用URL参数的timestamp        // @param sNonce: 随机串,可以自己生成,也可以用URL参数的nonce        // @param sEncryptMsg: 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串,        //                        当return返回0时有效        // return:成功0,失败返回对应的错误码
        public int EncryptMsg(string sReplyMsg, string sTimeStamp, string sNonce, ref string sEncryptMsg)
        {            if (m_sEncodingAESKey.Length != 43)
            {                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
            }            string raw = "";            try
            {
                raw = Cryptography.AES_encrypt(sReplyMsg, m_sEncodingAESKey, m_sAppID);
            }            catch (Exception)
            {                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_EncryptAES_Error;
            }            string MsgSigature = "";            int ret = 0;
            ret = GenarateSinature(m_sToken, sTimeStamp, sNonce, raw, ref MsgSigature);            if (0 != ret)                return ret;
            sEncryptMsg = "";            string EncryptLabelHead = "<Encrypt><![CDATA[";            string EncryptLabelTail = "]]></Encrypt>";            string MsgSigLabelHead = "<MsgSignature><![CDATA[";            string MsgSigLabelTail = "]]></MsgSignature>";            string TimeStampLabelHead = "<TimeStamp><![CDATA[";            string TimeStampLabelTail = "]]></TimeStamp>";            string NonceLabelHead = "<Nonce><![CDATA[";            string NonceLabelTail = "]]></Nonce>";
            sEncryptMsg = sEncryptMsg + "<xml>" + EncryptLabelHead + raw + EncryptLabelTail;
            sEncryptMsg = sEncryptMsg + MsgSigLabelHead + MsgSigature + MsgSigLabelTail;
            sEncryptMsg = sEncryptMsg + TimeStampLabelHead + sTimeStamp + TimeStampLabelTail;
            sEncryptMsg = sEncryptMsg + NonceLabelHead + sNonce + NonceLabelTail;
            sEncryptMsg += "</xml>";            return 0;
        }        public class DictionarySort : System.Collections.IComparer
        {            public int Compare(object oLeft, object oRight)
            {                string sLeft = oLeft as string;                string sRight = oRight as string;                int iLeftLength = sLeft.Length;                int iRightLength = sRight.Length;                int index = 0;                while (index < iLeftLength && index < iRightLength)
                {                    if (sLeft[index] < sRight[index])                        return -1;                    else if (sLeft[index] > sRight[index])                        return 1;                    else
                        index++;
                }                return iLeftLength - iRightLength;

            }
        }        //Verify Signature
        private static int VerifySignature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, string sSigture)
        {            string hash = "";            int ret = 0;
            ret = GenarateSinature(sToken, sTimeStamp, sNonce, sMsgEncrypt, ref hash);            if (ret != 0)                return ret;            //System.Console.WriteLine(hash);
            if (hash == sSigture)                return 0;            else
            {                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateSignature_Error;
            }
        }        public static int GenarateSinature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, ref string sMsgSignature)
        {
            ArrayList AL = new ArrayList();
            AL.Add(sToken);
            AL.Add(sTimeStamp);
            AL.Add(sNonce);
            AL.Add(sMsgEncrypt);
            AL.Sort(new DictionarySort());            string raw = "";            for (int i = 0; i < AL.Count; ++i)
            {
                raw += AL[i];
            }

            SHA1 sha;
            ASCIIEncoding enc;            string hash = "";            try
            {
                sha = new SHA1CryptoServiceProvider();
                enc = new ASCIIEncoding();                byte[] dataToHash = enc.GetBytes(raw);                byte[] dataHashed = sha.ComputeHash(dataToHash);
                hash = BitConverter.ToString(dataHashed).Replace("-", "");
                hash = hash.ToLower();
            }            catch (Exception)
            {                return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ComputeSignature_Error;
            }
            sMsgSignature = hash;            return 0;
        }
    }
}
登入後複製

在處理程序中,首先獲取到公眾平台伺服器發送過來的數據,並轉成字符串。程式碼如下

string postStr = "";
            Stream s = VqiRequest.GetInputStream();//此方法是对System.Web.HttpContext.Current.Request.InputStream的封装,可直接代码
            byte[] b = new byte[s.Length];
            s.Read(b, 0, (int)s.Length);
            postStr = Encoding.UTF8.GetString(b);
登入後複製

然後再分別取得url中的參數:timestamp,nonce,msg_signature,encrypt_type。可以看到,在明文模式下是沒有encrypt_type參數的。如圖:

微信開發之訊息體簽名與加解密

明文模式

 

微信開發之訊息體簽名與加解密

相容模式與安全模式

相容模式與安全模式則加入了訊息體的簽章與加密類型兩個參數。

由於在實際的營運中,相容模式不太可能使用,所以在此不做詳細介紹了。

接著上面的講。取得到url中的參數後,判斷encrypt_type的值是否為aes,如果是則說明是使用的相容模式或安全模式,此時則需呼叫解密相關的方法進行解密。

if (encrypt_type == "aes")
            {
                requestXML.IsAes = true;
                requestXML.EncodingAESKey = aeskey;
                requestXML.token = token;
                requestXML.appid = appid;                var ret = new MsgCrypt(token, aeskey, appid);                int r = ret.DecryptMsg(msg_signature, timestamp, nonce, postStr, ref data);                if (r!=0)
                {
                    WxApi.Base.WriteBug("消息解密失败");                    return null;
               
                }
            }
登入後複製

否則則直接解析接收到的xml字串。

下圖是接收到的密文:

微信開發之訊息體簽名與加解密

解密之後的內容如下:

微信開發之訊息體簽名與加解密

此時就可以解析此xml了。

當需要回覆加密的請求時,回覆的內容也是需要加密的,所以在回覆前需要判斷此條接收到的訊息是否加密,如果是加密的,則需要將需要回覆的內容加密後,再進行回覆。回覆訊息的方法將在下一篇中具體講解,此篇只講解加密的過程。

處理程式碼如下:

private static void Response(WeiXinRequest requestXML, string data)
        {            if (requestXML.IsAes)
            {                var wxcpt = new MsgCrypt(requestXML.token, requestXML.EncodingAESKey, requestXML.appid);
                 wxcpt.EncryptMsg(data, Utils.ConvertDateTimeInt(DateTime.Now).ToString(), Utils.GetRamCode(), ref data);
            }
            Utils.ResponseWrite(data);
      
        }
登入後複製

將接收到的訊息實體和需要回覆的內容xml傳遞過來,如果是加密的,則加密後再Response,否則直接Response。

【相關推薦】

1.微信公眾號平台原始碼下載

2.微智創T+微信機器人原始碼

#

以上是微信開發之訊息體簽名與加解密的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何在PDF中驗證簽名 如何在PDF中驗證簽名 Feb 18, 2024 pm 05:33 PM

我們通常會接收到政府或其他機構發送的PDF文件,有些文件有數位簽章。驗證簽名後,我們會看到SignatureValid訊息和一個綠色勾號。如果簽章未驗證,會顯示有效性未知。驗證簽名很重要,以下看看如何在PDF中進行驗證。如何在PDF中驗證簽名驗證PDF格式的簽名使其更可信,文件更容易被接受。您可以透過以下方式驗證PDF文件中的簽名。在AdobeReader中開啟PDF右鍵點選簽名,然後選擇顯示簽名屬性點選顯示簽署者憑證按鈕從「信任」標籤將簽名新增至「受信任的憑證」清單中點選驗證簽名以完成驗證讓

重新啟動後,Outlook簽名每天都會消失 重新啟動後,Outlook簽名每天都會消失 Feb 19, 2024 pm 05:24 PM

電子郵件簽名對於展示合法性和專業性非常重要,其中包括聯絡資訊和公司標誌。 Outlook用戶經常抱怨簽名在重啟後會消失,這對於希望提高公司知名度的人來說可能會感到沮喪。在本文中,我們將探討不同的修復程序,以解決這個問題。為什麼我的MicrosoftOutlook簽名總是消失?如果您第一次使用MicrosoftOutlook,請確保您的版本不是試用版。試用版可能導致簽名消失。此外,版本體系結構也應與作業系統的版本體系結構相符。如果您發現OutlookWeb應用程式中的電子郵件簽名不時消失,可能是因

用 Python 來實作 RSA 加解密 用 Python 來實作 RSA 加解密 Apr 14, 2023 pm 02:13 PM

昨天看到一篇英文文章[1],展示如何用Python 來實現RSA 演算法,程式碼的邏輯與前文一文搞懂RSA 演算法一樣,不太熟悉RSA 的朋友可以看一下一文搞懂RSA 演算法,裡面對什麼是RSA,RSA 的數學原理進行了說明,並舉了一個簡單的例子,可以說是全知乎最容易讀懂RSA 的文章了(這話來自讀者評論)。這篇英文提供的程式碼我運行了下,發現不能加密中文,於是就修改了下加解密的函數,讓其支援中文加解密。今天的文章就分享如何用 Python 來實現 RSA 加解密的這個過程,幫助你建立

PHP 8 新功能:增加了驗證和簽名 PHP 8 新功能:增加了驗證和簽名 Mar 27, 2024 am 08:21 AM

PHP8是PHP的最新版本,為程式設計師帶來了更多的便利性和功能。這個版本特別關注安全性和效能,其中一個值得注意的新功能是增加了驗證和簽章功能。在本文中,我們將深入了解這些新的功能及其用途。驗證和簽名是電腦科學中非常重要的安全概念。它們通常用於確保傳輸的數據是完整和真實的。在處理線上交易和敏感資訊時,驗證和簽名變得尤為重要,因為如果有人能夠篡改數據,可能會對

PHP中的簽名與驗簽 PHP中的簽名與驗簽 May 23, 2023 pm 04:10 PM

隨著網路技術的發展,安全性成為了一個越來越重要的議題,特別是在網路應用中傳輸資料的安全性。簽章和驗簽技術已成為保障資料安全性的重要手段,PHP作為一種流行的網路程式語言,也提供了簽章和驗簽的相關函數,本文將介紹PHP中的簽章和驗簽。一、簽章與驗簽的概念簽章是指在數位簽章演算法的基礎上,對資料進行加密處理,產生一段特定的字串。透過該字串可以驗證資料的

PHP中的簽名鑑權方法及其應用 PHP中的簽名鑑權方法及其應用 Aug 06, 2023 pm 07:05 PM

PHP中的簽名鑑權方法及其應用隨著網路的發展,Web應用程式的安全性愈發重要。簽名鑑權是一種常見的安全機制,用於驗證請求的合法性和防止未經授權的存取。本文將介紹PHP中的簽章鑑權方法及其應用,並提供程式碼範例。一、什麼是簽名鑑權?簽章鑑權是一種基於金鑰和演算法的驗證機制,透過對請求參數進行加密產生唯一的簽章值,服務端再透過同樣的演算法和金鑰對請求進行解密並驗證簽

PHP微信開發:如何實作訊息加密解密 PHP微信開發:如何實作訊息加密解密 May 13, 2023 am 11:40 AM

PHP是一種開源的腳本語言,廣泛應用於網頁開發和伺服器端編程,尤其在微信開發中得到了廣泛的應用。如今,越來越多的企業和開發者開始使用PHP進行微信開發,因為它成為了真正的易學易用的開發語言。在微信開發中,訊息的加密和解密是一個非常重要的問題,因為它們涉及資料的安全性。對於沒有加密和解密方式的消息,駭客可以輕鬆取得其中的數據,對用戶造成威脅

用PHP開發微信群發工具 用PHP開發微信群發工具 May 13, 2023 pm 05:00 PM

隨著微信的普及,越來越多的企業開始將其作為行銷工具。而微信群發功能,則是企業進行微信行銷的重要手段之一。但是,如果只依靠手動發送,對於行銷人員來說是一件極為費時費力的工作。所以,開發一款微信群發工具就顯得格外重要。本文將介紹如何使用PHP開發微信群發工具。一、準備工作開發微信群發工具,我們需要掌握以下幾個技術點:PHP基礎知識微信公眾平台開發開發工具:Sub

See all articles