Как создать снк из pfx / cer? - PullRequest
       82

Как создать снк из pfx / cer?

29 голосов
/ 18 ноября 2011

Microsoft, похоже, создала сертификационные джунгли, которые трудно понять.

  • Сертификат Microsoft X.509 (.cer)
  • Обмен личной информацией (.pfx)
  • Атрибут ключа подписи сборки (.snk)

    1. Было бы целесообразно создать файл snk на основе pfx или cer?(Не уверен, если это вообще возможно, и если это возможно, как это делается?)

    2. Хотя сборка может быть подписана с помощью защищенного паролем pfx, она не кажется надежнойименуется, если только он не подписан с помощью snk.Но у snk нет защиты паролем.Какой из них безопаснее использовать?Поскольку я являюсь единственным разработчиком в своем проекте, у меня нет проблемы с безопасностью среды для нескольких разработчиков, но я все же хотел бы знать, какой подход лучше.

Большое спасибо,

Ответы [ 3 ]

29 голосов
/ 13 июля 2012

Небольшое уточнение по поводу указанных вами типов файлов:

  • .cer - файлы имеют сертификаты X.509
  • .pfx -файлы являются зашифрованными сертификатами X.509 с использованием симметричного ключа на основе пароля, также см. PKCS # 12 (Wikipedia)
  • .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) только для извлечения открытого ключа! (например, для отсрочки подписания собраний)

29 голосов
/ 28 марта 2012

Чтобы создать файл snk из pfx:

sn -p keypair.pfx key.snk

Я всегда был поклонником использования файлов snk над файлами .pfx, они просто кажутся менее глючными.

5 голосов
/ 17 сентября 2016

Вот тот же метод, предоставленный @ 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 и пароль, и он создаст файл snk в том же каталоге, что и файл pfx (с тем же именем, но не с расширением).

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 в вывод проекта (в любом случае в конфигурациях проекта "Release").

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