如何从 pfx / cer 创建 snk?

发布于 2024-12-16 00:43:02 字数 368 浏览 3 评论 0原文

微软似乎创造了一个难以理解的认证丛林。

  • Microsoft X.509 证书 (.cer)
  • 个人信息交换 (.pfx)
  • 程序集签名密钥属性 (.snk)

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

    2. 虽然可以使用受密码保护的 pfx 对程序集进行签名,但它 不过名字好像不太强,除非是和snk签约的 反而。但snk没有密码保护。哪一种更安全 使用?由于我是项目中唯一的开发人员,因此我没有 多开发人员安全环境问题,但仍然想 知道什么是最好的方法。

非常感谢,

Microsoft seems to have created a certification jungle, that is hard to understand.

  • Microsoft X.509 certificate (.cer)
  • Personal Information Exchange (.pfx)
  • Assembly Signature Key Attribute (.snk)

    1. Would it be advisable to create an snk file based on pfx or cer?
      (Not sure if its even possible, and if its possible how is it done?)

    2. While an assembly can be signed with a password protected pfx, it
      doesn't seem to be strong named though, unless it is signed with snk
      instead. But the snk has no password protection. Which one is safer
      to use? As I am the only developer in my project, I don't have the
      multi-developer saftey environment issue, but still would like to
      know what is best approach.

Many Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧情别恋 2024-12-23 00:43:02

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

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

无论您使用 .pfx-文件还是 签署程序集都没有关系.snk-文件,无论哪种方式它都会得到强命名。
将 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) 仅提取公钥! (例如,用于程序集的延迟签名)

A little clarification about your mentioned file types:

  • .cer-files are X.509 Certificates
  • .pfx-files are encrypted X.509 Certificates using a password-based symmetric key, also see PKCS #12 (Wikipedia)
  • .snk-files only contain the RSA key (public/private or public only)

It doesn't matter if you sign an assembly using .pfx-files or .snk-files, it will get strong named either way.
Storing the RSA key as a encrypted certificate (.pfx) is of course more secure than storing just the unencrypted key (.snk).

You can easily extract the key from those files in code using class System.Security.Cryptography.X509Certificates.X509Certificate2.

To extract key from .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);
}

Use privateKey.ExportCspBlob(false) to extract public key only! (e.g. for delay-signing of assemblies)

你不是我要的菜∠ 2024-12-23 00:43:02

仅使用 pfx 中的公钥生成 snk 文件:

sn -p keypair.pfx key.snk

我一直热衷于使用 snk 文件而不是 .pfx 文件,它们看起来问题更少。

To generate a snk file with solely the public key from a pfx:

sn -p keypair.pfx key.snk

I have always been a fan of using snk files over .pfx files they just seem less buggy.

夏末染殇 2024-12-23 00:43:02

这是 @Sir Kill A Lot 在他的 答案,但转换为 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文件)的相同密钥进行强名称签名的过程。这不是一个要求,但对我来说,它们应该是相同的似乎是有意义的,并且它满足了我的强迫症倾向。

(我使用 snk 文件而不是原始 pfx,因为我有过使用 pfx 文件进行强名称签名的“错误”经验 @punkcoder 在他的回答中提到)

而且,如果您感兴趣,我在 Visual Studio 中的构建后过程中提供了类似以下内容,以将authenticode签名添加到项目输出(在无论如何“发布”项目配置)。

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

Here's the same method provided by @Sir Kill A Lot in his answer, but converted to a PowerShell script (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);

Just run that script providing the pfx file path and password and it will make an snk file in the same directory as the pfx file (with the same name other than the extension).

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

Or, if your pfx doesn't have a password (shame, shame):

powershell.exe -File pfx2snk.ps1 cert.pfx

And, if you're unfortunate enough to be working in an environment where they don't allow PowerShell scripts to execute (ie. interactive PowerShell sessions only), then you can execute this ugly one liner from a standard cmd.exe command line (replacing file paths and pfx password as needed).

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));"

I actually use that one-liner as a standard part of my Visual Studio pre-build process to automate the process of using the same keys from our authenticode signature certs (pfx file) for strong name signing. That's not a requirement, but it just seems to make sense to me that they should be the same and it feeds my OCD tendencies.

(I use an snk file rather than the original pfx because I've had the "buggy" experience using pfx files for strong name signing that @punkcoder mentioned in his answer)

And, if you're interested, I have something like the following as a part of my post-build process in Visual Studio to add the authenticode signature to the project output (in "Release" project configurations anyway).

powershell.exe -Command "Set-AuthenticodeSignature -FilePath '$(TargetPath)' -Certificate '$(SolutionDir)MyCert.pfx' -TimestampServer http://timestamp.verisign.com/scripts/timstamp.dll -HashAlgorithm sha256;"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文