最近在傳檔案上傳的功能,想到應該對每一個檔案新增一個對應的 token。這個 token 應該是一個 JSON 加密後的字串,於是我想到用 .NET 裡提供的 AES 相關類別來做加解密。

首先新增一個要轉為 JSON 的類別:

public class TokenInfo
{
    public string Id { get; set; }
    public string Guid { get; set; }
    public string FileName { get; set; }
}

再來是宣告 AesCryptoServiceProvider 的物件,加解密都會用到它:

AesCryptoServiceProvider AESProvider = new AesCryptoServiceProvider();
byte[] key = Encoding.ASCII.GetBytes("1234567812345678");
byte[] iv =  Encoding.ASCII.GetBytes("8765432187654321");
AESProvider.IV = iv;
AESProvider.Key = key;

在設定 Key 跟 IV 的時候,要注意長度,不得小於範例中的長度。

接下來產生要被加密的物件:

string guid = Guid.NewGuid().ToString();
TokenInfo tokenInfo = new TokenInfo
{
    Id = "Peter",
    FileName = "test.jpg",
    Guid = guid
};

然後進行加密:

//encrypt
string jsonStr = System.Text.Json.JsonSerializer.Serialize(tokenInfo);
byte[] source = Encoding.UTF8.GetBytes(jsonStr);
ICryptoTransform cryptoTransform = AESProvider.CreateEncryptor();
byte[] finalBytes = cryptoTransform.TransformFinalBlock(source, 0, source.Length);
string finalStr = Convert.ToBase64String(finalBytes);
Console.WriteLine($"base64 string: {finalStr}");

這邊是將物件轉為 JSON 字串後,利用 AesCryptoServiceProvider 產生的加密物件,將字串轉為 byte array,最後轉為 base64 字串。

接下來是解密的過程:

//decrypt
ICryptoTransform decryptoTransform = AESProvider.CreateDecryptor();
byte[] dataBytes = Convert.FromBase64String(finalStr);
jsonStr = string.Empty;
finalBytes = decryptoTransform.TransformFinalBlock(dataBytes, 0, dataBytes.Length);
string encodeStr = Encoding.UTF8.GetString(finalBytes);
Console.WriteLine($"json string: {encodeStr}");
tokenInfo = System.Text.Json.JsonSerializer.Deserialize<TokenInfo>(encodeStr);
Console.WriteLine(tokenInfo.FileName);

這裡的原始碼則是先將 base64 字串轉回 byte array,跟前面一樣,利用 AesCryptoServiceProvider 產生解密物件,將其轉回 JSON 字串,最後還原為物件。

參考資料