mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2025-07-18 04:33:16 +08:00
test(wxapi): 增加 AES-CBC 解密的单元测试用例
This commit is contained in:
parent
3afb92828c
commit
d3513dbc46
@ -35,6 +35,31 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 基于 CBC 模式加密数据。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="keyBytes">AES 密钥字节数组。</param>
|
||||||
|
/// <param name="ivBytes">加密使用的初始化向量字节数组。</param>
|
||||||
|
/// <param name="plainBytes">待加密数据字节数组。</param>
|
||||||
|
/// <returns>加密后的数据字节数组。</returns>
|
||||||
|
public static byte[] EncryptWithCBC(byte[] keyBytes, byte[] ivBytes, byte[] plainBytes)
|
||||||
|
{
|
||||||
|
if (keyBytes == null) throw new ArgumentNullException(nameof(keyBytes));
|
||||||
|
if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes));
|
||||||
|
if (plainBytes == null) throw new ArgumentNullException(nameof(plainBytes));
|
||||||
|
|
||||||
|
using (SymmetricAlgorithm aes = Aes.Create())
|
||||||
|
{
|
||||||
|
aes.Mode = CipherMode.CBC;
|
||||||
|
aes.Padding = PaddingMode.PKCS7;
|
||||||
|
aes.Key = keyBytes;
|
||||||
|
aes.IV = ivBytes;
|
||||||
|
|
||||||
|
using ICryptoTransform transform = aes.CreateEncryptor();
|
||||||
|
return transform.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基于 CBC 模式解密数据。
|
/// 基于 CBC 模式解密数据。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -54,5 +79,25 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
|
|||||||
);
|
);
|
||||||
return Encoding.UTF8.GetString(plainBytes);
|
return Encoding.UTF8.GetString(plainBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 基于 CBC 模式加密数据。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encodingKey">经 Base64 编码后的 AES 密钥。</param>
|
||||||
|
/// <param name="encodingIV">经 Base64 编码后的 AES 初始化向量。</param>
|
||||||
|
/// <param name="plainText">待加密文本。</param>
|
||||||
|
/// <returns>经 Base64 编码的加密后的数据。</returns>
|
||||||
|
public static string EncryptWithCBC(string encodingKey, string encodingIV, string plainText)
|
||||||
|
{
|
||||||
|
if (encodingKey == null) throw new ArgumentNullException(nameof(encodingKey));
|
||||||
|
if (plainText == null) throw new ArgumentNullException(nameof(plainText));
|
||||||
|
|
||||||
|
byte[] plainBytes = EncryptWithCBC(
|
||||||
|
keyBytes: Convert.FromBase64String(encodingKey),
|
||||||
|
ivBytes: Convert.FromBase64String(encodingIV),
|
||||||
|
plainBytes: Encoding.UTF8.GetBytes(plainText)
|
||||||
|
);
|
||||||
|
return Convert.ToBase64String(plainBytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,18 +11,19 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
|
|||||||
internal static class XmlUtility
|
internal static class XmlUtility
|
||||||
{
|
{
|
||||||
// REF: https://docs.microsoft.com/zh-cn/dotnet/api/system.xml.serialization.xmlserializer#dynamically-generated-assemblies
|
// REF: https://docs.microsoft.com/zh-cn/dotnet/api/system.xml.serialization.xmlserializer#dynamically-generated-assemblies
|
||||||
private static Hashtable _serializers = new Hashtable();
|
private static readonly Hashtable _xmlSerializers = new Hashtable();
|
||||||
|
private static readonly XmlRootAttribute _xmlRoot = new XmlRootAttribute("xml");
|
||||||
|
|
||||||
private static XmlSerializer GetTypedSerializer(Type type)
|
private static XmlSerializer GetTypedSerializer(Type type)
|
||||||
{
|
{
|
||||||
if (type == null) throw new ArgumentNullException(nameof(type));
|
if (type == null) throw new ArgumentNullException(nameof(type));
|
||||||
|
|
||||||
string skey = type.AssemblyQualifiedName ?? type.GetHashCode().ToString();
|
string skey = type.AssemblyQualifiedName ?? type.GetHashCode().ToString();
|
||||||
XmlSerializer? xmlSerializer = (XmlSerializer?)_serializers[skey];
|
XmlSerializer? xmlSerializer = (XmlSerializer?)_xmlSerializers[skey];
|
||||||
if (xmlSerializer == null)
|
if (xmlSerializer == null)
|
||||||
{
|
{
|
||||||
xmlSerializer = new XmlSerializer(type, new XmlRootAttribute("xml"));
|
xmlSerializer = new XmlSerializer(type, _xmlRoot);
|
||||||
_serializers[skey] = xmlSerializer;
|
_xmlSerializers[skey] = xmlSerializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return xmlSerializer;
|
return xmlSerializer;
|
||||||
|
@ -11,18 +11,19 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities
|
|||||||
internal static class XmlUtility
|
internal static class XmlUtility
|
||||||
{
|
{
|
||||||
// REF: https://docs.microsoft.com/zh-cn/dotnet/api/system.xml.serialization.xmlserializer#dynamically-generated-assemblies
|
// REF: https://docs.microsoft.com/zh-cn/dotnet/api/system.xml.serialization.xmlserializer#dynamically-generated-assemblies
|
||||||
private static Hashtable _serializers = new Hashtable();
|
private static readonly Hashtable _xmlSerializers = new Hashtable();
|
||||||
|
private static readonly XmlRootAttribute _xmlRoot = new XmlRootAttribute("xml");
|
||||||
|
|
||||||
private static XmlSerializer GetTypedSerializer(Type type)
|
private static XmlSerializer GetTypedSerializer(Type type)
|
||||||
{
|
{
|
||||||
if (type == null) throw new ArgumentNullException(nameof(type));
|
if (type == null) throw new ArgumentNullException(nameof(type));
|
||||||
|
|
||||||
string skey = type.AssemblyQualifiedName ?? type.GetHashCode().ToString();
|
string skey = type.AssemblyQualifiedName ?? type.GetHashCode().ToString();
|
||||||
XmlSerializer? xmlSerializer = (XmlSerializer?)_serializers[skey];
|
XmlSerializer? xmlSerializer = (XmlSerializer?)_xmlSerializers[skey];
|
||||||
if (xmlSerializer == null)
|
if (xmlSerializer == null)
|
||||||
{
|
{
|
||||||
xmlSerializer = new XmlSerializer(type, new XmlRootAttribute("xml"));
|
xmlSerializer = new XmlSerializer(type, _xmlRoot);
|
||||||
_serializers[skey] = xmlSerializer;
|
_xmlSerializers[skey] = xmlSerializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return xmlSerializer;
|
return xmlSerializer;
|
||||||
|
@ -11,18 +11,19 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Utilities
|
|||||||
internal static class XmlUtility
|
internal static class XmlUtility
|
||||||
{
|
{
|
||||||
// REF: https://docs.microsoft.com/zh-cn/dotnet/api/system.xml.serialization.xmlserializer#dynamically-generated-assemblies
|
// REF: https://docs.microsoft.com/zh-cn/dotnet/api/system.xml.serialization.xmlserializer#dynamically-generated-assemblies
|
||||||
private static Hashtable _serializers = new Hashtable();
|
private static readonly Hashtable _xmlSerializers = new Hashtable();
|
||||||
|
private static readonly XmlRootAttribute _xmlRoot = new XmlRootAttribute("xml");
|
||||||
|
|
||||||
private static XmlSerializer GetTypedSerializer(Type type)
|
private static XmlSerializer GetTypedSerializer(Type type)
|
||||||
{
|
{
|
||||||
if (type == null) throw new ArgumentNullException(nameof(type));
|
if (type == null) throw new ArgumentNullException(nameof(type));
|
||||||
|
|
||||||
string skey = type.AssemblyQualifiedName ?? type.GetHashCode().ToString();
|
string skey = type.AssemblyQualifiedName ?? type.GetHashCode().ToString();
|
||||||
XmlSerializer? xmlSerializer = (XmlSerializer?)_serializers[skey];
|
XmlSerializer? xmlSerializer = (XmlSerializer?)_xmlSerializers[skey];
|
||||||
if (xmlSerializer == null)
|
if (xmlSerializer == null)
|
||||||
{
|
{
|
||||||
xmlSerializer = new XmlSerializer(type, new XmlRootAttribute("xml"));
|
xmlSerializer = new XmlSerializer(type, _xmlRoot);
|
||||||
_serializers[skey] = xmlSerializer;
|
_xmlSerializers[skey] = xmlSerializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return xmlSerializer;
|
return xmlSerializer;
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
|
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
|
||||||
@ -16,9 +11,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
|
|||||||
string rawData = "jsapi_ticket=HoagFKDcsGMVCIY2vOjf9nGrZ3eaM0qXs5ROFN_3k_HrGc0VocemA6wMXkvrL-Ei4IitXxwKF62CJWR8mWXZ3Q&noncestr=e7b435f73835402da44f16640ddc8696×tamp=1621348162&url=https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign";
|
string rawData = "jsapi_ticket=HoagFKDcsGMVCIY2vOjf9nGrZ3eaM0qXs5ROFN_3k_HrGc0VocemA6wMXkvrL-Ei4IitXxwKF62CJWR8mWXZ3Q&noncestr=e7b435f73835402da44f16640ddc8696×tamp=1621348162&url=https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign";
|
||||||
|
|
||||||
string actualHash = Security.SHA1Utility.Hash(rawData);
|
string actualHash = Security.SHA1Utility.Hash(rawData);
|
||||||
string expectdHash = "b214ea1f8ae019c207f8c6ffb843c8474cbab28c";
|
string expectedHash = "b214ea1f8ae019c207f8c6ffb843c8474cbab28c";
|
||||||
|
|
||||||
Assert.Equal(expectdHash, actualHash, ignoreCase: true);
|
Assert.Equal(expectedHash, actualHash, ignoreCase: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(DisplayName = "信息摘要(HMAC-SHA-256)")]
|
[Fact(DisplayName = "信息摘要(HMAC-SHA-256)")]
|
||||||
@ -28,9 +23,22 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
|
|||||||
string rawData = "appid=wx1234567&offer_id=12345678&openid=odkx20ENSNa2w5y3g_qOkOvBNM1g&pf=android&ts=1507530737&zone_id=1&org_loc=/cgi-bin/midas/getbalance&method=POST&secret=zNLgAGgqsEWJOg1nFVaO5r7fAlIQxr1u";
|
string rawData = "appid=wx1234567&offer_id=12345678&openid=odkx20ENSNa2w5y3g_qOkOvBNM1g&pf=android&ts=1507530737&zone_id=1&org_loc=/cgi-bin/midas/getbalance&method=POST&secret=zNLgAGgqsEWJOg1nFVaO5r7fAlIQxr1u";
|
||||||
|
|
||||||
string actualHash = Security.HMACSHA256Utility.Hash(secret, rawData);
|
string actualHash = Security.HMACSHA256Utility.Hash(secret, rawData);
|
||||||
string expectdHash = "1ad64e8dcb2ec1dc486b7fdf01f4a15159fc623dc3422470e51cf6870734726b";
|
string expectedHash = "1ad64e8dcb2ec1dc486b7fdf01f4a15159fc623dc3422470e51cf6870734726b";
|
||||||
|
|
||||||
Assert.Equal(expectdHash, actualHash, ignoreCase: true);
|
Assert.Equal(expectedHash, actualHash, ignoreCase: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact(DisplayName = "AES-CBC 解密")]
|
||||||
|
public void AesCbcDecryptTest()
|
||||||
|
{
|
||||||
|
string iv = "KEWv/gyiIwAfHvjrLeaX6w==";
|
||||||
|
string key = "YZJqKnNFi0KAiKUc0ggC2g==";
|
||||||
|
string cipherText = "Gu2PVnxVWl+jK4F8c0liGxfkB5Bj3m5HRvwgEIk1Yb+36RZ3Bg7YmUnud/ooiHz0PQroipsH7GCjlGwUeT04NwmrFaP1y3dRYPLpS43ed9QZWcFIFo+8vTs3Zco6S98DUvaNEAs8duhz/BzfBOZaIHMziRqEtPFI0ZDzCgJluBirJ6Wl3UkygZ5/QLo3KA53qGdip7K48Rq8XbCwuidTCw==";
|
||||||
|
|
||||||
|
string expectedPlainData = "{\"phoneNumber\":\"186****5613\",\"purePhoneNumber\":\"186****5613\",\"countryCode\":\"86\",\"watermark\":{\"timestamp\":1634545675,\"appid\":\"wxc****17e87e0e0a7\"}}";
|
||||||
|
string actualPlainData = Utilities.AESUtility.DecryptWithCBC(encodingKey: key, encodingIV: iv, encodingCipherText: cipherText);
|
||||||
|
|
||||||
|
Assert.Equal(expectedPlainData, actualPlainData, ignoreCase: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user