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]
 IValidator.Init
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  Dim keyNode As XmlNode = config.SelectSingleNode( "key" )
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  _key 
= ExtractKeyFromNode (keyNode)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
If _key Is Nothing Then
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
'Throw a cryptographic exception
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
  End If
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
End Sub
[C#]
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]void IValidator.Init( XmlNode config )
{                    
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  XmlNode keyNode 
= config.SelectSingleNode( "key" );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  _key 
= ExtractKeyFromNode( keyNode );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
if ( null == _key )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
// Throw a cryptographic exception
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
  }
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]}
2. Init方法使用一个ExtractKeyFromNode私有函数解析位于配置文件中的base64加密的字符串,并且返回一个byte数组。下面的代码展示了ExtractKeyFromNode函数。
[VB.NET]
()
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  Dim key As Byte() = Nothing
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
If keyNode Is Nothing Then
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]     
Return Nothing
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
End If
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Try
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    key 
= Convert.FromBase64String(keyNode.InnerText)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Catch e As Exception
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
'exception handling code
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
  End Try
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Return key
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
End Function
[C#]
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]private byte[] ExtractKeyFromNode( XmlNode keyNode )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
byte[] key = null;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
if ( null == keyNode )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
return null;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  }

Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
try
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    key 
= Convert.FromBase64String( keyNode.InnerText );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  }

Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
catch( Exception e )
{                        
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
// exception handling code
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
  }
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
return key;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]}

签名
重载的Sign方法使用KeyedHashAlgorithm类生成hashed签名,下面的代码片断展示了这一过程:
[VB.NET]
 _
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    Implements IValidator.Sign 
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Dim outSignature As Byte() = Nothing
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Dim fs As FileStream = Nothing
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Try
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    fs 
= New FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
Dim kha As KeyedHashAlgorithm = KeyedHashAlgorithm.Create()
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    kha.Key 
= Convert.FromBase64String(key)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    outSignature 
= kha.ComputeHash(fs)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Catch e As Exception
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
' exception handling code
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
  Finally
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
If Not (fs Is NothingThen
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]      fs.Close()
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]     
End If
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]   
End Try
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]   
Return Convert.ToBase64String(outSignature)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
End Function
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译] 
 _
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
Implements IValidator.Sign
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Dim outSignature As Byte() = Nothing
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Dim xmlNodeByte As Byte() = Nothing
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  xmlNodeByte 
= Encoding.Unicode.GetBytes(Xml.InnerXml)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Try
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
Dim kha As KeyedHashAlgorithm = KeyedHashAlgorithm.Create()
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    kha.Key 
= Convert.FromBase64String(key)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    outSignature 
= kha.ComputeHash(xmlNodeByte)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Catch e As Exception
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
'exception handling code
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
  End Try
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Return Convert.ToBase64String(outSignature)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
End Function
[C#]
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]string IValidator.Sign( string filePath, string key )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
byte[] outSignature = null;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  FileStream fs 
= null;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
try
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    fs 
= new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    KeyedHashAlgorithm kha 
= KeyedHashAlgorithm.Create();
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    kha.Key 
= Convert.FromBase64String( key );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    outSignature 
= kha.ComputeHash( fs );       
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  }

Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
catch( Exception e )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
// exception handling code
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
  }
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
finally
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
if ( null != fs )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]      fs.Close();
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    }

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

Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
return Convert.ToBase64String( outSignature );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]}
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
string IValidator.Sign( XmlNode xml, string key )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
byte[] outSignature = null;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
byte[] xmlNodeByte = null;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  xmlNodeByte 
= Encoding.Unicode.GetBytes( xml.InnerXml );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
try
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    KeyedHashAlgorithm kha 
= KeyedHashAlgorithm.Create();
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    kha.Key 
= Convert.FromBase64String( key );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    outSignature 
= kha.ComputeHash( xmlNodeByte );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  }

Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
catch( Exception e )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
// exception handling code
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
  }
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
return Convert.ToBase64String( outSignature );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]}

