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

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

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

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

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

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

3 ответов


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

  • .cer-файлы X. 509 сертификаты
  • .pfx-файл-файлы зашифрованы сертификатами X. 509 с использованием симметричного ключа на основе пароля, Также см. PKCS #12 (Википедия)
  • .snk-файлы содержат только ключ RSA (только открытый/закрытый или открытый)

не имеет значения, подписываете ли вы сборку с помощью .pfx-файл-файлы или .snk-файлы, он получит строгое имя в любом случае. Хранение ключа RSA в виде зашифрованного сертификата (.pfx-файл), конечно, более безопасно, чем хранить только незашифрованный ключ (.snk).

вы можете легко извлечь ключ из этих файлов в коде, используя class 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) только для извлечения открытого ключа! (например, для delay-подписание сборок)


для создания файла snk из pfx:

sn -p keypair.pfx key.snk

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


вот тот же метод, предоставленный @Sir Убить Много в своем ответ, но преобразованный в сценарий 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;"