Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

Немного разъяснения о ваших упомянутых типах файлов:

  • .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) для извлечения только открытого ключа! (например, для оповещения о сбое сборок)

Ответ 2

Чтобы сгенерировать snk файл из pfx:

sn -p keypair.pfx key.snk

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

Ответ 3

Здесь тот же метод, предоставленный @Sir Kill A Lot в ответе , но преобразованный в 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);

Просто запустите script, указав путь и пароль файла 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, чтобы автоматизировать процесс использования тех же ключей из наших сертификатов подписи подлинника (файл pfx) для сильной подписи имени. Это не требование, но мне кажется, что мне кажется, что они должны быть одинаковыми, и это питает мои тенденции OCD.

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

И, если вам интересно, у меня есть что-то вроде следующего как часть моего процесса пост-сборки в Visual Studio, чтобы добавить подпись к подлиннику к выходу проекта (в любом случае в конфигурациях проекта "Релиз" ).

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