验证
Validate方法使用相同的KeyedHashAlgorithm验证签名和密钥,该密钥用于生成签名。Validate方法在下面的代码片断中实现:
[VB.NET]
) _
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    As Boolean Implements IValidator.Validate
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Dim inSignature As Byte() = Nothing
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Dim outSignature As Byte() = Nothing
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  inSignature 
= Convert.FromBase64String(signature)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Dim fs As New FileStream(filePath, FileMode.Open)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Try
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
Dim kha As KeyedHashAlgorithm = KeyedHashAlgorithm.Create()
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    kha.Key 
= _key
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    outSignature 
= kha.ComputeHash(fs)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Finally
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    fs.Close()
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
End Try
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Return compareKeys(outSignature, inSignature)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
End Function
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
) _
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
As Boolean Implements IValidator.Validate
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]   
Dim inSignature As Byte() = Nothing
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Dim outSignature As Byte() = Nothing
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Dim xmlNodeByte As Byte() = Nothing
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  xmlNodeByte 
= Encoding.Unicode.GetBytes(Xml.InnerXml)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  inSignature 
= Convert.FromBase64String(signature)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Dim kha As KeyedHashAlgorithm = KeyedHashAlgorithm.Create()
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  kha.Key 
= _key
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  outSignature 
= kha.ComputeHash(xmlNodeByte)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Return compareKeys(outSignature, inSignature)
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
End Function
[C#]
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]bool IValidator.Validate( string filePath, string signature )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
byte[] inSignature = null;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
byte[] outSignature = null;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  inSignature 
= Convert.FromBase64String( signature );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
using ( FileStream fs = new FileStream( filePath, FileMode.Open ) )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    KeyedHashAlgorithm kha 
= KeyedHashAlgorithm.Create();
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    kha.Key 
= _key;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    outSignature 
= kha.ComputeHash( fs );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  }

Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
return compareKeys( outSignature, inSignature );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]}
   
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
bool IValidator.Validate( XmlNode xml, string signature )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
byte[] inSignature = null;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
byte[] outSignature = null;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
byte[] xmlNodeByte = null;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  xmlNodeByte 
= Encoding.Unicode.GetBytes( xml.InnerXml );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  inSignature 
= Convert.FromBase64String( signature );               
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  KeyedHashAlgorithm kha 
= KeyedHashAlgorithm.Create();
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  kha.Key 
= _key;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  outSignature 
= kha.ComputeHash( xmlNodeByte );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
return compareKeys( outSignature, inSignature );
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]}
这两个Validate的重载方法使用一个私有的compareKeys来确认签名匹配。compareKeys函数在下面的代码中实现:
[VB.NET]
) _
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    As Boolean
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
If firstKey.Length <> secondKey.Length Then
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
Return False
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
End If
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Dim i As Integer
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
For i = 0 To firstKey.Length - 1
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
If firstKey(i) <> secondKey(i) Then
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]      
Return False
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
End If
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Next i
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
Return True
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
End Function
[C#]
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]private bool compareKeys( byte[] firstKey, byte[] secondKey )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
if( firstKey.Length != secondKey.Length ) return false;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
forint i = 0 ; i < firstKey.Length; i++ )
{
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]    
if( firstKey[ i ] != secondKey[ i ] ) return false;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  }

Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]  
return true;
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]}

KeyValidator配置
为了使用KeyValidator,你必须在应用程序升级器配置文件中包含一个<validator>元素,指定KeyValidator集合和类型的全名,以及你要使用的base64加密密钥。一个<validator>配置元素的例子如下所示:
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]<validator type="Microsoft.ApplicationBlocks.ApplicationUpdater.Validators.KeyValidator" assembly="Microsoft.ApplicationBlocks.ApplicationUpdater,Version=1.0.0.0, Culture=neutral,PublicKeyToken=null">
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
<key>ACQAAASAAACUAAAABgIAAAAkAABS[etc.]</key>   
Microsoft Updater Application Block 1.4.3 KeyValidator类设计 [翻译]
</validator>

相关文章:

  • 2021-09-16
  • 2022-02-01
  • 2022-12-23
  • 2021-09-12
  • 2021-09-15
  • 2021-10-26
  • 2021-06-16
  • 2021-05-20
猜你喜欢
  • 2021-10-05
  • 2021-10-26
  • 2021-06-15
  • 2022-03-10
  • 2021-09-06
  • 2021-10-29
  • 2022-01-15
相关资源
相似解决方案