首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

使用 SNK 強名稱簽名保護 DLL 防反編譯與惡意調用完整教程

     編輯:ASP.NET 基礎

威脅場景

分層架構中,業務邏輯層 (BLL) 引用數據訪問層 (DAL) 的 DLL。若客戶獲取 DLL,可直接引用調用敏感方法(如 ChangePwd、TransferMoney),繞過業務邏輯驗證造成破壞。

核心防護原理

  1. 強名稱簽名:賦予程序集全局唯一標識(名稱+版本+公鑰Token),防止偽造替換
  2. 代碼訪問安全 (CAS):通過 StrongNameIdentityPermission 限制調用者必須持有相同強名稱密鑰
  3. 密鑰隔離:私鑰 (.snk) 僅開發方持有,公鑰編譯進調用者程序集

完整實施步驟

步驟 1:生成強名稱密鑰對

# 開發者命令提示符 (管理員)
sn -k D:\Keys\MyProject.snk

生成包含公私鑰的 MyProject.snk 文件,嚴格保管,勿提交代碼倉庫。

步驟 2:為目標 DLL (如 DAL.dll) 簽名

項目屬性 → 簽名 → 勾選「為程序集簽名」 → 選擇強名稱密鑰文件

或編輯 AssemblyInfo.cs:

[assembly: AssemblyKeyFile(@"D:\Keys\MyProject.snk")]

步驟 3:提取公鑰字符串供調用方驗證

# 1. 從 .snk 導出公鑰
sn -p D:\Keys\MyProject.snk D:\Keys\MyProject.PublicKey.snk

# 2. 顯示公鑰 Token 與十六進制字符串
sn -tp D:\Keys\MyProject.PublicKey.snk

輸出示例:

Microsoft (R) .NET Framework Strong Name Utility  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

Public Key Token: 3b4a5c6d7e8f9a0b
Public Key:
0024000004800000940000000602000000240000525341310004000001000100...
(一長串十六進制字符)

步驟 4:在 DAL 核心類添加權限需求特性

using System;
using System.Security.Permissions;

[StrongNameIdentityPermissionAttribute(
    SecurityAction.LinkDemand,  // 或 Demand
    PublicKey = "0024000004800000940000000602000000240000525341310004000001000100...")]
public class UserRepository
{
    public void ChangePassword(string userName, string newPwd)
    {
        // 敏感操作
    }
}

步驟 5:調用方 (BLL/UI) 同樣簽名同一密鑰

// BLL 項目 AssemblyInfo.cs
[assembly: AssemblyKeyFile(@"D:\Keys\MyProject.snk")]

LinkDemand vs Demand 關鍵區別

特性LinkDemandDemand
檢查範圍直接調用者整個調用堆棧
性能高 (JIT 時檢查一次)低 (每次調用檢查堆棧)
場景信任直接調用者需信任完整調用鏈
繞過風險中間層可包裝調用繞過難繞過

驗證防護效果

  1. 編譯簽名後的 DAL.dll
  2. 未簽名或簽名不同密鑰的測試程序引用 DAL.dll
  3. 調用 ChangePassword 方法
  4. 預期拋出 System.Security.SecurityException:Request for the permission of type 'System.Security.Permissions.StrongNameIdentityPermission' failed.

現代 .NET Core / .NET 5+ 環境下的替代方案

  • 簽名程序集:dotnet sign 或項目屬性簽名,原理相同
  • 內部可見性:[assembly: InternalsVisibleTo("MyTrustedAssembly, PublicKey=...")] 精確控制友元訪問
  • Source Link + NuGet 簽名:供應鏈安全,驗證包來源完整性
  • ReadyToRun / AOT 編譯:提高逆向難度
  • 代碼混淆:Dotfuscator、ConfuserEx 增加反編譯分析成本

關鍵安全實踐

  1. 私鑰離線保管:HSM 硬件安全模塊或加密 USB Key
  2. CI/CD 簽名分離:構建服務器無私鑰,簽名步驟獨立受控
  3. 定期輪換密鑰:年度輪換,建立吊撤機制
  4. 防禦深度:強名稱 + 混淆 + 接口隔離 + 運行時完整性校驗

強名稱簽名配合 CAS 權限需求,構建「持有密鑰者才能調用」的信任邊界,是保護 .NET 組件知識產權與運行時安全的經典有效手段。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved