Как создать снк из pfx / cer?
Кажется, что Microsoft создала сертификационные джунгли, это трудно понять.
- Сертификат Microsoft X.509 (.cer)
- Обмен личной информацией (.pfx)
Атрибут ключа подписи сборки (.snk)
Было бы целесообразно создать файл snk на основе pfx или cer? (Не уверен, если это вообще возможно, и если это возможно, как это делается?)
Хотя сборка может быть подписана с помощью защищенного паролем pfx, она, похоже, не имеет строгого имени, если только она не подписана с помощью snk. Но у snk нет защиты паролем. Какой из них безопаснее использовать? Поскольку я являюсь единственным разработчиком в своем проекте, у меня нет проблемы безопасности среды для нескольких разработчиков, но я все же хотел бы знать, что является лучшим подходом.
Большое спасибо,
3 ответа
Небольшое разъяснение по поводу указанных вами типов файлов:
- .cer- файлы являются сертификатами X.509
- Файлы.pfx- это зашифрованные сертификаты X.509, использующие симметричный ключ на основе пароля, также см. PKCS # 12 (Wikipedia)
- .snk-files содержит только ключ 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)
извлечь только открытый ключ! (например, для отсрочки подписи сборок)
Чтобы сгенерировать файл snk из pfx:
sn -p keypair.pfx key.snk
Я всегда был поклонником использования файлов snk над файлами.pfx, они просто кажутся менее глючными.
Вот тот же метод, предоставленный 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, потому что у меня был "глючный" опыт использования файлов punkcoder для подписания punkcoder имени, который 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;"