Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.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#USB eToken签名和验证问题_C#_Cryptography_Rsacryptoserviceprovider - Fatal编程技术网

C#USB eToken签名和验证问题

C#USB eToken签名和验证问题,c#,cryptography,rsacryptoserviceprovider,C#,Cryptography,Rsacryptoserviceprovider,我有一个x509证书,带有存储在safenet usb令牌上的公钥和私钥 我有一些数据要签名。我需要使用证书的公钥来验证签名 使用我自己的自签名证书进行签名的最终代码: RSACryptoServiceProvider rsa1 = (RSACryptoServiceProvider)useCertificate.PrivateKey; byte[] digitalSignature = rsa1.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"))

我有一个x509证书,带有存储在safenet usb令牌上的公钥和私钥

我有一些数据要签名。我需要使用证书的公钥来验证签名

使用我自己的自签名证书进行签名的最终代码:

RSACryptoServiceProvider rsa1 = (RSACryptoServiceProvider)useCertificate.PrivateKey;
byte[] digitalSignature = rsa1.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)useCertificate.PublicKey.Key;
Verified = rsa.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), digitalSignature);
以及使用证书的公钥进行验证的代码:

RSACryptoServiceProvider rsa1 = (RSACryptoServiceProvider)useCertificate.PrivateKey;
byte[] digitalSignature = rsa1.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)useCertificate.PublicKey.Key;
Verified = rsa.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), digitalSignature);
使用自签名证书,此操作正常。我得到的签名是256
字节

由于令牌使用此代码获取签名,然后对其进行验证,我只获得128字节的签名,验证失败:

CspParameters csp = new CspParameters(1, "SafeNet RSA CSP");
csp.Flags = CspProviderFlags.UseDefaultKeyContainer;
csp.KeyNumber = (int)KeyNumber.Signature;
RSACryptoServiceProvider rsa1 = new RSACryptoServiceProvider(csp);
验证与上面相同的代码

我注意到我想要使用的证书是令牌中的默认证书。为什么我只得到128字节的签名而不是256字节的?我怀疑这就是为什么它无法验证

我的csp中是否需要一些其他参数和设置

谢谢

*根据评论更新*

很明显,当我指定csp.keyNumber=(int)keyNumber.Signature时,我使用的是1024位,但这是令牌实际返回任何内容的唯一方式。即使令牌密钥大小为2048位,并且密钥规范为\u KEYEXCHANGE。当我使用我认为实际上是正确的交换密钥号时,当我尝试计算签名时,系统会提示我登录,但随后会出现异常“参数无效”。所以我需要两件事情中的一件:

1-如何使用公钥使用1024位验证签名(没有令牌-我们需要在没有令牌的机器上进行验证)

2-如何设置不正确的内容,以便我们能够通过异常-我认为这是更好的主意

是否有人对我可以如何处理此异常或导致此异常的原因有任何建议

以下是所有例外情况的详细信息:

HResult=-2147024809 消息=参数不正确。 堆栈跟踪

在System.Security.Cryptographics.CryptographicException.ThrowCryptographicException(Int32 hr)中 在System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey、Int32 keyNumber、Int32 calgKey、Int32 calgHash、Byte[]散列、Int32 cbHash、ObjectHandleOnStack retSignature) at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey、Int32 keyNumber、Int32 calgKey、Int32 calgHash、Byte[]散列) 位于System.Security.Cryptography.RSACryptoServiceProvider.SignHash(字节[]rgbHash,Int32 calgHash) 位于System.Security.Cryptography.RSACryptoServiceProvider.SignHash(字节[]rgbHash,字符串str)
在z:\Work\computesolve\enctest\TE\TE\Program.cs:line 77中的TE.Program.Main(String[]args)处,我必须质疑您关于它实际上是默认密钥容器密钥的断言(您可能在代码第一次运行时创建了该密钥容器密钥,因为您没有断言
UseExistingKey
标志)

假设证书在您的证书存储中,运行
certutil-user-silent store my
,找到证书条目并检查
密钥容器
值:

================ Certificate 11 ================
Serial Number: 0123456789abcdeffedcba9876543210
Issuer: CN=Intermediate Certificate Authority
 NotBefore: 10/21/2016 7:26 AM
 NotAfter: 10/21/2017 7:26 AM
Subject: CN=bartonjs
Non-root Certificate
Template:
Cert Hash(sha1): 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14
  Key Container = le-Smartcard-987abcdf-6332-43-16531
  Provider = Microsoft Base Smart Card Crypto Provider
如果复制/粘贴任何值,并将其用作密钥容器名称,则签名的大小可能会正确


(如果您的证书位于计算机存储区而不是用户存储区,请省略
-user
选项)

