为通过ClickOnce部署的应用程序进行数字签名

ClickOnce是.NET用于Windows应用程序的一种便捷部署方式。不过由于便捷,导致缺少自定义操作的空间。比如需要对通过ClickOnce部署的应用程序的主程序(exe文件)进行数字签名就比较麻烦。下面简单分享下,在既能获得ClickOnce的便捷功能(包括VS自动生成ClickOnce部署包)的同时,又能方便的对应用程序进行签名。

1,为什么要进行数字签名

为了保证系统的安全,现在Windows(比如Windows 8)对于通过网络上下载的应用程序的执行文件都会首先阻止,并提示用户是否要运行。这个时候,同时会提示这个应用程序的发行者。如果一个没有进行数字签名的应用程序,这个时候发行者就为“未知”,签名后,就可以告知用户这个应用程序是由你提供的。在这里,数字签名就是保证这个应用程序是由你发行,并未被第三方更改的。

上面这种情况还好,很多时候,如果你安装了360之类的软件,对于未签名的应用程序,大部分情况是阻止其运行的。如果没有进行数字签名,那么对用户会造成极大困扰。

对执行文件进行数字签名还有诸多好处,我就不一一例举。现在购买一个代码签名的证书也不算贵,对于类似我们这种发行客户端应用程序的厂商而言,是很有必要购买一个证书的。

2,几个误解:程序集强签名、ClickOnce清单签名、安装程序签名

程序集强签名

.NET里面有个概念——程序集强签名。这个只是.NET可以使用这个强签名文件(snk)来对程序集进行签名,保证程序集本身不被篡改。以便保证其他人引用的这个程序集是你开发的。MSDN这样描述:

程序集签名(也称为强名称签名)赋予应用程序或组件一个唯一标识,其他软件可用该标识来显式标识和引用该应用程序或组件。强名称由程序集的简单文本名、版本号、区域性信息(如果提供)以及公钥/私钥对组成。

例如,强命名使应用程序作者和管理员可以指定用于共享组件将使用的一种准确的服务的版本。这使不同的应用程序指定不同的版本,而不会影响其他应用程序。 此外,还可以使用组件的强名称作为安全证据生成两个组件之间的信任关系。

要对程序集进行强签名,无需使用购买的代码签名数字证书,用.NET提供的sn工具就可以生成snk文件,你只要保存好这个文件,就可以保证你的程序集的签名。

但是,程序集强签名并不等于执行文件的数字签名(就算这个程序集是一个exe文件)。并且MSDN中明确说不应该对exe文件进行强签名(虽然我是这样做的)。文件的数字签名实际上是在文件系统级别对任何文件附加一个签名,告知操作系统此文件的发行者是谁。即可以在文件的属性对话框中,看到“数字签名”这项选项卡。

ClickOnce清单签名

另外,对于ClickOnce的应用程序清单(即app.exe.manifest文件)和部署清单(即app.application文件)进行签名。这样的签名实际上保证客户端正确识别ClickOnce部署包的发行者以及完整性,保证不被第三方篡改。如果不对ClickOnce清单进行签名的话,那么在安装(即运行app.application文件)的时候,安装程序就无法显示发行者,在某些企业环境下或某些安全软件下,就可能阻止application文件的运行(尤其你的应用程序需要获取Full Trust权限的时候更是如此)。但是,对于ClickOnce清单进行签名并不会对程序的执行文件进行签名(虽然同样需要代码签名数字证书)。

安装程序签名

使用过ClickOnce部署的同学,应该知道VS在生成ClickOnce部署包的时候,会同时生成一个setup.exe文件。同样,ClickOnce不会自动对这个按照执行文件进行签名。为了保证这个setup.exe能顺利的在客户端机器上运行,最好还是对其进行数字签名。MSDN文档中就有一节内容专门讲述了这个问题——“How to: Sign Setup Files with SignTool.exe (ClickOnce)”。同样,就算setup.exe被签名了,应用程序真正的执行文件还是需要签名的。

当然,正因为有了SignTool这个工具。

3,失败尝试:Post-Build Events

