2013-05-20 15 views
11

Próbuję znaleźć informacje o tym, jak (jeśli w ogóle możliwe) wyliczyć wszystkie nazwy kontenerów w usłudze Strong Name CSP (Cryptographic Service Provider).Wyliczanie nazw pojemników o silnej nazwie CSP

Zasadniczo po wpisaniu sn.exe -i key.snk MyContainerName pary kluczy publicznych i prywatnych są przechowywane w tak zwanym "kontenerze". Później w kodzie, można podać nazwę kontenera w AssemblyKeyNameAttribute, np .:

[assembly: AssemblyKeyName("MyContainerName")] 

To spowoduje, że zespół ma zostać podpisana w czasie kompilacji.

Próbuję dowiedzieć się, czy możliwe jest wyliczenie wszystkich nazw pojemników. Piszę kod plugin for ReSharper, który zapewnia uzupełnianie kodu dla atrybutu InternalsVisibleTo. Chciałbym również zapewnić uzupełnienie kodu dla atrybutu AssemblyKeyName, w którym wstępnie wypełniłem listę znanymi nazwami kontenerów.

Czy ta informacja jest dostępna?

EDIT: Od komentarzu this question w IT Security Stack Exchange Network, jest tam link do trochę util zwanego KeyPal. Uruchomienie tego programu narzędziowego z LM zrzuci lokalnego magazynu kluczy maszyny:

--------- 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 
------------------------------------------------- 

Gdzie mogę zobaczyć, że zarówno [0] i [2] są prawidłowymi nazwami kontenerów do korzystania z AssemblyKeyName. Istnieje jednak [1] jeden - "IIS Express ...", który nie jest prawidłowym kontenerem. Jak mogę je rozróżnić?

+1

by nie rozwiązywać rzeczywiste problem, ale na wypadek, gdyby pomogło ... Wiesz, że generowanie przez Atrybuty jest przestarzałe (jak w przypadku trudnych do zobaczenia poza bazami kodowymi V1.1) na korzyść VS zarządzania instalacją w sklepie i przekazywaniem ich do zadania CSC? (http://stackoverflow.com/a/16464894/11635) –

+0

@RubenBartelink Ciekawe, dzięki. Zakładałem tyle, ponieważ nie ma prawie żadnych aktualnych informacji o tych rzeczach. Robię to tylko z zainteresowaniem, ponieważ użytkownik mojej wtyczki ReSharper zgłosił błąd, aw jego przypadku wciąż używają atrybutów. Zastanawiałem się, jak trudno byłoby im "pomóc". Ale wygląda na to, że nikt go już nie używa. –

Odpowiedz

4

Oto przykładowy kod, który robi to samo, co to narzędzie keypalne. Wylicza wszystkie pojemniki (dla komputera lokalnego), a stamtąd dostaje ten, który może stać się StrongNameKeyPairs. Zazwyczaj silne klucze nazwa ma 160 bajtów długości klucza publicznego (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); 
} 

Poniższe Przestrzenie nazw są wymienione:

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

To jest doskonałe, dzięki! Niedawno zmodyfikowałem moją małą wtyczkę, aby odczytywać snk bezpośrednio za pomocą narzędzi z Roslyn. Mogę również włączyć do niego część twojego kodu (oczywiście z właściwą atrybucją!) –

Powiązane problemy