Skip to content

Instantly share code, notes, and snippets.

@jnm2
Created March 17, 2017 16:04
Show Gist options
  • Save jnm2/258a422cd17b9f951ef3ad6244e28519 to your computer and use it in GitHub Desktop.
Save jnm2/258a422cd17b9f951ef3ad6244e28519 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;
public static class CryptographicUtils
{
public static IEnumerable<string> GetKeyContainerNames(bool machine)
{
if (!CryptAcquireContext(
out CryptoServiceProviderHandle provider,
null,
null,
PROV.RSA_FULL,
CryptAcquireContextFlags.VERIFYCONTEXT | (machine ? CryptAcquireContextFlags.MACHINE_KEYSET : 0)))
{
throw new Win32Exception();
}
using (provider)
{
var buffer = new StringBuilder(512);
var size = buffer.Capacity;
if (!CryptGetProvParam(provider, PP.ENUMCONTAINERS, buffer, ref size, CryptGetProvParamFlags.ENUMCONTAINERS_FIRST))
{
var errorCode = Marshal.GetLastWin32Error();
if ((ERROR)errorCode == ERROR.NO_MORE_ITEMS) yield break;
throw new Win32Exception(errorCode);
}
yield return buffer.ToString();
for (;;)
{
size = buffer.Capacity;
if (!CryptGetProvParam(provider, PP.ENUMCONTAINERS, buffer, ref size, CryptGetProvParamFlags.ENUMCONTAINERS_NEXT))
{
var errorCode = Marshal.GetLastWin32Error();
if ((ERROR)errorCode == ERROR.NO_MORE_ITEMS) yield break;
throw new Win32Exception(errorCode);
}
yield return buffer.ToString();
}
}
}
#region P/invoke
// ReSharper disable UnusedMember.Local
// ReSharper disable ClassNeverInstantiated.Local
// ReSharper disable InconsistentNaming
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool CryptAcquireContext(out CryptoServiceProviderHandle hProv, string pszContainer, string pszProvider, PROV dwProvType, CryptAcquireContextFlags dwFlags);
private sealed class CryptoServiceProviderHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private CryptoServiceProviderHandle() : base(true)
{
}
protected override bool ReleaseHandle()
{
return CryptReleaseContext(handle, 0);
}
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);
}
private enum PROV : uint
{
RSA_FULL = 1
}
[Flags]
private enum CryptAcquireContextFlags : uint
{
VERIFYCONTEXT = 0xF0000000,
NEWKEYSET = 0x8,
DELETEKEYSET = 0x10,
MACHINE_KEYSET = 0x20,
SILENT = 0x40,
DEFAULT_CONTAINER_OPTIONAL = 0x80
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
private static extern bool CryptGetProvParam(CryptoServiceProviderHandle hProv, PP dwParam, [Out] StringBuilder pbData, ref int dwDataLen, CryptGetProvParamFlags dwFlags);
private enum PP : uint
{
ENUMCONTAINERS = 2
}
private enum CryptGetProvParamFlags : uint
{
ENUMCONTAINERS_FIRST = 1,
ENUMCONTAINERS_NEXT = 2
}
private enum ERROR
{
NO_MORE_ITEMS = 259
}
// ReSharper restore UnusedMember.Local
// ReSharper restore ClassNeverInstantiated.Local
// ReSharper restore InconsistentNaming
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment