首頁

目前文章總數:157 篇

  

最後更新:2024年 12月 07日

0045. .Net Core Website 實現上傳圖片並且加密,保護重要圖檔

日期:2023年 07月 29日

標籤: C# Asp.net Core Web MVC Web AES Cryptography

摘要:C# 學習筆記


應用所需:1. Visual Studio 2022
     2. .net core Web專案 (Website MVC示範)
範例檔案:連結
解決問題:某些機密的圖片,上傳後可以做加密,增加安全性
應用層面:駭客或有心人士盜取File Server時,即使資料被偷走,也可以放心機密資料不外洩
基本介紹:本篇分為3大部分。
第一部分:範例專案說明
第二部分:一般上傳圖片
第三部分:加密上傳圖片






第一部分:範例專案說明

Step 1:範例專案架構


1. 控制器 一個控制器Home,包含上傳圖片(未加密)、上傳圖片(加密)
2. 檢視頁面 頁面,包含上傳圖片(未加密)、上傳圖片(加密)
3. 商務邏輯 基本驗證、實現上傳檔案到Server、以及加密檔案後再上傳到Server
4. 加密工具 實現對稱式加解密AES,目的是上傳時加密圖檔,讀取時解密圖檔
5. 測試圖片 本次的測試圖片,作者自己畫的2張圖,沒有智慧財產權-法律問題






第二部分:一般上傳圖片

Step 1:上傳圖片頁面

選擇上傳圖片明文頁面,如下圖


Step 2:選擇圖片

選擇一張圖片,可以用範例網站中的TestImage資料夾下的圖片Busy.png做範例

~\\TestImage\\Busy.png




Step 3:點擊上傳

再按下上傳按鈕,上傳檔案




Step 4:上傳成功

上傳成功後,會立刻刷新頁面看到圖片


Step 5:檢視Server

我們到Server上看存放的位置,可以發現圖片成功上傳,但是任何人都可以知道圖片內容
假設駭客或內部員工要搞破壞,只要用一個USB就偷光資料了
※圖片上傳後會重新命名為 MyImage.png

~\\WebSiteUplodaImageEncryptExample\\wwwroot\\MyImage\\MyImage.png







第三部分:加密上傳圖片

Step 1:上傳圖片頁面

選擇上傳圖片加密範例頁面,如下圖


Step 2:選擇圖片上傳

選擇一張圖片,可以用範例網站中的TestImage資料夾下的圖片BrainStorm.png做範例,並且上傳

~\\TestImage\\BrainStorm.png




Step 3:上傳成功

上傳成功後,會立刻刷新頁面看到圖片


Step 4:檢視Server

我們到Server上看存放的位置,可以發現圖片成功上傳,並且已經做過加密
只有透過這個網站用對稱式金鑰解密後才能查看圖片內容
※圖片上傳後會重新命名為 BrainStorm.png

~\\WebSiteUplodaImageEncryptExample\\wwwroot\\MyImage\\BrainStorm.png





Step 5:如何實現-控制器

HomeController.cs 下我們實現了[HttpPost] Action API
到後端後,呼叫 _upload.UploadImageEncrypt(upload.Image);


/// <summary>
/// 上傳加密圖片
/// </summary>
/// <returns></returns>
[HttpPost]
public IActionResult UpLoadFileEncrypt([FromForm] UploadModel upload)
{
    if (ModelState.IsValid)
    {
        _upload.UploadImageEncrypt(upload.Image);
    }
    return RedirectToAction("UploadEncryptImageFile", "Home");
}



Step 6:如何實現-商務邏輯

UploadFileService.cs 實現了加密檔案,並且做上傳的工作
關鍵在呼叫加密工具 var encryptedImageData = CryptoUtil.AesEncrypt(imageData);
下面一行再進行上傳檔案 File.WriteAllBytes(filePath, encryptedImageData);


/// <summary>
/// 上傳圖片-加密
/// </summary>
/// <param name="imageFile"></param>
public void UploadImageEncrypt(IFormFile imageFile)
{
    var path = $"{_environment.WebRootPath}\\MyImage";
    if (!Directory.Exists(path))
    {
        Directory.CreateDirectory(path);
    }
    var filePath = Path.Combine(path, "MyEncryptImage.png");
    using (MemoryStream ms = new MemoryStream())
    {
        imageFile.CopyTo(ms);
        var imageData = ms.ToArray();
        // 將圖片資料進行加密
        var encryptedImageData = CryptoUtil.AesEncrypt(imageData);
        File.WriteAllBytes(filePath, encryptedImageData);
    }
}



Step 7:如何實現-加密過程

加密過程呼叫了 AesEncrypt()
將資料做了AES對稱式加密後輸出byte[]


/// <summary>
/// 1. 自定義固定金鑰
/// </summary>
private const string _AesDefaultKey ="24guDYHrUmj6ll4cIZXmBA8DTY2b8fzN";                                              
       
/// <summary>
/// 2. AES 加密
/// </summary>        
public static byte[] AesEncrypt(byte[] data)
{
    using (Aes aesAlg = Aes.Create())
    {
        aesAlg.Key = Encoding.UTF8.GetBytes(_AesDefaultKey);
        aesAlg.Mode = CipherMode.ECB;
        aesAlg.Padding = PaddingMode.PKCS7;
        ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
        using (MemoryStream msEncrypt = new MemoryStream())
        {
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {
                csEncrypt.Write(data, 0, data.Length);
                csEncrypt.FlushFinalBlock();
            }
            return msEncrypt.ToArray();
        }
    }
}



Step 8:如何實現-讀取圖片

在圖片檢視時 Views/Home/UploadEncryptImageFile.cshtml 我們進行解密圖片
在Razor的 1.1 與 1.2 部分進行讀圖片,並且做Aes解密,並且轉成base64存在 base64Image變數中
在2. 時,Html的img讀取base64Image變數,使原始圖片可以檢視


<!-- 1-1. 讀取圖檔,並且解密 -->
@inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment WebHostEnvironment
@{
    var file = Url.Content("~/MyImage/MyEncryptImage.png");
    var appRootPath = WebHostEnvironment.WebRootPath;    
    var imagePath = System.IO.Path.Combine(appRootPath, "MyImage", "MyEncryptImage.png");
    var base64Image = string.Empty;
    if(System.IO.File.Exists(imagePath))
    {
        var imageBytes = System.IO.File.ReadAllBytes(imagePath);
        //1-2. AES解密
        var originImage = CryptoUtil.AesDecrypt(imageBytes);
        base64Image = Convert.ToBase64String(originImage);
    }
}


<!-- 2. 圖片讀取內容 -->
<img src="data:image/png;base64,@base64Image" style='max-height:300px; max-width:300px' />