2013-05-20 19 views
11

Sto cercando di trovare alcune informazioni su come (se possibile) enumerare tutti i nomi dei contenitori nel CSP Strong Name (provider di servizi di crittografia).Enumerazione dei nomi contenitore del nome sicuro CSP

In sostanza, quando si digita sn.exe -i key.snk MyContainerName, le coppie di chiavi pubbliche e private vengono memorizzate in quello che viene chiamato "contenitore". Più tardi, all'interno del codice, è possibile specificare il nome del contenitore in AssemblyKeyNameAttribute, ad es .:

[assembly: AssemblyKeyName("MyContainerName")] 

questo farà sì che il gruppo da firmare al momento della compilazione.

Sto cercando di scoprire se è possibile enumerare in qualche modo tutti i nomi dei contenitori. Sto scrivendo un plugin for ReSharper che fornisce il completamento del codice per l'attributo InternalsVisibleTo. Mi piacerebbe anche fornire il completamento del codice per l'attributo AssemblyKeyName, dove vorrei pre-compilare l'elenco con nomi di container noti.

Questa informazione è accessibile?

EDIT: Da un commento sulla this question alla sicurezza IT StackExchange, c'è un link ad un po 'di util chiamato KeyPal. L'esecuzione di questo programma di utilità con LM permette di scaricare le chiavi macchina locale:

--------- KeyPal: MACHINE store: 3 keycontainers --------- 
[0] VS_KEY_F726FDF898BC4CB8 
    Signature 1024 
[1] IIS Express Development Certificate Container 
    Exchange 1024 
    CertE: CN=localhost 
[2] MyContainerName 
    Signature 1024 
------------------------------------------------- 

Dove posso vedere che sia [0] e [2] sono nomi validi contenitori da utilizzare con AssemblyKeyName. Tuttavia, c'è il [1] uno - "IIS Express ...", che non è un contenitore valido. Come faccio a distinguerli?

+1

non risolvere l'attuale problema, ma nel caso in cui aiuti ... Sapete in generale specificare tramite Attributi è deprecato (come in faticherete a vederlo al di fuori delle codebase V1.1) a favore di VS che gestisce l'installazione nel negozio e il loro superamento per l'attività CSC? (http://stackoverflow.com/a/16464894/11635) –

+0

@RubenBartelink Interessante, grazie. Ho pensato tanto, dato che non ci sono informazioni aggiornate su queste cose. Sto solo facendo questo per interesse, dal momento che un utente del mio plug-in ReSharper ha segnalato un bug, e nel suo caso stanno ancora utilizzando gli attributi. Quindi mi sono chiesto quanto sarebbe stato difficile "aiutarli". Ma sembra che qualcuno lo usi a malapena. –

risposta

4

Ecco un esempio di codice che fa la stessa cosa di quello strumento keypal. Enumera tutti i contenitori (per la macchina locale) e da lì ottiene quello che può diventare StrongNameKeyPairs. Di solito, forti chiavi di nomi hanno una chiave a 160 byte di lunghezza pubblico (SHA1):

foreach (var kc in KeyUtilities.EnumerateKeyContainers("Microsoft Strong Cryptographic Provider")) 
{ 
    CspParameters cspParams = new CspParameters(); 
    cspParams.KeyContainerName = kc; 
    cspParams.Flags = CspProviderFlags.UseMachineKeyStore; 
    using (RSACryptoServiceProvider prov = new RSACryptoServiceProvider(cspParams)) 
    { 
     if (prov.CspKeyContainerInfo.Exportable) 
     { 
      var blob = prov.ExportCspBlob(true); 
      StrongNameKeyPair kp = new StrongNameKeyPair(prov.ExportCspBlob(false)); 
      Console.WriteLine(kc + " pk length:" + kp.PublicKey.Length); 
     } 
    } 
    Console.WriteLine(); 
} 

...

public static class KeyUtilities 
{ 
    public static IList<string> EnumerateKeyContainers(string provider) 
    { 
     ProvHandle prov; 
     if (!CryptAcquireContext(out prov, null, provider, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT)) 
      throw new Win32Exception(Marshal.GetLastWin32Error()); 

     List<string> list = new List<string>(); 
     IntPtr data = IntPtr.Zero; 
     try 
     { 
      int flag = CRYPT_FIRST; 
      int len = 0; 
      if (!CryptGetProvParam(prov, PP_ENUMCONTAINERS, IntPtr.Zero, ref len, flag)) 
      { 
       if (Marshal.GetLastWin32Error() != ERROR_MORE_DATA) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 
      } 

      data = Marshal.AllocHGlobal(len); 
      do 
      { 
       if (!CryptGetProvParam(prov, PP_ENUMCONTAINERS, data, ref len, flag)) 
       { 
        if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS) 
         break; 

        throw new Win32Exception(Marshal.GetLastWin32Error()); 
       } 

       list.Add(Marshal.PtrToStringAnsi(data)); 
       flag = CRYPT_NEXT; 
      } 
      while (true); 
     } 
     finally 
     { 
      if (data != IntPtr.Zero) 
      { 
       Marshal.FreeHGlobal(data); 
      } 

      prov.Dispose(); 
     } 
     return list; 
    } 

    private sealed class ProvHandle : SafeHandleZeroOrMinusOneIsInvalid 
    { 
     public ProvHandle() 
      : base(true) 
     { 
     } 

     protected override bool ReleaseHandle() 
     { 
      return CryptReleaseContext(handle, 0); 
     } 

     [DllImport("advapi32.dll")] 
     private static extern bool CryptReleaseContext(IntPtr hProv, int dwFlags); 

    } 

    const int PP_ENUMCONTAINERS = 2; 
    const int PROV_RSA_FULL = 1; 
    const int ERROR_MORE_DATA = 234; 
    const int ERROR_NO_MORE_ITEMS = 259; 
    const int CRYPT_FIRST = 1; 
    const int CRYPT_NEXT = 2; 
    const int CRYPT_MACHINE_KEYSET = 0x20; 
    const int CRYPT_VERIFYCONTEXT = unchecked((int)0xF0000000); 

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    private static extern bool CryptAcquireContext(out ProvHandle phProv, string pszContainer, string pszProvider, int dwProvType, int dwFlags); 

    [DllImport("advapi32.dll", SetLastError = true)] 
    private static extern bool CryptGetProvParam(ProvHandle hProv, int dwParam, IntPtr pbData, ref int pdwDataLen, int dwFlags); 
} 

seguenti spazi dei nomi fanno riferimento:

using Microsoft.Win32.SafeHandles; 
using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Reflection; 
using System.Runtime.InteropServices; 
using System.Security.Cryptography; 
+1

Questo è eccellente, grazie! Di recente ho modificato il mio piccolo plugin per leggere direttamente i file snk utilizzando alcuni programmi di utilità da Roslyn. Potrei incorporare anche parte del tuo codice (con una corretta attribuzione, ovviamente!) –

Problemi correlati