关于.Net的强名称(Strong Name)

.Net中的强名称(Strong Name)

Anor     2008-12-30    Version 1.0


1.关于强名称

强名称是用于标识配件的一种方法(当然它也可以用来标识一个.Net应用程序,应用程序配件单或部署配件单)。它具有充分限定(full qualified)性,可以全局唯一标识一个配件。它由以下几个部分组成:

  • 用于 简单描述配件的名称,如mscorlib;
  • 版本号;
  • 文化信息,包含关于配件的语言环境等信息, 缺省为不确定;
  • 公有密钥;
  • 数字签名

※&nbsp公有密钥和数字签名用于保证配件内容不会被第三方轻易篡改。关于它们的详细信息请参考第3节。

2.为什么使用强名称

和以往非托管(Native/Unmanaged)的组件,如COM,普通的DLL,及弱名称配件仅仅使用简单的名称标识自己相比,.Net配件使用强名称有如下好处:

1) 可以准确地标识一个配件
使用强名称能够准确区分不同的配件,强名称中的版本信息用于识别同一个配件的不同版本,从而避免版本冲突问题,比如DLL地狱(DLL Hell)等问题。
2) 防止配件内容被篡改
强名称对配件的内容采用了相应的签名机制,配合相应的验证机制,虽然不能完全避免但可防止配件内容被第三方轻易地篡改。

※ 其实与传统的直接编译成机器码的程序不同,.Net配件是以托管代码形式存在于PE格式的DLL中的,也就是以微软中间语言代码(MSIL)形式存在。 因此只要熟悉MSIL,第三方就可以很容易地对.Net配件进行篡改,所以使用强名称是保护配件内容安全的方法之一。

3.强签名的实现

3.1强签名

配件强签名的过程如下图所示:


角色、对象:

  • .Net Developer: .Net配件开发者;
  • Strong name Tool(Sn.exe)/Assembly Linker(Al.exe): 配件强签名工具;
  • Strong-naming Assembly:强名称配件;
  • Cryptography:密码系统;
  • Consumer of Strong-named Assembly:强名称配件使用者;

过程:

1)(1-2)配件开发者使用相应的工具如Sn.exe产生用于非对称加解密的密钥对,即一个公有密钥和一个私有密钥。如果使用sn.exe,它将把密钥对保存到指定的文件中;

2)(3)配件开发者将保存的密钥对的文件作为参数请求配件连接器al.exe对配件进行强签名,下面是一个强签名的例子:

al /out:Anor.dll Anor.module /keyfile:1.snk

# 除了使用配件连接器之外,我们也可以通过以下方式请求编译器对配件进行强签名:
  1. 使用编译器选项 如、/keyfie (C#),/KEYFILE(C++);
  2. 在配件源代码中使用配件属性指定密钥对文件。如在C#源代码中可以这样指定:

    [assembly:AssemblyKeyFile("1.snk")]

3)(4-7)强签名工具(al.exe,或相应.Net语言编译器)获取配件内容,并请求密码系统对其进行散列,密码系统对配件内容进行散列后返回其哈希值;

4)(8-9)强签名工具从密钥对文件中摘取私有密钥(Private Key),然后请求密码系统使用私有密钥对配件内容进行非对称加密, 密码系统随后返回加密结果,亦即所谓的数字签名(Digital Signature);

5)(10-11)签名工具从密钥对文件中摘取出公有密钥(Public Key),连同4)获得的配件的数字签名一起存储在配件的装配单中(Assembly Manifest);

6)(12-17)强名称配件使用者引用强名称配件后,在编译时,编译器将从强名称配件中获取该强名称配件的公有密钥(Public Key), 然后请求密码系统对公有密钥进行散列,最后把密码系统返回的哈希值保存在强名称配件使用者的装配件中。

※ 公有密钥散列后的哈希值称之为公有密钥令牌(Public Key Token)。强名称配件使用者之所以保存公有密钥令牌而不是公有密钥本身是为了节省自己的存储空间,因为令牌比密钥本身所需的存储空间小得多。

3.2.延迟签名

从3.1可以看出对配件进行签名需要同时使用公有密钥和私有密钥。在大型项目中,往往存在大量的分别由不同开发人员开发的需要强签名的配件, 这些开发人员都需要使用私有密钥对配件进行强签名。私有密钥同时被许多开发人员使用可能会影响私有密钥的安全性。为了保证私有密钥的安全性,私有密钥应该被保存在少数授权人手中。 另外由于开发过程中配件需要反复的进行编译、测试、修改,在这个过程中对配件反复进行强签名是没有必要的。

