2013-05-20 31 views
11

厳密な名前のCSP(暗号化サービスプロバイダ)内のすべてのコンテナ名を列挙する方法についてすべての情報を検索しようとしています。厳密な名前のコンテナ名を列挙するCSP

基本的に、sn.exe -i key.snk MyContainerNameと入力すると、公開鍵と秘密鍵のペアが「コンテナ」と呼ばれるものに格納されます。その後、あなたのコードの中に、あなたは:例えば、AssemblyKeyNameAttributeにコンテナ名を指定することができ

[assembly: AssemblyKeyName("MyContainerName")] 

これは、アセンブリがコンパイル時に署名されるようになります。

私は何とかすべてのコンテナ名を列挙できるかどうかを調べようとしています。私はInternalsVisibleTo属性のコード補完を提供するplugin for ReSharperを書いています。また、AssemblyKeyName属性のコード補完を提供したいと思います。ここでは、リストに既知のコンテナ名をあらかじめ入力しています。

この情報にアクセス可能ですか?

EDIT:ITセキュリティStackExchangeでthis questionにコメントからKeyPalと呼ばれる小さなutilのへのリンクがあります。私は両方の[0]と[2] AssemblyKeyNameで使用する有効なコンテナ名であることがわかります

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

LMでこのユーティリティを実行すると、ローカルマシンのキーストアをダンプします。しかし、[1] 1つ - 「IIS Express ...」があります。これは有効なコンテナではありません。どうやって区別するのですか?

+1

実際に解いていない通常、厳密な名前のキーは、160バイト長の公開鍵(SHA1)を持っていますあなたが一般的にAttributesを使って指定することは廃止されました(V1.1コードベース外で見るのは難しいでしょう)VSを使ってストアへのインストール管理とパスCSCタスクに? (http://stackoverflow.com/a/16464894/11635) –

+0

@RubenBartelink面白い、ありがとう。これらのことについての最新の情報はほとんどないので、私は多くを前提としていました。 ReSharperプラグインのユーザーがバグを報告していて、彼の場合はまだ属性を使用しているので、私はこれを興味の対象から外しています。だから私は彼らを「援助する」ことがどれほど難しいのだろうと思った。しかし、もう誰もそれをほとんど使わないように見えます。 –

答えて

4

ここに、そのキーパルツールと同じことを行うサンプルコードがあります。すべてのコンテナ(ローカルマシン用)を列挙し、そこからStrongNameKeyPairsになるコンテナを取得します。

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

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

これは素晴らしいです、ありがとう!私は最近、Roslynのいくつかのユーティリティを使ってsnkファイルを直接読み込むように小さなプラグインを修正しました。私はあなたのコードのいくつかを同様に組み込むことができます(もちろん、適切な帰属で!) –

関連する問題