日期:2014-05-17  浏览次数:21052 次

Windows PowerShell 2.0语言开发之脚本签名

Windows PowerShell 2.0语言开发之脚本签名
2010年12月02日
  脚本签名用来保护代码在发布之后,用户使用之前不被篡改。数据源发送方使用自己的私钥加密数据校验和其他与数据内容有关的变量,完成对数据的合法“签名”;数据接收方则利用对方的公钥来解密收到的“数字签名”。并将结果用于数据完整性检验,以确认签名的合法性。
  1 代码签名如何工作
  签名代码确保程序对目标用户无害,其背后存在复杂而严密的操作来保证签名的有效性。当处理可执行代码签名时存在代码的完整性和来源的有效性问题,为此需要确保代码没有被篡改。如需要确认没有人中途截取并替换发送端的代码,并确认文件的来源是其标识的来源人。
  1.1 保证脚本的完整性
  为了验证将要执行的代码确系出自原作者手中并没有任何增删,在发送代码给其他人之前可以用算法获取代码的消息摘要,计算机科学中已经提供了相应的函数用于计算数据流的校验和。一些流行的能获取消息摘要的算法包括MD5和SHA-1,这些函数有时称为“哈希函数”,它们会遍历所有数据并计算出完全不同于另外一端数据流的摘要。改变原始数据中的任何一位都将会完全改变校验和的值。获取代码后可以使用相同的算法获取消息摘要,如果两段消息摘要相同,那么脚本未被修改。
  哈希函数在设计上存在缺陷,恶意用户可以截取消息、修改脚本、重新获取并替换消息摘要。同样需要保证消息摘要未被篡改,可以加密消息摘要,但是存在传输密钥的问题。如果在传输的过程中包含密钥,则未起到加密消息摘要的作用。攻击者可以修改脚本并用密钥重新加密消息摘要后传输,此时不能使用带密钥或对称算法解决。需要使用非对称算法加密密钥,该算法采用一对密钥,其中一个用来加密数据,另外一个用来解密数据。加密密钥被称为“私钥”,从不传输;解密密钥或称为“公钥”,可以被自由地分发给任何人。脚本作者计算脚本的消息摘要并用自己的私钥加密。接收方可以使用公钥解密消息摘要并计算另外一个消息摘要,对比两个值是否相等即可知道代码是否被篡改过。
  1.2 保证原始脚本
  验证脚本完整性的方案看起来很完美,但是如果恶意用户在中途截取消息、修改该脚本、更新消息摘要,用其私钥加密消息摘要并用其公钥替换原有包含的公钥,则接收方将不会发现问题。解决方法是由中立的第三方来收藏所有人的公钥,这样即可保证某个邮件中加密消息摘要的私钥对应公钥的作者不是脚本作者。这里受信任的第三方的角色由中立的CA(Certification Authorities)来承担,现在流行最广的CA公司有VerSign和Thawte。
  CA发行的所有公钥/私钥对能够确认某个公钥确实属于某个个人或组织,当用户从其购买数字证书时本质上获取的是一个公钥/私钥对。获取私钥和包含公钥的证书文件,以及认证持有者的附加信息和过期时间等。数字证书能够分发给任何人,任何人可以验证自己是否属于正确的用户。
  脚本开发人员从CA处购买数字证书,计算出脚本的校验和,然后发送脚本、加密的校验和及其证书(其中包含其公钥)。收到信息后,接收方可以使用证书发放机构的公钥来验证脚本开发人员的数字签名是否真实。如果真实且计算出的消息摘要与用开发人员公钥解密的结果一致,则消息没有被篡改。在这个过程中,CA机构的私钥必须准确无误才能保证数字签名有效,攻击者没有它则无法分发假证书。通常情况下CA的私钥作为高级机密存在,攻击者根本无法获取,从而保证了数字签名的有效性。
  上述交换机制中密钥和证书的产生称为“公共密钥基础设施”(PKI),它广泛应用于在Internet中建立信任体系,以验证其他用户和实体。完整的PKI标准包括多种超约束力的公钥用户身份验证,如撤销机制、证书过期和证书泄露等。
  2 管理证书
  在现实生活中,数字证书的使用不仅限于信任的安全网站或者运行的签名程序,而且需要用户交换密钥跟踪证书。一旦信任一个软件发行商,则每次运行其软件时不再需要确认。所有信任的证书均保存在Windows证书存储区中,通过微软管理控制台工具(mmc)和证书管理单元很容易管理证书,在Windows Vista下运行mmc即可。如果使用其他版本的Windows,则启动管理控制台后可通过文件菜单中的添加或删除管理单元来实现。图1所示为“添加或删除管理单元”对话框。
  
  单击“添加”按钮,显示“证书管理单元”对话框,如图2所示。
  
  选择用户账户管理的证书,单击“完成”按钮。
  如果需要在服务账户或所有用户下运行签名脚本,则需要添加另一个证书管理单元实例。图3所示为在管理控制台中添加了当前用户和计算机两个管理单元。
  
  也可以使用PowerShell来访问证书,默认情况下证书提供程序注册了证书驱动器。可以如同访问文件系统那样来访问证书系统,如下代码列举当前用户中的所有证书: 从管理控制台获取的结果更为友好,如个人和信任根证书授权等。而PowerShell提供程序则用了简短名,如My和AuthRoot。
  3 创建自签名证书
  从CA获取一张证书需要花费较长的一段时间,而且并不便宜。使用代码签名工具和基础设施提供的手段可以很好地平衡安全性和实用性。这种方法即用户创建自签名证书并用其签名脚本,如同使用第三方CA签发的数字证书。唯一的区别是自签名证书建立在自己的信任体系上,而第三方CA证书建立在整个社会的信任体系上。自签名证书可以让每个人创建一张相同的证书,而不是人人保护自己的私钥。在大多数情况下这类有限的保护没有严重的问题,在单一网络中分发脚本并不会存在大的安全漏洞。正如所有任何安全并不是绝对的,而总是相对的。
  3.1 创建认证证书
  发行脚本签名证书之前需要创建CA认证证书,即根证书。通常情况下,第三方CA的根证书会被导人本地证书存储区,因此可以用来验证脚本签名。这里使用作为微软.NET 2.0框架SDK一部分且自由免费下载的Makecert.exe工具来创建根证书,如果计算机已经安装SDK,则makecert.exe可能已经包含在其路径中,可以直接使用程序名来调用;否则可以自己添加。使用以下参数来调用makecert.exe: 执行后显示如图4所示的“Create Private Key Password”对话框。
  
  在其中输入私钥密码,涉及处理私钥保存的文件均受密码保护,从而增加了一道安全屏障。单击“OK”按钮,显示“Enter Private Key Password”对话框,如图5所示。
  
  再次输入私钥密码,单击“OK”按钮,CA根证书会被自动添加到当前用户的证书存储区内。Windows会弹出警告信息提示用户,一旦信任这张证书,则自动信任所有由此签发的所有证书,如图6所示。
  
  单击“是”按钮,然后可在已导入证书的Trusted Root Certification Authorities(信任的根CA)目录中找到已导入的根证书,如图7所示。
  
  如果用户不再信任此证书,将其从该目录中删除即可。
  双击其中的证书显示“证书”对话框,如图8所示。
  
  其中显示证书在2040年1月1日之前一直有效。
  makecert.exe工具包含的参数如下。
  (1)-n:证书存储区内的证书名,可以是任何满足X.500标准的字符串,语法为CN=。
  (2)-a:指定签名算法,在上例中通过指定sha1选项使用SHA-1算法。也可以使用MD5算法,此算法主要用计算文件完整性校验和,语法为-a MD5。
  (3)-eku:指定增强型密钥使用对象标识符,上例中的1.3.6.1.5.5.7.3.3为标准化常数。为了让用户免于阅读X.500冗长的标准文档,不同的常数代表不同的用途。makecert.exe可以生成所有类型的证书,1.3.6.1.5.5.7.3.1将会生成用于服务器SSL通信的认证证书。
  (4)-r:标识自签名证书,并告诉makecert.exe不使用CA私钥来生成该证书。
  (5)-ss:指定特定的证书,将新生成的证书导入到目标区域内。在上例中使用Root是因为将证书作为根CA证书。
  (6)-sr:指定证书存储位置,可选项为CurrentUser和LocalMachine,分别将证书添加到当前用户和整个计算机。
  (7)-sv:指定私钥文件的存储的位置,makecert.exe自动创建这个文件夹并且在其中保存私钥文件。
  (8)ProPowerShell_CA.cer:指定包含证书的文件名,其中包含公钥和关于证书持有人的附加数据。
  3.2 发行代码签名证书
  创建证书后需要使用makecert.exe工具关联证书所有者的公钥和私钥,执行命令: 其中的选项说明如下。
  (1)-n:指定证书持有者名,因为这是作为脚本发布人的证书,所以在前面设置的是CN=Windows Powe