The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

簡介 ASP.NET Core 資料保護 (Data Protection)

ASP.NET Core Data Protection 提供了一組加密 API (cryptographic API) 來保護資料安全,其中還自動包含了密鑰管理(key management)與密鑰更換(key rotation)等機制。這套技術主要用來長期取代 .NET Framework 的 ASP.NET 1.x ~ 4.x 中 web.config 定義的 <machineKey> 元素,我研究之後發現這套機制不但簡單好上手,背後的金鑰管理也有一定程度的複雜度,可算是相當不錯的資料保護解決方案。這篇文章我想帶大家快速上手 ASP.NET Core 資料保護機制,並透過一個簡單範例說明他的加解密的用法。

Data Protection

關於這個 ASP.NET Core 資料保護的問題陳述設計原理適用對象等重要觀念,已經被完整寫在 ASP.NET Core Data Protection Overview 文件中,建議看英文版本,因為中文翻譯有點糟糕。

為什麼要用 ASP.NET Core 資料保護?

一句話表達:「我需要保存信任的資訊以供稍後擷取,但我不信任持續性機制。」

換句話說就是:「我需要儲存一些敏感的資料在應用程式端,例如帳號、密碼、金鑰、連接字串等資訊,但我不信任儲存在硬碟中的資料,因為本機磁碟中的資料有可能或有機會被駭客存取,如此一來會導致重要資料外洩。」這裡的「本機磁碟」就是「持續性機制」。

官網也用這句話來說:

In web terms, this might be written as "I need to round-trip trusted state via an untrusted client."

我是這樣理解的:「我需要透過不受信任的用戶端來回存取信任的狀態」。這裡的來回存取(round-trip)意思應該是「資料平常都處於加密狀態,有需要的時候才送去一個地方做解密處理,而短暫取回的明文資料,就是 trusted state」。

為了要達到 Authenticity (真實性), Confidentiality (保密性), Isolation (隔離性) 等要求,我們縮小要求的範圍,我們可以提供進一步的約束條件。我們假設在加密系統中操作的所有服務都是平等可信的,並且數據不需要在我們直接控制的服務之外生成消費。此外,我們要求操作盡可能快,因為每個對 Web 服務的請求可能需要通過加密系統一次或多次。這使得對稱加密演算法非常適合我們的情況,我們可以在需要時忽略非對稱加密法。

設計原則 (Design philosophy)

  1. 該系統應提供簡單易用的配置方式

    理想情況下,系統應該是零配置的,開發人員可以立即開始使用。對於需要配置特定方面(例如密鑰庫)的情況,應考慮簡化這些特定配置。

  2. 提供簡單易用的用戶 API (consumer-facing API)

    該 API 應易於正確使用,且難以誤用。

  3. 開發人員不應該學習密鑰管理原則

    系統應代表開發人員處理演算法選擇和密鑰生命週期。理想情況下,開發人員甚至不應接觸到原始密鑰材料。

  4. 在可能的情況下,應保護休息狀態的密鑰

    系統應找到適當的預設保護機制,並自動套用。

快速體驗 ASP.NET Core Data Protection API

  1. 建立 ASP.NET Core Web API 專案

    dotnet new webapi -n AspNetCoreDataProtectionDemo
    cd AspNetCoreDataProtectionDemo
    dotnet new gitignore
    git init
    git add .
    git commit -m "Initial commit"
    
  2. 安裝 Microsoft.AspNetCore.DataProtection 套件

    dotnet add package Microsoft.AspNetCore.DataProtection
    
  3. 修改 Program.cs 註冊 Data Protection 服務到 DI 容器

    builder.Services.AddDataProtection();
    
  4. 加入一個 DataController API 控制器

    以下就是一個完整的範例,非常簡單好上手,對開發人員極度友善!

    其中呼叫 CreateProtector 時要傳入一個 Purpose String 用來區隔不同的保護資料。

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.DataProtection;
    
    namespace AspNetCoreDataProtectionDemo.Controllers
    {
        [ApiController]
        [Route("api/[controller]")]
        public class DataController : ControllerBase
        {
            IDataProtector _protector;
    
            public DataController(IDataProtectionProvider provider)
            {
                // 呼叫 CreateProtector 時要傳入一個 Purpose String 用來區隔不同的保護資料
                _protector = provider.CreateProtector("AspNetCoreDataProtectionDemo.v1");
            }
    
            [HttpGet("encrypt")]
            public ActionResult<String> Encrypt(string data)
            {
                return _protector.Protect(data);
            }
    
            [HttpGet("decrypt")]
            public ActionResult<String> Decrypt(string data)
            {
                return _protector.Unprotect(data);
            }
        }
    }
    
  5. 啟動網站

    dotnet run --no-launch-profile
    

    我加上 --no-launch-profile 是為了能讓 ASP.NET Core 網站跑在預設的 Port 5000,方便後續測試!

  6. 測試資料保護

    傳入 Hello 並回傳保護後的內容

    curl http://localhost:5000/api/data/encrypt?data=Hello
    

    回傳密文結果如下:

    CfDJ8GwUYirwodBDvAnxhXxULD96kPT9pguVgfMGeVnlcOGOrF2fyIJDb9-pwpjYopu5sEkRogzj_zv-AGpiM5lypwL6miYJEmSb3aPl39BWOPHDZ6e_LH8_WKpOougoTucqtw
    
  7. 測試解除資料保護

    傳入密文並回傳解除保護後的內容

    curl http://localhost:5000/api/data/decrypt?data=CfDJ8GwUYirwodBDvAnxhXxULD96kPT9pguVgfMGeVnlcOGOrF2fyIJDb9-pwpjYopu5sEkRogzj_zv-AGpiM5lypwL6miYJEmSb3aPl39BWOPHDZ6e_LH8_WKpOougoTucqtw
    

    回傳結果如下:

    Hello
    

總結

如果你看的懂我上面的範例程式碼,一定會有兩個感覺:

  1. 這程式碼也太簡單了吧?都不用學習各種加解密技術了嗎?

    沒錯,複雜的加密技術都被封裝起來了,這就是一開始設計原則的第一點所述,開發人員不用管這些,會呼叫 API 即可!

  2. 咦?金鑰呢?金鑰在哪裡?不用管理嗎?我要怎樣換金鑰?

    有金鑰,儲存在一個神秘的地方,總之換了一台電腦金鑰就會失效,你只能在本機使用這把隱形的金鑰!

    但你也可以自行指定金鑰儲存的資料夾路徑,接著你就可以在多台電腦共用金鑰來進行加解密。宣告方式如下:

    using Microsoft.AspNetCore.DataProtection;
    
    builder.Services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp-keys"));
    

    金鑰管理請見 Key management in ASP.NET Core 文件說明。

其實 ASP.NET Core Data Protection 文件蠻多的,我還沒完全看完,但基本的加解密應用應該有辦法掌握了,金鑰的管理也有方向,建議想深入研究的朋友可以完整看完官方文件,建立更完整的知識脈絡!👍

相關連結

留言評論