先来复习一下~在产出Message前我们会需要什麽东西呢?
按照惯例,一样先上图:
重点来了!我们今天会利用AES-CBC
的方式,来加密产生讯息内文,然後官方文件有提到:
加密後的 Byte 以十六进制2位数字串相加
高阶加密标准(Advanced Encryption Standard)是一种常见的对称加密演算法(加密传输,能用於保护电子数据)。
也就是说,在加密
和解密
数据时都是使用相同的金钥。而在 AES 中,可以使用128、192 和256 位密钥,并且用128 位(16字节)来分组加密和解密数据。
AES加密算法的详细介绍与实现
通过分组密码返回的加密数据的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutations )和替换(substitutions)输入数据。
有兴趣的同学们,可以去参考 AES加密算法的实现原理
来个小插曲,到目前为止都还没有正式到C#处理API Request的Model,既然刚好会用到就顺便讲一下吧~
这边想推荐一个笔者平常开发C#专案时,很常使用的线上小工具 Convert Json to C# Classes Online
名副其实的,只要把格式正确的JSON文档丢下去,按下Convert,这个工具就会帮你自动解析成C#的类别(强者其实都会自己写一个自己的Converter,但我就懒...好孩子别学我)
不过这个Converter只会帮你处理基本的型别,像int
到float
decimal
,或是 string
和 DateTime
还是需要自己手动调整(如果有人哪天做了一个可以靠栏位名称自动帮你判断型别的工具,拜托一定要分享给我xd)
取得结果後,贴到自己的程序码动手稍微改改就好罗:
using System;
namespace Qpay_Core.Models
{
public class OrderingMessageModel
{
public string ShopNo { get; set; }
public string OrderNo { get; set; }
public decimal Amount { get; set; }
public string CurrencyID { get; set; }
public string PayType { get; set; }
public ATMParam ATMParam { get; set; }
public CardParam CardParam { get; set; }
public ConvStoreParam ConvStoreParam { get; set; }
public string PrdtName { get; set; }
public string ReturnURL { get; set; }
//http://10.11.22.113:8803/QPay.ApiClient/Store/Return
public string BackendURL { get; set; }
//http://10.11.22.113:8803/QPay.ApiClient/AutoPush/PushSuccess
}
public class ATMParam
{
public string ExpireDate { get; set; } //应该能改用DateTime
}
public class CardParam
{
//待续
}
public class ConvStoreParam
{
//待续
}
}
碍於篇幅的关系,今天先不负责任地找了网路上的sample code来实践CBC模式的AEC加密
AES加密CBC模式相容互通四种程序语言平台【PHP、Javascript、Java、C#】
这位大大用心提供了四种语言,让我们来看一下C#的部分:
public static string Encrypt(string toEncrypt, string key, string iv)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.IV = ivArray;
rDel.Mode = CipherMode.CBC;
rDel.Padding = PaddingMode.Zeros;
ICryptoTransform cTransform = rDel.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static string Decrypt(string toDecrypt, string key, string iv)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.IV = ivArray;
rDel.Mode = CipherMode.CBC;
rDel.Padding = PaddingMode.Zeros;
ICryptoTransform cTransform = rDel.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return UTF8Encoding.UTF8.GetString(resultArray);
}
(2021-09-23补充)
其实上面网友提供的RijndaelManaged
算是年代比较久远的类别了(AES就是利用Rijndael演算法啦xd)
可以去参考 C# 的 Rijndael、AES、AesManaged、AesCryptoServiceProvider类整理分析
从.NET 3.5开始,就有推出了AES
抽象类别,基於一些实作上的细节差异,现在微软MSDN其实是比较推荐使用基於AES
抽象基底类别实作的AesManaged
或**AesCryptoServiceProvider**
(较优),永丰银行提供的samplecode也是这麽做的当初为何不先去好好参考他们的程序码还要自己乱搞阿
这次的铁人赛的其中一项目标是希望能把这些方法封装成完整的.Net Core微服务,前几天的内容因为很简单就先暂且略过不提,不过像这次的AES-CBC加解密,以及先前提过的SHA256,其实都能将这些方法变成共用的Helper(Common)类别函式库
至於要怎麽让代码看起来更简洁也更易读,之後也会从 .Net Core架构 概念开始,再慢慢带到实作部分
今天讲了不少内容,先喘喘口气好了(汗
明天见,See you!
<<: Day 4: LeetCode 995. Minimum Number of K Consecutive Bit Flips(v2)
要不要自己加赛到 42 天?还是乖乖完赛就好? 记得以前还是跑者的时候,练跑距离大概都维持在 8 公...
我们根据昨天的需求画出以下两张图 1. Flowchart 我们先看看 Flowchart 图中的白...
接续昨天的部分,今天的登入会依照你的身分进入不同的页面(以会员、管理员为例)。 首先先增加资料表的内...
阵列资料处理 - map 特性 可以将原始阵列经过处理後,重新组合回传一个新阵列 不会影响原始阵列 ...
已经常用的一些指令集介绍完毕,接下来就是要如何使用 ARM Cortex-M 进行程序设计。 Cor...