2012-11-30 56 views
2

如何計算VS_KEY容器名稱?他們通常是這樣的:VS_KEY_71E582524B5DDE29。計算VS_KEY容器名稱

我假設它是基於計算機的名字,但如果我們有一個雲服務運行,每次隨機改變計算機名稱實例重新啓動?

我們需要在實例上升,所以我們知道什麼容器來存儲私鑰到如此構建工具和所有的工作,因爲他們應該有容器名稱。我們需要自動設置容器名稱。

所以基本上我們需要找出一種方法來每次計算機重新啓動時生成正確的容器名稱。任何提示或幫助?

回答

7

我們在嘗試自動在集成服務器上註冊密鑰時加入了此問題。必須運行Visual Studio或MSBuild來提取VS_KEY是不可接受的。然後通過調查最大冗長的MSBuild日誌,我發現了以下內容。

該密鑰是通過Microsoft.Build.Tasks.v4.0.dll(存在於GAC中)生成的。在這個DLL中有一個名爲「ResolveKeySource」的類。通過使用ILSpy或Reflector查看代碼,您將看到一個調用ResolveAssemblyKey的Execute方法。這種方法是VS_KEY_xxxxxx之謎的核心。

的VS_KEY_xxxxx值由散列與Environment.UserDomainName和Environment.UserName密鑰的內容而生成。

第一個解決方案:您創建一個ResolveKeySource實例並調用相應的方法。由於您沒有提供密碼和其他信息,因此會引發異常,其消息包含強大的VS_KEY事件。

var key = new ResolveKeySource(); 
key.KeyFile = path_to_key_file; 
try { 
    key.Execute(); 
} catch (Exception e) { 
    var match = Regex.Match(e.Message, "VS_KEY_[A-F0-9]+"); 
    if (match.Success) { 
     return match.Value; 
    } 
} 

解決方法二:搶到即生成此哈希碼的代碼,並用它來直接獲得無異常值。這或多或少是DLL的摘錄。

public static string GetLocalUserKeyContainerByGeneration(string keyFile) { 

     string localName = Environment.UserDomainName + "\\" + Environment.UserName; 

     FileStream keyFileStream = null; 

     try { 
      keyFileStream = File.OpenRead(keyFile); 

      int num = (int)keyFileStream.Length; 
      byte[] array = new byte[num]; 

      keyFileStream.Read(array, 0, num); 

      ulong hash1 = HashFromBlob(array); 
      byte[] bytes = Encoding.Unicode.GetBytes(localName.ToLower(CultureInfo.InvariantCulture)); 

      return "VS_KEY_" + (hash1^HashFromBlob(bytes)).ToString("X016", CultureInfo.InvariantCulture); 
     } 
     finally { 
      if (keyFileStream != null) { 
       keyFileStream.Close(); 
      } 
     } 
    } 

    private static ulong HashFromBlob(byte[] data) { 

     uint num = 17339221u; 
     uint num2 = 19619429u; 
     uint num3 = 10803503u; 

     for (int i = 0; i < data.Length; i++) { 
      byte b = data[i]; 
      uint num4 = (uint)b^num3; 
      num3 *= 10803503u; 
      num += (num4^num2) * 15816943u + 17368321u; 
      num2 ^= ((num4 + num) * 14984549u^11746499u); 
     } 

     ulong num5 = (ulong)num; 
     num5 <<= 32; 

     return num5 | (ulong)num2; 
    } 
+0

添加答案,因爲評論是有限的 – NGaida

1

此答案與@ kdrapel's一起使用,但我無法將其置於評論中。我不得不對它進行一些破解,以找出如何在內聯任務中實際使用它,所以我想我會分享。

<?xml version="1.0" encoding="utf-8" ?> 
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Test" ToolsVersion="4.0" > 

    <Target Name="Test"> 
    <CalcKey InputKey="c:\path\to\your\key.pfx"> 
     <Output PropertyName="VSKEY" TaskParameter="VSKEY"/> 
    </CalcKey> 
    <Message Text="VSKey = $(VSKEY)"/> 
    </Target> 

    <UsingTask 
     TaskName="CalcKey" 
     TaskFactory="CodeTaskFactory" 
     AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" > 
    <ParameterGroup> 
     <InputKey ParameterType="System.String" Required="true"/> 
     <VSKEY ParameterType="System.String" Output="true"/> 
    </ParameterGroup> 
    <Task> 
     <Reference Include="$(MSBuildBinPath)\Microsoft.Build.Framework.dll"/> 
     <Reference Include="$(MSBuildBinPath)\Microsoft.Build.Utilities.v12.0.dll"/> 
     <Reference Include="$(MSBuildBinPath)\Microsoft.Build.Tasks.v12.0.dll"/> 
     <Using Namespace="System.Text.RegularExpressions"/> 
     <Using Namespace="Microsoft.Build.Tasks"/> 
     <Code Type="Fragment" Language="cs"> 
     <![CDATA[ 
      var key = new ResolveKeySource(); 
      key.KeyFile = InputKey; 
      try 
      { 
       key.Execute(); 
      } 
      catch (Exception e) 
      { 
       var match = Regex.Match(e.Message, "VS_KEY_[A-F0-9]+"); 
       if (match.Success) 
       { 
        this.VSKEY = match.Value; 
       } 
      } 
]]> 
     </Code> 
    </Task> 
    </UsingTask> 

</Project>