如何从pfx / cer创建snk?

时间:2011-11-17 21:00:11

标签: c# .net x509certificate pfx snk

微软似乎已经创建了一个很难理解的认证丛林。

  • Microsoft X.509证书(.cer)
  • 个人信息交流(.pfx)
  • 装配体签名密钥属性(.snk)

    1. 建议基于pfx或cer创建snk文件吗? (不确定它是否可能,如果它可能如何完成?)

    2. 虽然可以使用受密码保护的pfx对程序集进行签名 虽然看起来并不强大,除非它是用snk签名的 代替。但是snk没有密码保护。哪一个更安全 用吗?因为我是我项目中唯一的开发人员,所以我没有 多开发人员安全环境问题,但仍然愿意 知道什么是最好的方法。

非常感谢,

3 个答案:

答案 0 :(得分:28)

关于您提到的文件类型的一点说明:

  • .cer - 文件是X.509证书
  • .pfx -files是使用基于密码的对称密钥加密的X.509证书,另请参阅PKCS #12 (Wikipedia)
  • .snk - 文件只包含RSA密钥(公共/私人或公开)

如果使用 .pfx -files或 .snk -files对程序集进行签名并不重要,它将以任一方式命名。 将RSA密钥存储为加密证书( .pfx )当然比仅存储未加密的密钥( .snk )更安全。

您可以使用类System.Security.Cryptography.X509Certificates.X509Certificate2轻松地从代码中的这些文件中提取密钥。

.pfx 中提取密钥:

/// <summary>
/// Converts .pfx file to .snk file.
/// </summary>
/// <param name="pfxData">.pfx file data.</param>
/// <param name="pfxPassword">.pfx file password.</param>
/// <returns>.snk file data.</returns>
public static byte[] Pfx2Snk(byte[] pfxData, string pfxPassword)
{
    // load .pfx
    var cert = new X509Certificate2(pfxData, pfxPassword, X509KeyStorageFlags.Exportable);

    // create .snk
    var privateKey = (RSACryptoServiceProvider)cert.PrivateKey;
    return privateKey.ExportCspBlob(true);
}

使用privateKey.ExportCspBlob(false)仅提取公钥! (例如,延迟签署集会)

答案 1 :(得分:27)

从pfx生成snk文件:

sn -p keypair.pfx key.snk

我一直都喜欢在.pfx文件上使用snk文件,他们看起来不那么多了。

答案 2 :(得分:5)

这是@Sir Kill A Lotanswer中提供的相同方法,但转换为PowerShell脚本( pfx2snk.ps1 )。

Param(
    [Parameter(Mandatory=$True,Position=1)]
    [string] $pfxFilePath,
    [string] $pfxPassword
)

# The path to the snk file we're creating
[string] $snkFilePath = [IO.Path]::GetFileNameWithoutExtension($pfxFilePath) + ".snk";

# Read in the bytes of the pfx file
[byte[]] $pfxBytes = Get-Content $pfxFilePath -Encoding Byte;

# Get a cert object from the pfx bytes with the private key marked as exportable
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2(
    $pfxBytes,
    $pfxPassword,
    [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable);

# Export a CSP blob from the cert (which is the same format as an SNK file)
[byte[]] $snkBytes = ([Security.Cryptography.RSACryptoServiceProvider]$cert.PrivateKey).ExportCspBlob($true);

# Write the CSP blob/SNK bytes to the snk file
[IO.File]::WriteAllBytes($snkFilePath, $snkBytes);

只需运行提供pfx文件路径和密码的脚本,它就会在与pfx文件相同的目录中创建一个snk文件(扩展名以外的名称)。

powershell.exe -File pfx2snk.ps1 -pfxFilePath cert.pfx -pfxPassword "pfx password"

或者,如果你的pfx没有密码(羞耻,羞耻):

powershell.exe -File pfx2snk.ps1 cert.pfx

而且,如果您不幸在一个他们不允许执行PowerShell脚本的环境中工作(例如,仅限交互式PowerShell会话),那么您可以从标准cmd.exe执行这个丑陋的内容命令行(根据需要替换文件路径和pfx密码)。

powershell.exe -Command "[IO.File]::WriteAllBytes('SnkFilePath.snk', ([Security.Cryptography.RSACryptoServiceProvider](New-Object System.Security.Cryptography.X509Certificates.X509Certificate2((Get-Content 'PfxFilePath.pfx' -Encoding Byte), 'PfxPassword', [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)).PrivateKey).ExportCspBlob($true));"

我实际上使用该单行作为我的Visual Studio预构建过程的标准部分,以自动化使用来自我们的authenticode签名证书(pfx文件)中的相同密钥以进行强名称签名的过程。这不是一个要求,但它似乎对我有意义,它们应该是相同的,并且它会影响我的OCD倾向。

(我使用的是snk文件,而不是原始的pfx,因为我有使用pfx文件进行强烈的名称签名的“错误”体验@punkcoder在他的回答中提到了 < / p>

并且,如果您感兴趣,我会在Visual Studio中将后续构建过程中的以下内容添加到项目输出中(在“发布”项目配置中)。

powershell.exe -Command "Set-AuthenticodeSignature -FilePath '$(TargetPath)' -Certificate '$(SolutionDir)MyCert.pfx' -TimestampServer http://timestamp.verisign.com/scripts/timstamp.dll -HashAlgorithm sha256;"
相关问题