为此,可以使用.Net延迟签名机制。配件在开发过程中,开发人员只需使用公有密钥(可以使用Sn.exe从密钥对中摘取出来)对配件进行延迟签名, 这时3.1的步骤2就有些变化了:强签名工具不会对配件的数字签名,而仅把公有密钥保存在配件的装配单中,同时在装配单中为延迟产生的数字签名预留存储空间。

当项目开发完成后,发布时,项目组才使用Sn.exe等强签名工具配合私有密钥对配件进行强签名。签名工具将在配件装配单预留空间中添加配件的数字签名。这就是所谓的延迟签名。

3.3.强签名配件的验证

经过第3节的强签名之后,配件中包含了公有密钥和数字签名,这些信息将成为强签名验证机制(如.Net CLR验证)识别配件和验证配件内容是否被修改的依据。 利用这些信息,同时结合强名称配件使用者所拥有的公共密钥令牌,.Net CLR可以验证所引用的配件内容是否被篡改。其过程如下图所示:


过程:

1)(1)强名称配件使用者引用强名称配件,向CLR提供配件的强名称信息,其中包括它所持有的强名称配件的公有密钥令牌。 CLR根据提供的信息加载相应强名称配件,加载之前需要对配件进行验证;

2)(2-6)验证公共令牌。CLR从强名称配件中获取公有密钥并使用密码系统对其进行散列,然后把散列后的哈希值同强名称配件使用者提供的公有密钥令牌相比较,判断是否相同, 如果相同则继续,否则说明至少有一方的公有密钥相关数据被修改了,验证失败;

3)(7-15)CLR获取强名称配件的内容,然后使用密码系统对配件内容进行散列,获散列后的哈希值。同时CLR请求密码系统使用存放在强名称配件的装配件中的公共密钥 对同样保存在其中的数字签名进行解密从而获得另外一个哈希值。最后比较上述两个哈希值,如果相同说明强名称配件完好无损,未被篡改,验证通过,否则验证失败。

#上述过程中,CLR使用的散列算法应该和强名称工具对强名称配件公共密钥散列时使用的算法一致。实际上,CLR可以从强名称配件使用者的装配件中获知后者使用的散列算法。

4.参考

  1. MSDN library for Visual Studio 2008 (Topic -- Creating and Using Strong-Named Assemblies)
  2. C#技术揭秘(第二版) Tom Archer,Andrew Whitechapel等著

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 ASP.NET 留言板的示例代码: 前端代码(留言页面): ```html <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Messages.aspx.cs" Inherits="MessageBoard.Messages" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta charset="utf-8" /> <title>留言板</title> <style> .message { border: 1px solid #ccc; margin-bottom: 10px; padding: 10px; } </style> </head> <body> <form id="form1" runat="server"> <div> <h1>留言板</h1> <hr /> <h2>发表留言</h2> <p> <label for="txtName">姓名:</label> <asp:TextBox ID="txtName" runat="server"></asp:TextBox> </p> <p> <label for="txtEmail">电子邮件:</label> <asp:TextBox ID="txtEmail" runat="server"></asp:TextBox> </p> <p> <label for="txtMessage">留言内容:</label> <asp:TextBox ID="txtMessage" runat="server" TextMode="MultiLine"></asp:TextBox> </p> <p> <asp:Button ID="btnSubmit" runat="server" Text="提交" OnClick="btnSubmit_Click" /> </p> <hr /> <h2>已发布留言</h2> <div id="messages"> <% foreach (var message in Messages) { %> <div class="message"> <p> <strong><%= message.Name %></strong> <span><%= message.Email %></span> </p> <p> <%= message.Content %> </p> </div> <% } %> </div> </div> </form> </body> </html> ``` 后端代码: ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace MessageBoard { public partial class Messages : System.Web.UI.Page { // 用于存储留言信息的列表 private List<Message> messages = new List<Message>(); // 页面加载时读取已有留言 protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { messages = GetMessages(); } } // 获取所有留言 private List<Message> GetMessages() { // 在实际应用中,可以将留言存储在数据库中 // 这里简化起见,将留言存储在 Session 中 if (Session["Messages"] == null) { Session["Messages"] = new List<Message>(); } return (List<Message>)Session["Messages"]; } // 提交留言 protected void btnSubmit_Click(object sender, EventArgs e) { var message = new Message { Name = txtName.Text, Email = txtEmail.Text, Content = txtMessage.Text }; messages.Add(message); Session["Messages"] = messages; Response.Redirect("Messages.aspx"); } // 留言实体类 private class Message { public string Name { get; set; } public string Email { get; set; } public string Content { get; set; } } // 获取所有留言 private List<Message> Messages { get { return messages; } } } } ``` 这是一个简单的留言板,用户可以填写姓名、电子邮件和留言内容,并提交留言。提交后,留言将被添加到留言列表中。在实际应用中,可以将留言存储在数据库中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值