In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-10 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces the Wechat development of how to achieve message body signature and encryption and decryption, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article. Next, let the editor take you to understand it.
Code:
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 >Return outval;} public static Int32 HostToNetworkOrder (Int32 inval) {Int32 outval = 0; for (int I = 0; I)
< 4; i++) outval = (outval >Return outval;} / decryption method / ciphertext / 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 = "2Precedence 34JHERE 5Zhi 6Zhi 7Zhi crecediceParticipityParticipityParticipityReferenceComparenceParticipityforcedforcewerenforceforcforceforcedforforceforcforceforcforceweredforcedforceforceforceweredforcedforceforcedforcedforcedforceforcedforcedforcedforceforggforforceforforcewreceddfordforceforcedforcedforcedforcedforceforgecommerce private static string CreateRandCode (int codeLen) {string codeSerial =" 2 forerunners, 3 forces4, 5, 5, 6, and 7, respectively. If (codeLen = = 0) {codeLen = 16;} string [] arr = codeSerial.Split (','); 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: signature verification error / /-40002: xml parsing failed / /-40003: sha encryption generation signature failed / /-40004: AESKey illegal / /-40005: appid verification error / /-40006: AES encryption failure / /-40007: AES decryption failure / /-40008: illegal buffer obtained after decryption / /-40009: base64 encryption exception / /-40010: base64 decryption exception namespace WxApi { Public class MsgCrypt {string m_sToken String EncodingAESKeys; 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} / / constructor / / @ param sToken: Token / / @ param sEncodingAESKey set by the developer on the public platform: EncodingAESKey / / @ param sAppID set by the developer on the public platform: appid public MsgCrypt (string sToken, string sEncodingAESKey, string sAppID) {m_sToken = sToken; m_sAppID = sAppID of the public account M_sEncodingAESKey = sEncodingAESKey } / / verify the authenticity of the message, and obtain the decrypted plaintext / / @ param sMsgSignature: signature string, corresponding to the msg_signature / / @ param sTimeStamp: timestamp of the URL parameter, timestamp / / @ param sNonce: random string of the URL parameter, and nonce / / @ param sPostData: ciphertext of the URL parameter. Corresponding to the data requested by POST / / @ param sMsg: the decrypted original text is valid / / @ return when return returns 0: success 0, and failure returns the corresponding error code 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 } / / encrypt and package the message returned by the enterprise account to the user / / @ param sReplyMsg: the message to be replied to by the enterprise number. The xml format string / / @ param sTimeStamp: timestamp can be generated by yourself, or you can use the random string of the URL parameter timestamp / / @ param sNonce: to generate the message yourself. You can also use the nonce / / @ param sEncryptMsg of the URL parameter: the encrypted ciphertext can directly reply to the user's ciphertext, including the string in xml format of msg_signature, timestamp, nonce, and encrypt. / / valid when return returns 0 / / return: successful 0 The corresponding error code public int EncryptMsg (string sReplyMsg, string sTimeStamp, string sNonce, ref string sEncryptMsg) {if (m_sEncodingAESKey.Length! = 43) {return (int) WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey is returned for failure. } 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 ="; string MsgSigLabelHead = ""; string TimeStampLabelHead = ""; string NonceLabelHead = "" SEncryptMsg = sEncryptMsg + "" + EncryptLabelHead + raw + EncryptLabelTail; sEncryptMsg = sEncryptMsg + MsgSigLabelHead + MsgSigature + MsgSigLabelTail; sEncryptMsg = sEncryptMsg + TimeStampLabelHead + sTimeStamp + TimeStampLabelTail; sEncryptMsg = sEncryptMsg + NonceLabelHead + sNonce + NonceLabelTail; sEncryptMsg + = ""; 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;}} / / VerifySignature 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参数的。如图: 明文模式Compatibility mode and security mode
Compatibility mode and security mode add two parameters: signature and encryption type of the message body.
Since the compatibility mode is unlikely to be used in actual operation, I will not go into detail here.
Go on with the above. After obtaining the parameters in url, determine whether the value of encrypt_type is aes, and if so, indicate the compatibility mode or security mode used. In this case, you need to call the method related to decryption to decrypt.
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 (ringing destroy 0) {WxApi.Base.WriteBug (message decryption failed); return null;}}
Otherwise, the received xml string is parsed directly.
The following picture shows the ciphertext received:
The decrypted content is as follows:
This xml can be parsed at this point.
When you need to reply to an encrypted request, the content of the reply also needs to be encrypted, so you need to judge whether the message received by this message is encrypted before replying. If it is encrypted, you need to encrypt the content that needs to be replied before replying. The method of replying to a message will be explained in detail in the next article, which only explains the process of encryption.
The processing code is as follows:
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 the received message entity and the content that needs to be replied. If it is encrypted, it is encrypted and then Response, otherwise it is directly Response.
Thank you for reading this article carefully. I hope the article "how to achieve message body signature and encryption and decryption" shared by the editor will be helpful to everyone. At the same time, I also hope you can support it and pay attention to the industry information channel. more related knowledge is waiting for you to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.