2013-05-20 20 views
11

Güçlü Ad CSP'sinde (Kriptografik Servis Sağlayıcısı) tüm kapsayıcı adlarını nasıl (eğer varsa) nasıl sıralayacağınızla ilgili bazı bilgileri bulmaya çalışıyorum. Temel olarak, sn.exe -i key.snk MyContainerName yazarken, genel ve özel anahtar çiftleri "kapsayıcı" olarak adlandırılır. Daha sonra Kodunuzdaki, sen .: ör AssemblyKeyNameAttribute konteyner adını belirtebilirsinizGüçlü adın kapsayıcı adlarını belirtme CSP

[assembly: AssemblyKeyName("MyContainerName")] 

Bu meclis derleme sırasında imzalanacak neden olacaktır.

Tüm kapsayıcı adlarını bir şekilde numaralandırmanın mümkün olup olmadığını öğrenmeye çalışıyorum. InternalsVisibleTo özniteliği için kod tamamlama sağlayan bir plugin for ReSharper yazıyorum. Ayrıca, listeyi bilinen kapsayıcı adlarıyla önceden dolduracağım AssemblyKeyName özniteliği için kod tamamlamayı da sağlamak istiyorum.

Bu bilgiye erişilebilir mi?

DÜZENLEME: IT Security Stack Exchange de this question yorumunda itibaren denilen KeyPal util biraz bir bağlantı var. LM ile bu programı Koşu yerel makine anahtar deposunu dökümünü: Görebildiğim

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

her iki [0] ve [2] AssemblyKeyName ile kullanmak için geçerli konteyner isimleridir. Ancak, geçerli bir kap olmayan [1] bir - "IIS Express ..." var. Bunları nasıl ayırt edebilirim?

+1

gerçek çözme değil Genellikle, güçlü bir isim tuşları 160 byte uzunlukta genel anahtarı (SHA1) sahip sorun, ama o yardımcı olur ... Genel olarak tanımlayarak Öznitelikler aracılığıyla tanımlayarak (V1.1 codebases dışında görmek için mücadele olarak) deplasmanda mağaza yönetme ve bunları dağıtmak için VS lehine CSC Görevine mi? (http://stackoverflow.com/a/16464894/11635) –

+0

@RubenBartelink İlginç, teşekkürler. Ben de bu gibi şeyler hakkında güncel bir bilgi olmadığı için çok fazla varsaydım. Ben sadece ilgimi çekiyorum, çünkü ReSharper eklentimin bir kullanıcısı bir hata bildirdi ve onun durumunda hala öznitelikleri kullanıyorlar. Bu yüzden onlara yardım etmenin ne kadar zor olacağını merak ettim. Ancak, artık hiç kimse onu zar zor kullanmıyor gibi görünüyor. –

cevap

4

İşte örnek kod, bu tür bir tuş takımı aracıyla aynı şeyi yapar. Tüm kapları (yerel makine için) numaralandırır ve buradan StrongNameKeyPairs haline gelebilir.

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(); 
} 

... Aşağıdaki Ad alanları başvurulan

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); 
} 

:

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

Bu mükemmel, teşekkürler! Kısa bir süre önce benim küçük eklenti, Snick dosyalarını Roslyn'in bazı araçlarını kullanarak okumak için değiştirdim. Kodunuzun bir kısmını da buna dahil edebilirim (elbette uygun ilişkilendirme ile!) –