[Day 05] 产出回应内文&初探AES CBC加密 - [C#]丰收款API必备前置作业(四)

先来复习一下~在产出Message前我们会需要什麽东西呢?

  1. HashID: [Day 03]取得Nonce与HashID - [C#]丰收款API必备前置作业(二)
  2. IV值: [Day 04] 轻松取得IV值(使用SHA256) - [C#]丰收款API必备前置作业(三)
  3. 加密後的JSON讯息内文 (等等就会讲到啦~)

产生讯息内文(Message)流程说明 :

按照惯例,一样先上图:
https://ithelp.ithome.com.tw/upload/images/20210918/20131205SWMGclwVgr.png

重点来了!我们今天会利用AES-CBC的方式,来加密产生讯息内文,然後官方文件有提到:

加密後的 Byte 以十六进制2位数字串相加

新手小补帖:什麽是AES?

高阶加密标准(Advanced Encryption Standard)是一种常见的对称加密演算法(加密传输,能用於保护电子数据)。
也就是说,在加密解密数据时都是使用相同的金钥。而在 AES 中,可以使用128、192 和256 位密钥,并且用128 位(16字节)来分组加密和解密数据。
AES加密算法的详细介绍与实现

通过分组密码返回的加密数据的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutations )和替换(substitutions)输入数据。

有兴趣的同学们,可以去参考 AES加密算法的实现原理


来个小插曲,到目前为止都还没有正式到C#处理API Request的Model,既然刚好会用到就顺便讲一下吧~

讯息内文JSON解析

这边想推荐一个笔者平常开发C#专案时,很常使用的线上小工具 Convert Json to C# Classes Online
名副其实的,只要把格式正确的JSON文档丢下去,按下Convert,这个工具就会帮你自动解析成C#的类别(强者其实都会自己写一个自己的Converter,但我就懒...好孩子别学我)/images/emoticon/emoticon25.gif

不过这个Converter只会帮你处理基本的型别,像intfloat decimal ,或是 stringDateTime 还是需要自己手动调整(如果有人哪天做了一个可以靠栏位名称自动帮你判断型别的工具,拜托一定要分享给我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
    {
        //待续
    }

}

实作AES-CBC加密

碍於篇幅的关系,今天先不负责任地找了网路上的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)

>>:  [Day9] 预设贴图

[Day30] 前面就是终点,该写什麽呢?

要不要自己加赛到 42 天?还是乖乖完赛就好? 记得以前还是跑者的时候,练跑距离大概都维持在 8 公...

Day07 - Flowchart versus State Diagram 让我们比一比

我们根据昨天的需求画出以下两张图 1. Flowchart 我们先看看 Flowchart 图中的白...

第16天 - PHP 简易登入(3)_判断身分

接续昨天的部分,今天的登入会依照你的身分进入不同的页面(以会员、管理员为例)。 首先先增加资料表的内...

[ Day 23 ] - 阵列资料处理 - map

阵列资料处理 - map 特性 可以将原始阵列经过处理後,重新组合回传一个新阵列 不会影响原始阵列 ...

Day15.进入 ARM 世界: ARM Cortex-M Programming

已经常用的一些指令集介绍完毕,接下来就是要如何使用 ARM Cortex-M 进行程序设计。 Cor...