由于我生成ClickOnce部署包,是完全依赖于VS来自动生成的。所以为了最大限度的保证这种自动化,我首先尝试在Post-Build Events中对编译出来的exe程序集(bin文件夹内的)进行签名。不过后来发现,ClickOnce是从obj文件夹里面复制文件;随后对obj中的程序集进行签名,结果ClickOnce包含的程序集还是未签名的。我估计,ClickOnce在打包前会对程序集进行hash检查,如果hash不对,就会自动全新编译(跳过Build Events的执行)。经过几次尝试后,最后还采用ClickOnce打包完成后,再来签名的方法。

4,最终做法:用CMD脚本对ClickOnce部署包进行处理

在重新复习了ClickOnce的一些重打包的命令之后,编写了如下命令行脚本,可以对ClickOnce打包好的部署包中的exe文件进行签名:

   1:  SET _dir=%CD%
   2:   
   3:  ECHO %_dir%
   4:   
   5:  rename eBalance.exe.deploy eBalance.exe
   6:   
   7:  signtool.exe sign /sha1 F0B5D453FE821F3DA370B87933BXXX /t http://timestamp.comodoca.com/authenticode eBalance.exe
   8:   
   9:  mage -update eBalance.exe.manifest
  10:   
  11:  mage -sign eBalance.exe.manifest -ch F0B5D453FE821F3DA370B87933BXXX -ti http://timestamp.comodoca.com/authenticode
  12:   
  13:  rename eBalance.exe eBalance.exe.deploy
  14:   
  15:  cd ..\..
  16:   
  17:  signtool.exe sign /sha1 F0B5D453FE821F3DA370B87933BXXX /t http://timestamp.comodoca.com/authenticode setup.exe
  18:   
  19:  mage -update eBalance.application -appm "%_dir%\eBalance.exe.manifest"
  20:   
  21:  mage -sign eBalance.application -ch F0B5D453FE821F3DA370B87933BXXX -ti http://timestamp.comodoca.com/authenticode
  22:   
  23:  xcopy eBalance.application "%_dir%\eBalance.application"

对上面的脚本简单解释一下:

5行,由于我打包部署的时候,包含了deploy后缀,所以先进行了一个重命名操作

7行,对exe执行文件进行签名,使用的是我安装在本机中的签名证书

9行,更新应用程序清单(即这个应用程序会包含哪些程序集、资源和其他文件)

11行,对应用程序清单重新签名

13行,把exe文件改回deploy后缀,以便接下来更新部署清单的时候能正常执行

17行,对setup.exe进行签名(可选)

19行,更新部署清单,且指明对应的应用程序清单是那个

21行,对部署清单重新签名

23行,用更新且重新签名的部署清单覆盖具体版本目录里面的部署清单

这段脚本需要进入到具体的部署版本目录里(比如:publish\Application Files\eBalance_4_1_13054_7),才能执行。

5,可选做法:手动生成ClickOnce部署包

当然,通过利用signtool、mage工具,你可以编写一段更加复杂的脚本(甚至使用PowerShell),来完全用脚本执行签名、生成相关清单,打包的工作。具体可以参考MSDN文档:http://msdn.microsoft.com/zh-cn/library/xc3tc5xx.aspx