这一问题的答案是双重的。如果您正在使用这些设备之一,我在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider下的注册表中发现

有3个不同的提供商。每个都具有相同的类型设置,甚至图像设置-使用的dll。但是选择另一个,在我的例子中是Datakey RSP CSP,它提供了基于2048位密钥的256字节签名。您还必须确保您使用的证书是令牌中的默认证书。就我而言,有两种不同的证书。我使用一个进行验证,但使用另一个进行签名

测试客户端的完整源代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;

namespace TE
{
class Program
{
    static void Main(string[] args)
    {
        try
        {

            // these variables should be changed to math your installation

            // find CSP's in this windows registry key:  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider
            string TokenCSPName = "Datakey RSA CSP";
            string TokenCertificateName = "ACME Inc";
            string NonTokenCertificateName = "SelfSigned";
            string certLocation = "Token"; // change to something else to use self signed "Token" for token
            // the certificate on the token should be installed into the local users certificate store
            // tokens will not store or export the private key, only the public key


            // find the certificate we want to use - there's no recovery if the certificate is not found

            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            store.Open(OpenFlags.OpenExistingOnly);
            X509Certificate2Collection certificates = store.Certificates;
            X509Certificate2 certificate = new X509Certificate2();
            X509Certificate2 useCertificate = new X509Certificate2();
            if (certLocation == "Token")
            {
                for (int i = 0; i < certificates.Count; i++)
                {
                    certificate = certificates[i];
                    string subj = certificate.Subject;
                    List<X509KeyUsageExtension> extensions = certificate.Extensions.OfType<X509KeyUsageExtension>().ToList();
                    if (certificate.GetNameInfo(X509NameType.SimpleName, false).ToString() == TokenCertificateName)
                    {
                        for (int j = 0; j < extensions.Count; j++)
                        {
                            if ((extensions[j].KeyUsages & X509KeyUsageFlags.DigitalSignature) == X509KeyUsageFlags.DigitalSignature)
                            {
                                useCertificate = certificate;
                                j = extensions.Count + 1;
                            }

                        }

                    }
                }
            } else
            {
                for (int i = 0; i < certificates.Count; i++)
                {
                    certificate = certificates[i];
                    string subj = certificate.Subject;
                    List<X509KeyUsageExtension> extensions = certificate.Extensions.OfType<X509KeyUsageExtension>().ToList();
                    if (certificate.GetNameInfo(X509NameType.SimpleName, false).ToString() == NonTokenCertificateName)
                        useCertificate = certificate;
                }

            }
            CspParameters csp = new CspParameters(1, TokenCSPName);

            csp.Flags = CspProviderFlags.UseDefaultKeyContainer;
            csp.KeyNumber = (int)KeyNumber.Exchange;
            RSACryptoServiceProvider rsa1 = new RSACryptoServiceProvider(csp);
            string SignatureString = "Data that is to be signed";
            byte[] plainTextBytes = Encoding.ASCII.GetBytes(SignatureString);
            bool Verified = false;
            using (SHA1CryptoServiceProvider shaM = new SHA1CryptoServiceProvider())
            {
                // hash the data to be signed - you can use signData and avoid the hashing if you like

                byte[] hash = shaM.ComputeHash(plainTextBytes);
                // sign the hash
                byte[] digitalSignature = rsa1.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
                // check your signature size here - if not 256 bytes then you may not be using the proper
                // crypto provider

                // Verify the signature with the hash

                RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)useCertificate.PublicKey.Key;
                Verified = rsa.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), digitalSignature);
                if (Verified)
                {
                    Console.WriteLine("Signature Verified");
                }
                else
                {
                    Console.WriteLine("Signature Failed Verification");
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
  }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Security.Cryptography.X509证书;
使用System.Security.Cryptography;
名称空间TE
{
班级计划
{
静态void Main(字符串[]参数)
{
尝试
{
//应更改这些变量以适应您的安装
//在此windows注册表项中查找CSP:HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider
字符串TokenCSPName=“Datakey RSA CSP”;
字符串TokenCertificateName=“ACME公司”;
字符串NonTokenCertificateName=“自签名”;
string certLocation=“Token”;//更改为其他内容以使用自签名的“Token”作为令牌
//令牌上的证书应安装到本地用户证书存储中
//令牌不会存储或导出私钥,而只存储或导出公钥
//找到我们要使用的证书-如果找不到证书,将无法恢复
X509Store=新的X509Store(StoreName.My,StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly);
X509Certificate2Collection certificates=存储证书;
X509Certificate2证书=新的X509Certificate2();
X509Certificate2 useCertificate=新的X509Certificate2();
如果(certLocation==“令牌”)
{
for(int i=0;i