Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的智能卡证书_C#_Certificate_Smartcard - Fatal编程技术网

C# C语言中的智能卡证书

C# C语言中的智能卡证书,c#,certificate,smartcard,C#,Certificate,Smartcard,如何确保我正在从智能卡访问证书,而不是在c中形成个人证书存储? 我如何让我的加密提供商使用我的智能卡证书私钥 谢谢 Wally您需要通过加密服务提供商CSP获取智能卡。在Windows 2000、XP和Vista上,每当您将智能卡插入智能卡读卡器时,智能卡上的所有证书都会分发到您的个人证书存储中。您的私钥保留在智能卡上。这意味着,如果您使用证书(例如)对电子邮件进行数字签名,则系统会提示您插入智能卡。如果您的智能卡需要PIN码,系统将要求您输入PIN码。原因是应用程序只有一个位置可以查找用户证书

如何确保我正在从智能卡访问证书,而不是在c中形成个人证书存储? 我如何让我的加密提供商使用我的智能卡证书私钥

谢谢


Wally

您需要通过加密服务提供商CSP获取智能卡。在Windows 2000、XP和Vista上,每当您将智能卡插入智能卡读卡器时,智能卡上的所有证书都会分发到您的个人证书存储中。您的私钥保留在智能卡上。这意味着,如果您使用证书(例如)对电子邮件进行数字签名,则系统会提示您插入智能卡。如果您的智能卡需要PIN码,系统将要求您输入PIN码。原因是应用程序只有一个位置可以查找用户证书,即您的个人证书存储,因此应用程序不必仅为处理智能卡上的证书而重写。

有时,特别是如果您没有在Microsoft推荐的智能卡上使用默认密钥容器名称,证书不会复制到本地证书存储。解决方案是使用crypto api访问具有KP_证书的密钥,从检索到的数据构造证书,并为其分配一个使用您自己的密钥容器名称构造的新RSACryptoServiceProvider

伪C代码如下所示:

int reti = CryptoApi.CryptGetUserKey(_hprovider, keytype, ref userKey);

if (reti)
{
    reti =CryptoApi.CryptGetKeyParam(_userKey, KP_CERTIFICATE, ref  pbdata, ref pwddatalen, 0);
}

if (reti || pwddatalen>0)
{
    byte[] data = new byte[pwddatalen];
    ret  = CryptoApi.CryptGetKeyParam(_userKey, KP_CERTIFICATE, data, ref pwddatalen, 0);
    if (ret) 
    {
        X509Certificate2 c = new X509Certificate2(data);
        X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        store.Open(OpenFlags.ReadOnly);
        X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindByThumbprint, c.Thumbprint, validonly);
        store.Close();

        if (col.Count != 1) 
        {
            //not found in store - CSP didn't copy it
            c.PrivateKey = PrivateKey(keytype);
            return c;
        }
        else
        {
            return col[0];
        }
    }
}


private RSACryptoServiceProvider PrivateKey (KeyType keytype)
{
    CspParameters csparms = new CspParameters();
    csparms.KeyContainerName = _containerName;
    csparms.ProviderName = _provider;
    csparms.ProviderType = 1;
    csparms.Flags = CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseExistingKey;
    csparms.KeyNumber = (int)keytype;

    return new RSACryptoServiceProvider(csparms);
}

我有点困惑,什么时候需要这样的代码?如果说您知道智能卡主题行,则在注册时为每个用户存储该主题行,然后将证书存储在DB中,然后每次有人尝试登录时,将DB中的证书与Request.ClientCertificate中给出的证书进行比较,对吗?您只能将证书的公共部分存储在某个地方,而比较证书的公共部分并不足以证明您拥有私钥。因此,您需要私钥访问来签署一些数据并证明这一点。加密提供程序有时会自动向证书存储区提供私钥,有时则不会。如果没有,这是得到它的方法。有没有一篇文章是你发现这种类型的代码的?您的代码有点不完整,包含未声明的变量。其中有一篇C文章描述了检查私钥有效性的过程。我一直认为,使用X509Certificate对有效证书进行简单检查,以检查散列是否是客户端证书中的有效散列就足够了,但我认为可以用自签名证书伪造散列。任何信息都会有帮助。我仍然不明白为什么我需要检查私钥。C的API不应返回与注册时使用的原始证书相同的ClientCertificate,如果事实上ClientCertificate变量是伪造的,则解密应导致上下文中出现无效证书。ClientCertificate.Hi,您可能需要了解一些关于公钥-私钥加密的知识。。。将公钥的散列和其他散列进行比较不足以证明其身份,因为公钥是公共的,很抱歉,这里不能将其设为粗体,所以任何人都可以进行拦截。为了证明身份,您需要使用私钥对数据段进行签名,并使用私钥对哈希进行有效加密。可以使用公钥验证此签名,并使用它解密散列并将其与数据进行比较。这就是您需要访问私钥的原因。或者我误解了你的问题?Java应用程序可以使用智能卡/证书,而无需在个人存储上安装证书。如果之前未安装,.NET应用程序找不到必要的证书。