首页 文章

如何从pfx / cer创建snk?

提问于
浏览
24

微软似乎已经创建了一个认证丛林,这很难理解 .

  • Microsoft X.509证书(.cer)

  • 个人信息交流(.pfx)

  • 程序集签名密钥属性(.snk)

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

  • 虽然可以使用受密码保护的pfx对程序集进行签名,但它似乎没有强名称,除非使用snk签名 . 但是snk没有密码保护 . 哪一个更安全?由于我是项目中唯一的开发人员,我没有多开发人员安全环境问题,但仍想知道什么是最好的方法 .

非常感谢,

3 回答

  • 25

    这是@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文件进行了强烈的名称签名"buggy"在他的回答中提到了@punkcoder

    而且,如果您感兴趣,我会在Visual Studio的后期构建过程中添加以下内容,以将authenticode签名添加到项目输出中(无论如何都在“Release”项目配置中) .

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

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

    • .cer文件是X.509证书

    • .pfx文件使用基于密码的对称密钥加密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) 仅提取公钥! (例如,延迟签署集会)

  • 26

    要从pfx生成snk文件:

    sn -p keypair.pfx key.snk
    

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

相关问题