【问题标题】:Calculating VS_KEY container name计算 VS_KEY 容器名称
【发布时间】:2012-11-30 07:18:07
【问题描述】:

如何计算 VS_KEY 容器名称?它们通常是这样的:VS_KEY_71E582524B5DDE29。

我假设它基于计算机名称,但如果我们运行的云服务会在每次实例重新启动时随机更改计算机名称?

当实例启动时,我们需要知道容器名称,这样我们就知道将我们的私钥存储到哪个容器中,这样构建工具就可以正常工作了。我们需要自动设置容器名称。

所以基本上我们需要想办法在每次计算机重新启动时生成正确的容器名称。有什么提示或帮助吗?

【问题讨论】:

    标签: c# visual-studio-2010 msbuild private-key


    【解决方案1】:

    我们在尝试在集成服务器上自动注册密钥时遇到了这个问题。不得不运行 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;
       }
    }
    

    第二种解决方案:抓取产生这个hashcode的代码,用它直接获取值,没有异常。这或多或少是从 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;
        }
    

    【讨论】:

    • 添加答案作为评论是有限的
    【解决方案2】:

    此答案与@kdrapel 的答案一致,但我无法将其放在评论中。为了弄清楚如何在内联任务中实际使用它,我不得不对其进行破解,所以我想我会分享。

    <?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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多