密码学:为什么我获取的RSA签名因证书存储不同而有所不同?

9
我有一些可行的代码,如果我从文件或当前用户存储中加载证书,则可以生成正确的字符串签名。然而,如果我从机器证书存储中加载完全相同的证书(相同的.p12和相同的指纹),则会出现不同的行为。当从该存储中加载时,C#代码生成的签名长度为原来的一半(1024位而不是2048位),并且是不正确的。在两种情况下,私钥似乎都能够正确加载。
为什么证书从哪个存储加载会影响生成的签名?为什么签名的长度会减半? 从CurrentUser加载:
Thumbprint: FBBE05A1C5F2AEF637CDE20A7985CD1011861651
Has private key:True
rsa.KeySize (bits) =2048
Signature Length (bits): 2048
Signature: kBC2yh0WCo/AU8aVo+VUbRoh67aIJ7SWM4dRMkNvt...

(正确)

从本机加载:

Thumbprint: FBBE05A1C5F2AEF637CDE20A7985CD1011861651
Has private key: True
rsa.KeySize (bits) = 1024
Signature Length (bits): 1024
Signature: RijmdQ73DXHK1IUYkOzov2R+WRdHW8tLqsH....

(不正确的 - 注意1024位密钥大小和签名长度)

这是我正在使用的C#代码:

        string s = "AE0DE01564,1484821101811,http://localhost:8080/example_site/CallBack";

        var inputData = Encoding.UTF8.GetBytes(s);

        var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

        string thumbprint = CleanThumbPrint("fb be 05 a1 c5 f2 ae f6 37 cd e2 0a 79 85 cd 10 11 86 16 51");
        X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);

        // TODO: close store.
        X509Certificate2 certificate = null;

        Console.WriteLine("Cert count: " + col.Count);
        if (col.Count == 1)
        {
            certificate = col[0];
            RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)col[0].PrivateKey;

            // Force use of the Enhanced RSA and AES Cryptographic Provider with openssl-generated SHA256 keys
            var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;

            var cspparams = new CspParameters(enhCsp.ProviderType, enhCsp.ProviderName, rsa.CspKeyContainerInfo.KeyContainerName);

            rsa = new RSACryptoServiceProvider( cspparams);
            Console.WriteLine("Name: " + certificate.SubjectName.Name);
            Console.WriteLine("Thumbprint: " + certificate.Thumbprint);
            Console.WriteLine("Has private key: " + certificate.HasPrivateKey);
            Console.WriteLine("Sig algorithm: " + certificate.SignatureAlgorithm);
            Console.WriteLine("rsa.KeySize (bits) =" + rsa.KeySize);

            var sha256 = CryptoConfig.CreateFromName("SHA256");
            byte[] signature = rsa.SignData(inputData, sha256);

            Console.WriteLine("Signature Length (bits): " + signature.Length * 8);
            Console.WriteLine("Signature: " + System.Convert.ToBase64String(signature));
            Console.WriteLine();
      }

1
你能检查一下返回证书的发行者和序列号吗? - Maarten Bodewes
@MaartenBodewes 发行者和序列号相同。 - NickG
我能想到的唯一可能是私钥与证书不匹配。也许P12没有正确生成。我几乎无法想象Microsoft的证书存储不正确(另一方面,微软以前曾令我惊讶过)。 - Maarten Bodewes
我已经更新了我的帖子,因为在重新初始化RSA对象之前,我输出了一些调试行。现在,当我从机器存储中加载它时,我获得了1024位RSA密钥大小。 - NickG
也许你遇到了编码和解码相关的问题,可以看看Base64。 https://dev59.com/5mox5IYBdhLWcg3wTytx - Skyware
1个回答

4
原来问题出在我使用OpenSSL创建证书时的文件格式而加密提供程序未设置。以下是关键步骤命令:
这是我用来创建可用证书的命令:
1. 生成密钥对:
openssl genrsa -out private_key.pem 2048
2. 提取公钥:
openssl rsa -pubout -in private_key.pem -out public_key.pem
3. 从私钥创建证书签名请求:
openssl req -new -key private_key.pem -out csr.csr 4. 生成自签名证书:
openssl x509 -req -days 1095 -in csr.csr -signkey private_key.pem -out certificate.crt
5. 使用指定的CSP创建PFX格式证书:
openssl pkcs12 -export -in certificate.crt -inkey private_key.pem -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" -out TEST_pfx.pfx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接