在智能卡加密提供程序的对话框中设置PIN提示

时间:2015-01-09 16:25:33

标签: c# c++ windows cryptoapi

我想更改调用需要智能卡PIN的CryptoApi操作时显示的文本。当前提示非常通用(并且使用系统语言),"请输入您的身份验证PIN":

enter image description here

此对话框显示在COM对象中调用CryptSignMessage时,但调用是从C#WPF桌面应用程序(.NET 4.5)进行的。如何自定义对话框?我找到PP_PIN_PROMPT_STRING函数的CryptSetProvParam参数,但该函数需要HCRYPTPROV而我没有这个句柄。我所拥有的只是读者的姓名和签名证书。只是无法绕过它。

是否可以从C ++或C#(最好是C#)自定义PIN对话框?

1 个答案:

答案 0 :(得分:1)

我相信以下内容应该有效。因为我没有任何设置来测试收集我无法验证的信息。

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptAcquireContext(out IntPtr phProv, string pszContainer, string pszProvider, uint dwProvType, uint dwFlags);

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CryptSetProvParam(IntPtr hProv, uint dwParam, [In] byte[] pbData, uint dwFlags);

[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);

const string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
const uint NTE_BAD_KEYSET = 0x80090016;
const uint PROV_RSA_FULL = 1;
const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
const uint CRYPT_NEWKEYSET = 0x00000008;
const uint PP_PIN_PROMPT_STRING = 0x2C;

public unsafe void SetPinText(string text)
{
    byte[] data = Encoding.UTF8.GetBytes(text);

    IntPtr hCryptProv;

    try
    {
        if (!CryptAcquireContext(out hCryptProv, null, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
        {
            if (Marshal.GetLastWin32Error() == NTE_BAD_KEYSET)
            {
                if (!CryptAcquireContext(out hCryptProv, null, null, PROV_RSA_FULL, CRYPT_NEWKEYSET))
                    throw new Exception("Unable to acquire crypt context.");
            }
            else
            {
                throw new Exception("Unable to acquire crypt context.");
            }
        }

        if (!CryptSetProvParam(hCryptProv, PP_PIN_PROMPT_STRING, DataColumn, 0))
            throw new Exception("Unable to set prompt string.");
    }
    finally
    {
        if (hCryptProv != IntPtr.Zero)
        {
            CryptReleaseContext(hCryptProv, 0);
        }
    }
}