为通过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. .NET源代码的内部排序实现

    使用JetBrains的DotPeek工具能够方便地查看.net的部分源代码.于是看了一下.NET的内部是怎样实现排序的算法. 在System.Collections.Generic 命名空间下能够看 ...

  2. 阐述 QUEST CENTRAL FOR DB2 八罪

    作为一个从事oracle plsql发展2猿 - 年计划,现在,在退出DB2数据仓库项目. 同PL/SQL Developer参考,下文PLSQL,阐述QUEST CENTRAL FOR DB2 5. ...

  3. 简洁vim配置方案Janus(1)

    最近不想在编辑器上花太多的精力,所以找到个不错的解决方案. 在不懂vim配置的前提下也能用的很开心. 1,下载安装Janus(https://github.com/carlhuda/janus) 安装 ...

  4. Swift初探一

    今天安装了一下Xcode6-Beta版,想来体验一下Swift的魅力:安装Swift系统最低版本号为:10.9.3 仅仅看看一点The Swift Programming Language,以下给大家 ...

  5. 实例学习SSIS(四)--使用日志记录和错误流重定向

    原文:实例学习SSIS(四)--使用日志记录和错误流重定向 导读: 实例学习SSIS(一)--制作一个简单的ETL包 实例学习SSIS(二)--使用迭代 实例学习SSIS(三)--使用包配置 实例学习 ...

  6. js根据IP地址判断城市

    var province = '' ;var city = '' ;jQuery.getScript("http://int.dpool.sina.com.cn/iplookup/iploo ...

  7. Xamarin.Android学习之应用程序首选项

    Xamarin.Android学习之应用程序首选项 一.前言 任何App都会存在设置界面,如果开发者利用普通控件并绑定监听事件保存设置,这一过程会非常的枯燥,而且耗时.我们可以看到Android系统的 ...

  8. cocos2d-x3.2中将XCode发展project转移到VS2010可能会发生错误

    一些代码在线xcode写.我们希望我们自己的屌丝vs上述的实施,要重新构建它project,然后加载.但是绝对 没想到在VS里新建project再加入文件,编译后出现了好多错误.以下就把解决这些错误的 ...

  9. php表单(2)

    学习php表单 主要是想知道 前端通过submit之后 后端是如何进行操作的.现在实现一个效果:点击submit,输入框的信息不会被刷掉:刷新页面,输入框的信息被刷掉(index.php). < ...

  10. c# in deep 之委托

    通俗来讲,委托就是吩咐别人去做某件事,但不知道他具体会怎么做.使用委托必须注意的一个问题是内存泄露问题:假如委托实例本身不能被回收,委托实例会阻止他的目标被作为垃圾回收.尤其是假如某“短命”的对象调用 ...