Calculating VS_KEY container name

放肆的年华 提交于 2019-12-04 14:35:18

问题


How does one calculate VS_KEY container name? They are generally something like this: VS_KEY_71E582524B5DDE29.

I'm assuming it's based on computer name but what if we have a cloud service running that changes the computer name randomly every time the instance restarts?

We need to have the container name when the instance goes up so we know what container to store our private keys into so build tools and all work as they should. We need to automatically set the container name.

So basically we need to figure out a way to generate correct container name every time the computer reboots. Any tips or help?


回答1:


We stepped upon this question while trying to automatically register the key on an integration server. Having to run Visual Studio or MSBuild to extract the VS_KEY was unacceptable. Then by investigating the logs of MSBuild with the maximal verbosity, I came upon the following.

This key is generated via Microsoft.Build.Tasks.v4.0.dll (present in GAC). There's a class called "ResolveKeySource" within this DLL. By looking at the code with ILSpy or Reflector, you will see an Execute method calling ResolveAssemblyKey. This method is the heart of the VS_KEY_xxxxxx mystery.

The VS_KEY_xxxxx value is generated by hashing the content of the key with Environment.UserDomainName and Environment.UserName.

First solution: you create an ResolveKeySource instance and call the appropriate method. As you don't provide a password and other information, it will raise an exception whose message contains the mighty VS_KEY thing.

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;
   }
}

Second solution: grab the code that is generating this hashcode and use it to directly get the value without exceptions. This is more or less an extract from the 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:


This answer goes along with @kdrapel's, but I couldn't put it in a comment. I had to hack it for a bit to figure out how to actually use it in an inline task, so I figured I'd share.

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


来源:https://stackoverflow.com/questions/13640650/calculating-vs-key-container-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!