class Program
{
static void Main(string[] args)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);
X509Certificate2Collection fcollection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection collection = X509Certificate2UI.SelectFromCollection(fcollection, "Select an X509 Certificate", "Choose a certificate to examine.", X509SelectionFlag.SingleSelection);
X509Certificate2 MyCertificate=null;
if (collection[0] != null)
{
MyCertificate = collection[0];
CRYPT_KEY_PROV_INFO Info = GetCertificateContextProperty(MyCertificate);
string s = Info.pwszContainerName.ToString();
CMS.Sign(Info.pwszContainerName, "password", "123.txt", "123.txt.bin");// падает внутри этого метода
}
Console.ReadKey();
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CRYPT_KEY_PROV_INFO
{
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszContainerName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszProvName;
public uint dwProvType;
public uint dwFlags;
public uint cProvParam;
public IntPtr rgProvParam;
public uint dwKeySpec;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CRYPTOAPI_BLOB
{
public uint cbData;
public IntPtr pbData;
}
[DllImport("crypt32.dll")]
public static extern bool CertGetCertificateContextProperty(IntPtr pCertContext,
uint dwPropId, IntPtr pvData, ref uint pcbData);
public static CRYPT_KEY_PROV_INFO GetCertificateContextProperty(X509Certificate2 certificate)
{
try
{
IntPtr certhandle = certificate.Handle;
uint pcbData = 0;
if (CertGetCertificateContextProperty(certhandle, 2, IntPtr.Zero, ref pcbData))
{
IntPtr memoryChunk = Marshal.AllocHGlobal((int)pcbData);
try
{
if (CertGetCertificateContextProperty(certhandle, 2, memoryChunk,
ref pcbData))
{
CRYPT_KEY_PROV_INFO context =
(CRYPT_KEY_PROV_INFO)Marshal.PtrToStructure(memoryChunk,
typeof(CRYPT_KEY_PROV_INFO));
return context;
}
else
{
throw new Exception("сбой :( !");
}
}
finally
{
Marshal.FreeHGlobal(memoryChunk);
}
}
}
finally
{
//
}
throw new Exception("Ошибка Context Property");
}
}
В метод CMS.Sign(Info.pwszContainerName, "password", "123.txt", "123.txt.bin");
передаётся такой контейнер Info.pwszContainerName = "REGISTRY\\ContainerName".
В этом методе вызывается такая функция.
public static SafeCSPHandle GetCSPHandle(string containerPath, string password)
{
// Variables-переменные
SafeCSPHandle hProv = SafeCSPHandle.Null;
bool bResult = false;
// Get CSP handle
bResult = CryptAcquireContext(
out hProv,
containerPath,
Win32.VPN_DEF_PROV,
Win32.VPN_PROV_TYPE,
Win32.CRYPT_SILENT
);
if (!bResult)
{
throw new Exception("CryptAcquireContext error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
}
ASCIIEncoding enc = new ASCIIEncoding();
bResult = CryptSetProvParam(hProv, PP_SIGNATURE_PIN, enc.GetBytes(password), 0);
if (!bResult)
throw new Exception("CryptSetProvParam error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
// Return handle
return hProv;
}
Вероятно, что нужно передавать в эту функцию
CryptAcquireContext(
out hProv,
containerPath,
Win32.VPN_DEF_PROV,
Win32.VPN_PROV_TYPE,
Win32.CRYPT_SILENT
);
друге параметры, так как контейнер содержится в реестре. Прав?
PS - на самом деле моя программа выдает ошибку так - CryptAcquireContext error # -2146893799. Но я в нете накопал, что это ошибка : набор ключей не определён.