【问题标题】:How to provide PIN to access smartcard programmatically?如何提供 PIN 以编程方式访问智能卡?
【发布时间】:2010-01-14 22:25:35
【问题描述】:

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

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

我在这个article中发现了一些有用的东西:

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

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

【问题讨论】:

    标签: wcf wcf-security smartcard


    【解决方案1】:

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

    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

    【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2010-12-21
      • 2011-02-17
      • 1970-01-01
      • 2017-12-19
      • 1970-01-01
      • 2012-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多