Microsoft Updater Application Block KeyValidator类设计

译者:Tony Qu

KeyValidator类提供一个基于对称密钥的验证器,该章节将介绍KeyValidator设计的以下几个方面:
问题描述
设计目标、权衡和问题
解决方案描述
具体实现

问题描述
一个通常使用的验证方法是使用对称密钥进行签名和验证数据。为了支持这项技术,必须实现一个基于对称密钥的验证器。

设计目标、权衡和问题
1. KeyValidator应该支持由.net的KeyedHashAlgorithm类支持的对称密钥。
2. 开发人员应该能够在应用程序升级器的配置文件中指定密钥,该密钥应该用base64字符串存储。如果没有密钥被指定,KeyValidator会抛出一个异常。

解决方案描述
KeyValidator类派生自IValidator接口,它使用.net的KeyedHashAlgorithm类基于一个对称密钥生成和验证签名。

具体实现
KeyValidator类由Microsoft.ApplicationBlocks.ApplicationUpdater.Validators命名空间实现。
实现KeyValidator需要考虑四个方面:
1. 密钥初始化
2. 签名
3. 验证
4. KeyValidator配置

密钥初始化
1. Init方法用于从应用程序升级器配置文件传递<validator>元素给KeyValidator类。该元素应该包含<key>子元素,该元素中以base64字符串存储密钥。<key>元素用于初始化验证密钥,该初始化过程代码在下面的代码片断中。
[VB.NET]

Sub Init()Sub Init (ByVal config As XmlNode) Implements IValidator.Init
  Dim keyNode As XmlNode = config.SelectSingleNode( "key" )
  _key = ExtractKeyFromNode (keyNode)
  If _key Is Nothing Then
    'Throw a cryptographic exception
  End If
End Sub

