2013-05-20 4 views
11

(가능한 경우) 강력한 이름 CSP (암호화 서비스 공급자)의 모든 컨테이너 이름을 열거하는 방법에 대한 정보를 찾으려고합니다.강력한 이름의 컨테이너 이름 열거 CSP

기본적으로 sn.exe -i key.snk MyContainerName을 입력하면 공개 키와 개인 키 쌍이 "컨테이너"에 저장됩니다. 나중에 코드에서, 당신은 : 예컨대의 AssemblyKeyNameAttribute에 컨테이너 이름을 지정할 수

[assembly: AssemblyKeyName("MyContainerName")] 

이 어셈블리가 컴파일시에 서명하게됩니다.

어떻게 든 모든 컨테이너 이름을 열거 할 수 있는지 알아 내려고하고 있습니다. 나는 InternalsVisibleTo 속성에 대한 코드 완성을 제공하는 plugin for ReSharper을 쓰고 있습니다. 또한 AssemblyKeyName 속성에 대해 코드 완성을 제공하고 싶습니다. 여기서는 알려진 컨테이너 이름으로 목록을 미리 채울 것입니다.

이 정보에 액세스 할 수 있습니까?

편집 : IT 보안 StackExchange에서 this question에 코멘트에서 라 불리는 KeyPal 폴더의 유틸리티 조금에 대한 링크가 있습니다. LM에이 유틸리티를 실행하면 로컬 컴퓨터 키 저장소를 덤프 : 내가 볼 수

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

이 모두 [0]와 [2] AssemblyKeyName에 사용할 유효한 컨테이너 이름입니다. 그러나 [1] 하나가 있습니다 - "IIS Express ...", 유효한 컨테이너가 아닙니다. 어떻게 구별합니까?

+1

실제를 해결하지 일반적으로 강력한 이름 키는 160 바이트 길이의 공개 키 (SHA1)가 문제가 발생했을 때 도움이되는 경우 ... 일반적으로 Attributes를 통해 지정하는 것은 더 이상 사용되지 않습니다 (V1.1 코드베이스 외부에서 볼 때 어려움을 겪을 수 있음). VS 로의 설치 관리 및 저장소 전달 CSC 작업에? (http://stackoverflow.com/a/16464894/11635) –

+0

@RubenBartelink 흥미 롭습니다. 감사합니다. 나는이 것들에 대한 최신 정보가 거의 없기 때문에 많은 것을 생각했다. ReSharper 플러그인의 사용자가 버그를보고하고 자신의 경우 여전히 특성을 사용하고 있기 때문에 나는 관심을 보이지 않고 있습니다. 그래서 나는 그들을 "돕는"것이 얼마나 어려울 지 궁금했습니다. 그러나 그것은 더 이상 거의 사용하지 않는 것처럼 보입니다. –

답변

4

다음은 keypal 도구와 동일한 작업을 수행하는 샘플 코드입니다. 모든 컨테이너 (로컬 컴퓨터 용)를 열거하고 거기에서 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 파일을 직접 읽도록 작은 플러그인을 수정했습니다. 적절한 코드를 사용하여 코드 일부를 통합 할 수도 있습니다. –

관련 문제