Comment créer un snk à partir de pfx / cer?
Microsoft semble avoir créé une jungle de certification, c'est difficile à comprendre.
- certificat Microsoft X. 509 (.cer)
- Échange De Renseignements Personnels (.pfx)
-
Attribut Clé De Signature D'Assemblage (.snk)
Serait-il souhaitable de créer un fichier snk basé sur pfx ou cer? (Je ne sais pas si c'est encore possible, et si c'est possible comment faire?)
Alors qu'un assemblage peut être signé avec un pfx protégé par mot de passe, il ne semble pas être fort nommé cependant, à moins qu'il ne soit signé avec snk plutôt. Mais le snk n'a pas de protection par mot de passe. Lequel est le plus sûr à utiliser? Comme je suis le seul développeur de mon projet, je n'ai pas le problème d'environnement de sécurité multi-développeur, mais aimerait toujours savoir quelle est la meilleure approche.
Merci Beaucoup,
3 réponses
Une petite clarification sur les types de fichiers mentionnés:
- .cer - les fichiers sont des certificats X. 509
- .pfx - les fichiers sont des certificats X. 509 cryptés à l'aide d'une clé symétrique basée sur un mot de passe, Voir aussi PKCS # 12 (Wikipedia)
- .snk - les fichiers ne contiennent que la clé RSA (publique/privée ou publique uniquement)
Peu importe si vous signez un assembly en utilisant .pfx-fichiers ou .snk - fichiers, il obtiendra un nom fort de toute façon. Stocker la clé RSA en tant que certificat chiffré (.pfx ) est bien sûr plus sûr que de stocker uniquement la clé non cryptée (.snk ).
Vous pouvez facilement extraire la clé de ces fichiers dans le code en utilisant la classe System.Security.Cryptography.X509Certificates.X509Certificate2
.
Pour extraire la clé de .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);
}
Utilisez privateKey.ExportCspBlob(false)
pour extraire la clé publique uniquement! (par exemple pour la signature tardive des assemblages)
Pour générer un fichier snk à partir d'un pfx:
sn -p keypair.pfx key.snk
J'ai toujours été un fan de l'utilisation des fichiers snk .les fichiers pfx semblent juste moins bogués.
Voici la même méthode fournie par @ Sir Kill A Lot dans sa réponse , mais convertie en script 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);
Exécutez simplement ce script en fournissant le chemin du fichier pfx et le mot de passe et il créera un fichier snk dans le même répertoire que le fichier pfx (avec le même nom que l'extension).
powershell.exe -File pfx2snk.ps1 -pfxFilePath cert.pfx -pfxPassword "pfx password"
Ou, si votre pfx n'a pas de mot de passe (honte, honte):
powershell.exe -File pfx2snk.ps1 cert.pfx
, Et si vous êtes assez malheureux pour travailler dans un environnement où ils ne permettent pas l'exécution des scripts PowerShell (ie. sessions PowerShell interactives uniquement), alors vous pouvez exécuter ce liner moche à partir d'un cmd standard.ligne de commande exe (remplacement des chemins de fichiers et du mot de passe pfx si nécessaire).
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));"
En fait, j'utilise ce one-liner comme une partie standard de mon processus de pré-construction Visual Studio pour automatiser le processus d'utilisation des mêmes clés de nos certificats de signature authenticode (fichier pfx) pour la signature de noms forts. Ce n'est pas une obligation, mais il me semble juste logique qu'ils devraient être les mêmes et cela nourrit mes tendances TOC.
(j'utilise un fichier snk plutôt que le pfx original parce que j'ai eu l'expérience "buggy" en utilisant des fichiers pfx pour la signature de nom fort que @punkcoder mentionné dans sa réponse)
Et, si vous êtes intéressé, j'ai quelque chose comme ce qui suit dans le cadre de mon processus de post-construction dans Visual Studio pour ajouter la signature authenticode à la sortie du projet (dans " Release" configurations de projet de toute façon).
powershell.exe -Command "Set-AuthenticodeSignature -FilePath '$(TargetPath)' -Certificate '$(SolutionDir)MyCert.pfx' -TimestampServer http://timestamp.verisign.com/scripts/timstamp.dll -HashAlgorithm sha256;"