[C#]

void IValidator.Init( XmlNode config )
{                    
  XmlNode keyNode = config.SelectSingleNode( "key" );
  _key = ExtractKeyFromNode( keyNode );
  if ( null == _key )
  {
    // Throw a cryptographic exception
  }
}

2. Init方法使用一个ExtractKeyFromNode私有函数解析位于配置文件中的base64加密的字符串,并且返回一个byte数组。下面的代码展示了ExtractKeyFromNode函数。
[VB.NET]

Private Function ExtractKeyFromNode()Function ExtractKeyFromNode(ByVal keyNode As XmlNode) As Byte()
  Dim key As Byte() = Nothing
  If keyNode Is Nothing Then
     Return Nothing
  End If
  Try
    key = Convert.FromBase64String(keyNode.InnerText)
  Catch e As Exception
    'exception handling code
  End Try
  Return key
End Function

[C#]

private byte[] ExtractKeyFromNode( XmlNode keyNode )
{
  byte[] key = null;
  if ( null == keyNode )
  {
    return null;
  }
  try
  {
    key = Convert.FromBase64String( keyNode.InnerText );
  }
  catch( Exception e )
  {                        
    // exception handling code
  }
  return key;
}

签名
重载的Sign方法使用KeyedHashAlgorithm类生成hashed签名,下面的代码片断展示了这一过程:
[VB.NET]

Overloads Function Sign()Function Sign(ByVal filePath As String, ByVal key As String) As String _
    Implements IValidator.Sign 
  Dim outSignature As Byte() = Nothing
  Dim fs As FileStream = Nothing
  Try
    fs = New FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)
    Dim kha As KeyedHashAlgorithm = KeyedHashAlgorithm.Create()
    kha.Key = Convert.FromBase64String(key)
    outSignature = kha.ComputeHash(fs)
  Catch e As Exception
    ' exception handling code
  Finally
    If Not (fs Is Nothing) Then
      fs.Close()
     End If
   End Try
   Return Convert.ToBase64String(outSignature)
End Function
 
Overloads Function Sign()Function Sign(ByVal xml As XmlNode, ByVal key As String) As String _
    Implements IValidator.Sign
  Dim outSignature As Byte() = Nothing
  Dim xmlNodeByte As Byte() = Nothing
  xmlNodeByte = Encoding.Unicode.GetBytes(Xml.InnerXml)
  Try
    Dim kha As KeyedHashAlgorithm = KeyedHashAlgorithm.Create()
    kha.Key = Convert.FromBase64String(key)
    outSignature = kha.ComputeHash(xmlNodeByte)
  Catch e As Exception
    'exception handling code
  End Try
  Return Convert.ToBase64String(outSignature)
End Function

[C#]

string IValidator.Sign( string filePath, string key )
{
  byte[] outSignature = null;
  FileStream fs = null;
  try
  {
    fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
    KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create();
    kha.Key = Convert.FromBase64String( key );
    outSignature = kha.ComputeHash( fs );       
  }
  catch( Exception e )
  {
    // exception handling code
  }
  finally
    if ( null != fs )
    {
      fs.Close();
    }
  }
  return Convert.ToBase64String( outSignature );
}

string IValidator.Sign( XmlNode xml, string key )
{
  byte[] outSignature = null;
  byte[] xmlNodeByte = null;
  xmlNodeByte = Encoding.Unicode.GetBytes( xml.InnerXml );
  try
  {
    KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create();
    kha.Key = Convert.FromBase64String( key );
    outSignature = kha.ComputeHash( xmlNodeByte );
  }
  catch( Exception e )
  {
    // exception handling code
  }
  return Convert.ToBase64String( outSignature );
}

验证
Validate方法使用相同的KeyedHashAlgorithm验证签名和密钥,该密钥用于生成签名。Validate方法在下面的代码片断中实现:
[VB.NET]

Overloads Function Validate()Function Validate(ByVal filePath As String, ByVal signature As String) _
    As Boolean Implements IValidator.Validate

  Dim inSignature As Byte() = Nothing
  Dim outSignature As Byte() = Nothing
  inSignature = Convert.FromBase64String(signature)
  Dim fs As New FileStream(filePath, FileMode.Open)
  Try
    Dim kha As KeyedHashAlgorithm = KeyedHashAlgorithm.Create()
    kha.Key = _key
    outSignature = kha.ComputeHash(fs)
  Finally
    fs.Close()
  End Try
  Return compareKeys(outSignature, inSignature)
End Function

Overloads Function Validate()Function Validate(ByVal xml As XmlNode, ByVal signature As String) _
    As Boolean Implements IValidator.Validate

   Dim inSignature As Byte() = Nothing
  Dim outSignature As Byte() = Nothing
  Dim xmlNodeByte As Byte() = Nothing
  xmlNodeByte = Encoding.Unicode.GetBytes(Xml.InnerXml)
  inSignature = Convert.FromBase64String(signature)
  Dim kha As KeyedHashAlgorithm = KeyedHashAlgorithm.Create()
  kha.Key = _key
  outSignature = kha.ComputeHash(xmlNodeByte)
  Return compareKeys(outSignature, inSignature)
End Function

[C#]

bool IValidator.Validate( string filePath, string signature )
{
  byte[] inSignature = null;
  byte[] outSignature = null;
  inSignature = Convert.FromBase64String( signature );
  using ( FileStream fs = new FileStream( filePath, FileMode.Open ) )
  {
    KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create();
    kha.Key = _key;
    outSignature = kha.ComputeHash( fs );
  }
  return compareKeys( outSignature, inSignature );
}   

bool IValidator.Validate( XmlNode xml, string signature )
{
  byte[] inSignature = null;
  byte[] outSignature = null;
  byte[] xmlNodeByte = null;
  xmlNodeByte = Encoding.Unicode.GetBytes( xml.InnerXml );
  inSignature = Convert.FromBase64String( signature );               
  KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create();
  kha.Key = _key;
  outSignature = kha.ComputeHash( xmlNodeByte );
  return compareKeys( outSignature, inSignature );
}

这两个Validate的重载方法使用一个私有的compareKeys来确认签名匹配。compareKeys函数在下面的代码中实现:
[VB.NET]

Private Function compareKeys()Function compareKeys(ByVal firstKey() As Byte, ByVal secondKey() As Byte) _
    As Boolean
  If firstKey.Length <> secondKey.Length Then
    Return False
  End If
  Dim i As Integer
  For i = 0 To firstKey.Length - 1
    If firstKey(i) <> secondKey(i) Then
      Return False
    End If
  Next i
  Return True
End Function

[C#]

private bool compareKeys( byte[] firstKey, byte[] secondKey )
{
  if( firstKey.Length != secondKey.Length ) return false;
  for( int i = 0 ; i < firstKey.Length; i++ )
  {
    if( firstKey[ i ] != secondKey[ i ] ) return false;
  }
  return true;
}

KeyValidator配置
为了使用KeyValidator,你必须在应用程序升级器配置文件中包含一个<validator>元素,指定KeyValidator集合和类型的全名,以及你要使用的base64加密密钥。一个<validator>配置元素的例子如下所示:

<validator type="Microsoft.ApplicationBlocks.ApplicationUpdater.Validators.KeyValidator" assembly="Microsoft.ApplicationBlocks.ApplicationUpdater,Version=1.0.0.0, Culture=neutral,PublicKeyToken=null">
<key>ACQAAASAAACUAAAABgIAAAAkAABS[etc.]</key>   
</validator>

Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]相关推荐

  1. Microsoft Updater Application Block 1.5.3 服务器端manifest文件设计 [翻译]

    Microsoft Updater Application Block 服务器端manifest文件设计 译者:Tony Qu Manfest文件用于列出一次升级所需要的所有的文件,它与验证签名相关联 ...

  2. Microsoft Updater Application Block 1.2.1 核心设计(core design) [翻译]

    Microsoft Updater Application Block 核心设计(core design) 译者:Tony Qu Updater Application Block由一个核心应用程序升 ...

  3. Updater Application Block for .NET

    Introduction Do you need to deploy updates to .NET applications across multiple desktops? Would you ...

  4. Updater Application Block v1.0 翻译文档目录

    为方便大家阅读有关Updater Application Block v1.0 的翻译文章,在本文中列出最近翻译的相关文章目录. Updater Application Block v1.0 介绍 U ...

  5. Updater Application Block for .net 2.0 发布了

    Updater Application Block for .net 2.0 终于发布了,做smart client的兄弟来下载吧! 另外 Smart Client Application Block ...

  6. 近期工作:Updater Application Block (UAB)继续

    阅读: 1.Using Updater Block   by Praveen Nayak http://www.codeproject.com/csharp/VanillaUpdaterBlock.a ...

  7. 黄聪:Microsoft Enterprise Library 5.0 系列教程(九) Policy Injection Application Block

    代理对象(Proxy Object)会通过Handler链定位到真实对象(Real Object),而Policy则被注入到代理对象和真实对象中.整个流程如图: 我个人对Policy Injectio ...

  8. 黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (高级)

    原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (高级) 本章介绍的是企业库加密应用程序模块 ...

  9. 黄聪:Microsoft Enterprise Library 5.0 系列教程(四) Logging Application Block

    企业库日志应用程序模块工作原理图:   从上图我们可以看清楚企业库日志应用程序模块的工作原理,其中LogFilter,Trace Source,Trace Listener,Log Formatter ...

最新文章

  1. dbartisan mysql_Sybase数据库安全
  2. IIC原理及简单流程
  3. python 定时器_按键精灵定时器介绍和使用,不会的小伙伴速速看看精辟
  4. php monolith,单体架构(Monolith)与微服务架构(MicroService)
  5. sae java 开发环境_新浪开放平台 sae环境 java主机使用感受
  6. LR运行负载测试场景-笔记
  7. WAMP(windows+apache+mysql+php)
  8. 03 - 雷达的基本组成
  9. 剧本创作时的标准格式,让你的剧本轻松得到制片公司青睐
  10. 有多少旅游企业入驻了抖音平台?有多少抖音用户喜欢看旅游视频?
  11. Justinmind,为移动设计而生
  12. 【转】ORA-28040: 没有匹配的验证协议
  13. java生成自己的Doc文档
  14. Word: 是否将更改保存到WordCmds.dot中?
  15. 对称矩阵到三对角矩阵的Lanczos推导(python,数值积分)
  16. 浅析B树、B+树插入删除操作(附代码实现)
  17. 屏幕录像软件使用心得
  18. 利用python处理Excel表格中的销售数据
  19. python 警告:simplify chained comparison
  20. 计算机考试题画图板,9月全国计算机一级Photoshop考试试题操作题

热门文章

  1. php解析定时任务格式,php 实现定时任务简单实现
  2. linux查看usb设备名称,Linux系统下查看USB设备名及使用USB设备
  3. 苹果6重置系统后无服务器,iphone6总是无服务,恢复初始设置就好了,然后一两天又不行了,怎么处理...
  4. 通过build.xml在Eclipse中导入工程
  5. 支持access的php框架,NginX友好的PHP框架
  6. matlab 离散点求导_Matlab的离散点曲线导数曲率数值模拟方法
  7. flink读取不到文件_flink批处理从0到1
  8. python删除文件代码_python2.7删除文件夹和删除文件代码实例
  9. tomcat ajp协议安全限制绕过漏洞_Apache tomcat 文件包含漏洞复现(CVE20201938)
  10. 评分卡模型开发(四)--定量指标筛选