如何提供 PIN 码以编程方式访问智能卡?

发布于 2024-08-17 21:12:37 字数 660 浏览 3 评论 0原文

我使用证书来保护客户端和服务器之间的通信(没有代码,只有端点配置)。证书当前存储在 ACOS5 智能卡中。一切都运行良好,除了每次 WCF 创建新通道来访问服务器时,ACOS5 驱动程序都会要求用户输入“用户 PIN”。不幸的是,这种情况经常发生。

有什么方法可以配置驱动程序以缓存用户在当前进程中输入的 PIN 至少一段时间,或者如何缓存 PIN 并每次在同一会话中以编程方式提供它?

我在这个 文章

这是因为在以前的版本中 Windows 的每个 CSP 都会缓存 您输入的 PIN,但 Windows 7 实际上将 PIN 转换为安全的 令牌并缓存它。很遗憾 只有一个全局令牌缓存 但 CSP 不能使用代币 由其他人生成,所以首先 智能卡CSP提示您并缓存 一个令牌,然后 SSL 会提示您并 缓存自己的令牌(覆盖 第一个),然后是智能卡系统 再次提示您(因为它已缓存 令牌消失了)。

但我无法使用作者提出的解决方案。那我该怎么办呢?

I'm using certificates to secure my communications between client and server (no code, just endpoint configuration). Certificates are currently stored in ACOS5 smart cards. Everything works very well except that every time when WCF creates a new channel to access the server, the ACOS5 driver asks user to enter “User PIN”. Unfortunately, it happens quite often.

Is there any way to configure driver to cache PIN that user has already entered within current process at least for some time or how can I cache pin and provide it every time programmatically within same session?

I have found some useful in this article:

This is because in previous versions
of Windows each CSP would cache the
PIN you entered, but Windows 7
actually converts the PIN to a secure
token and caches that. Unfortunately
there’s only one global token cache
but the CSPs can’t use tokens
generated by others, so first the
smart card CSP prompts you and caches
a token, then SSL prompts you and
caches its own token (overwriting the
first one), then the smart card system
prompts you again (because its cached
token is gone).

But I can't use solution that was proposed by author. So what should I do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一笔一画续写前缘 2024-08-24 21:12:37

这是我们多年来在主应用程序中发现和使用的一种方法:

static class X509Certificate2Extension
{
    public static void SetPinForPrivateKey(this X509Certificate2 certificate, string pin)
    {
        if (certificate == null) throw new ArgumentNullException("certificate");
        var key = (RSACryptoServiceProvider)certificate.PrivateKey;

        var providerHandle = IntPtr.Zero;
        var pinBuffer = Encoding.ASCII.GetBytes(pin);

        // provider handle is implicitly released when the certificate handle is released.
        SafeNativeMethods.Execute(() => SafeNativeMethods.CryptAcquireContext(ref providerHandle, 
                                        key.CspKeyContainerInfo.KeyContainerName, 
                                        key.CspKeyContainerInfo.ProviderName,
                                        key.CspKeyContainerInfo.ProviderType, 
                                        SafeNativeMethods.CryptContextFlags.Silent));
        SafeNativeMethods.Execute(() => SafeNativeMethods.CryptSetProvParam(providerHandle, 
                                        SafeNativeMethods.CryptParameter.KeyExchangePin, 
                                        pinBuffer, 0));
        SafeNativeMethods.Execute(() => SafeNativeMethods.CertSetCertificateContextProperty(
                                        certificate.Handle, 
                                        SafeNativeMethods.CertificateProperty.CryptoProviderHandle, 
                                        0, providerHandle));
    }
}

internal static class SafeNativeMethods
{
    internal enum CryptContextFlags
    {
        None = 0,
        Silent = 0x40
    }

    internal enum CertificateProperty
    {
        None = 0,
        CryptoProviderHandle = 0x1
    }

    internal enum CryptParameter
    {
        None = 0,
        KeyExchangePin = 0x20
    }

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CryptAcquireContext(
        ref IntPtr hProv,
        string containerName,
        string providerName,
        int providerType,
        CryptContextFlags flags
        );

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

    [DllImport("CRYPT32.DLL", SetLastError = true)]
    internal static extern bool CertSetCertificateContextProperty(
        IntPtr pCertContext,
        CertificateProperty propertyId,
        uint dwFlags,
        IntPtr pvData
        );

    public static void Execute(Func<bool> action)
    {
        if (!action())
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }
    }
}

完整的帖子和作者在这里:
http:// www.infinitec.de/post/2010/11/22/Setting-the-PIN-of-a-smartcard-programmatically.aspx

This is a way we found and use from many years in our main application:

static class X509Certificate2Extension
{
    public static void SetPinForPrivateKey(this X509Certificate2 certificate, string pin)
    {
        if (certificate == null) throw new ArgumentNullException("certificate");
        var key = (RSACryptoServiceProvider)certificate.PrivateKey;

        var providerHandle = IntPtr.Zero;
        var pinBuffer = Encoding.ASCII.GetBytes(pin);

        // provider handle is implicitly released when the certificate handle is released.
        SafeNativeMethods.Execute(() => SafeNativeMethods.CryptAcquireContext(ref providerHandle, 
                                        key.CspKeyContainerInfo.KeyContainerName, 
                                        key.CspKeyContainerInfo.ProviderName,
                                        key.CspKeyContainerInfo.ProviderType, 
                                        SafeNativeMethods.CryptContextFlags.Silent));
        SafeNativeMethods.Execute(() => SafeNativeMethods.CryptSetProvParam(providerHandle, 
                                        SafeNativeMethods.CryptParameter.KeyExchangePin, 
                                        pinBuffer, 0));
        SafeNativeMethods.Execute(() => SafeNativeMethods.CertSetCertificateContextProperty(
                                        certificate.Handle, 
                                        SafeNativeMethods.CertificateProperty.CryptoProviderHandle, 
                                        0, providerHandle));
    }
}

internal static class SafeNativeMethods
{
    internal enum CryptContextFlags
    {
        None = 0,
        Silent = 0x40
    }

    internal enum CertificateProperty
    {
        None = 0,
        CryptoProviderHandle = 0x1
    }

    internal enum CryptParameter
    {
        None = 0,
        KeyExchangePin = 0x20
    }

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CryptAcquireContext(
        ref IntPtr hProv,
        string containerName,
        string providerName,
        int providerType,
        CryptContextFlags flags
        );

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

    [DllImport("CRYPT32.DLL", SetLastError = true)]
    internal static extern bool CertSetCertificateContextProperty(
        IntPtr pCertContext,
        CertificateProperty propertyId,
        uint dwFlags,
        IntPtr pvData
        );

    public static void Execute(Func<bool> action)
    {
        if (!action())
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }
    }
}

The full post and author is here:
http://www.infinitec.de/post/2010/11/22/Setting-the-PIN-of-a-smartcard-programmatically.aspx

孤寂小茶 2024-08-24 21:12:37

实际上,我已经找到了我的问题的答案:由高级卡系统 CSP v1.9 中的错误引起的所描述的行为。切换到 Alladin eToken 应用程序后,它可以正常工作。
因此,我无法通过代码提供 PIN,但输入后 CSP 会记住它,并且不需要通过代码提供。更多好消息:在这种情况下,用户会在来自 CSP 的熟悉对话框中看到 PIN 请求。

Actually I have found answer on my question: the described behavior caused by bug in Advanced Card Systems CSP v1.9. After switching to Alladin eToken application works as it should.
So I can't provide PIN from code but it is remembered by CSP after entering and providing from code is not required. More good news: user sees PIN request in familiar dialog from CSP in this case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文