• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Tony Qu
我的软件工作室
博客园    首页    新随笔    联系   管理     

Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]

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>

版权声明:本文由作者Tony Qu原创, 未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
posted @ 2005-03-11 09:58  找事的狐狸  阅读(1643)  评论(1)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3