如何计算VS_KEY容器名称?它们通常是这样的:VS_KEY_71E582524B5DDE29。
我假设它基于计算机名称但是如果我们运行的云服务会在每次实例重新启动时随机更改计算机名称会怎样?
我们需要在实例启动时拥有容器名称,以便我们知道将私钥存储到哪个容器中,因此构建工具和所有工作都应该如此。我们需要自动设置容器名称。
所以基本上我们需要找到一种方法来在每次计算机重新启动时生成正确的容器名称。任何提示或帮助?
答案 0 :(得分: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;
}
答案 1 :(得分:1)
这个答案与@ 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>