为通过ClickOnce部署的应用程序进行数字签名的更多相关文章

  1. 获取使用ClickOnce部署的应用程序的版本号

    引子 在编写使用ClickOnce部署的应用程序时,需要在程序的标题栏.软件变更记录.软件关于等页面读取显示当前的版本号. 之前很傻瓜的做法就是在Resource中维护一个string值,在使用到的地 ...

  2. 以管理员身份启动ClickOnce部署的应用程序

    ClickOnce方式部署应用简单方便,估计很多人都用过,但这种方式存在一定的“缺陷”,即以管理员方式启动应用的问题,虽然出于安全考虑可以理解,但给需要管理员权限才能正常运行的程序带来了一定的麻烦,这 ...

  3. ClickOnce部署疑难杂症:更新时部署与应用程序标识不一致问题。要安装此应用程序,请修改此文件的清单版本或卸载之前存在的应用程序。

    使用ClickOnce部署winform应用程序.无论是安装或者自动更新都极为方便,但有时候一些疑难杂症也令人头疼 1.注意每次部署完成之后 setup.exe无需覆盖,只需要在Application ...

  4. C# ClickOnce部署WinForm程序

    之前做过ClickOnce部署应用程序的项目,今天做一次全面的总结.那么这些都是微软提供方便分布式部署的相关解决方法,这种方法既有弊端,也有优点. 最大的缺点: 远程部署,不能更换安装目录:并且每次安 ...

  5. 使用ClickOnce发布Windows应用程序

    前言 因本人工作需要,在一名非常非常好的老师的指导下,入门了C#,再次向老师表示感谢. 本人平时经常遇到的业务就是将数据下发给各部门,并让各部门再上报,此过程中经常会遇到数据格式不正确,数据错误等诸多 ...

  6. 转:ClickOnce部署Winform程序的方方面面

    1. ClickOnce简介 微软官方对ClickOnce的解释是:ClickOnce 是一项部署技术,您可以利用这项技术来创建基于 Windows 的自行更新的应用程序,并且安装和运行这类应用程序所 ...

  7. ClickOnce部署

    (1):一些发布方式 ClickOnce是什么玩意儿,这个问题嘛,在21世纪的互联网严重发达的时代,估计也没有必要大费奏章去介绍了,弄不好的话,还有抄袭之嫌.因此,有关ClickOnce的介绍,各位朋 ...

  8. ClickOnce部署(5):自定义安全权限

    今天我们来探讨一下在ClickOnce部署中如何严格控制应用程序的权限. 演示应用 为了在下文中能更好地演示,我们先要做一个测试项目.也为了显得简单易懂,我使用最常用且最常见的WinForm项目,这是 ...

  9. ClickOnce部署(4):下载多个安装包

    有时候,我们可能会一次性发布多个安装包,当然在网页上多加几个链接让用户逐个安装也是可取的.不过,也可以弄得更方便些,即用户先安装一个,作为一个"引导程序",然后通过这个程序去下载安 ...

随机推荐

  1. outlook自动备份

    在 这里 下载 http://support.microsoft.com/kb/238782

  2. Unofficial Microsoft SQL Server Driver for PHP (sqlsrv)非官方的PHP SQL Server 驱动

    原文 Unofficial Microsoft SQL Server Driver for PHP (sqlsrv) Here are unofficial modified builds of Mi ...

  3. jQuery 表格

    jQuery 表格插件汇总     本文搜集了大量 jQuery 表格插件,帮助 Web 设计者更好地驾御 HTML 表格,你可以对表格进行横向和竖向排序,设置固定表头,对表格进行搜索,对大表格进行分 ...

  4. 用一条SQL语句取出第 m 条到第 n 条记录的方法

    原文:用一条SQL语句取出第 m 条到第 n 条记录的方法   --从Table 表中取出第 m 条到第 n 条的记录:(Not In 版本)       *    FROM Table     id ...

  5. SQL点滴5—产生时间demention,主要是时间转换

    原文:SQL点滴5-产生时间demention,主要是时间转换 数据仓库中有时间表,存储时间信息,这个存储过程接收开始时间结束时间,写入时间具体信息.有高手用excel函数功能很快能产生INSERT语 ...

  6. android数据库升级的措辞

    在基类table增加upgrade操作: public abstract class DbBaseTable { private static final String TAG = "DbB ...

  7. UC编程:通过fwrite()和write()比较标准库函数和系统调用的速度

    fwrte是C标准库中提供的函数,是对write函数的扩展与封装,write则是Unix系统提供的函数.按照常理来讲,系统调用肯定比使用库快的多,但是事实正好相反 Why?原因就在于缓冲的问题,fwi ...

  8. Linux Kernel的Makefile与Kconfig文件的语法

    https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt Introduction ------------ The c ...

  9. 【PLSQL】过程procedure形参和参数

    ************************************************************************   ****原文:blog.csdn.net/clar ...

  10. CreateFont详细解释

    CFont * f;    f = new CFont;    f->CreateFont(10, // nHeight         0, // nWidth         0, // n ...