我正在尝试使用CNG API和来自Microsoft证书存储区的证书向ECDSA签署文件。我已经通读了很多文档,并且接近完成,但我在从证书导入私钥时挂起了手。我用RSA做过同样的事情,但它的做法似乎截然不同。以下是我到目前为止拥有的代码:
static void signFile()
{
X509Certificate2 myCert =
selectCert(StoreName.My,
StoreLocation.CurrentUser,
"Select a Certificate",
"Please select a certificate from the list below:");
Console.Write("Path for file to sign: ");
string path = Console.ReadLine();
TextReader file = null;
try
{
file = new StreamReader(path);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.Write("\nPress any key to return to the main menu: ");
Console.ReadKey();
}
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(file.ReadToEnd());
ECDsaCng dsa = new ECDsaCng(
CngKey.Import(StringToByteArray(myCert.PrivateKey.ToString()),
CngKeyBlobFormat.EccPrivateBlob,
CngProvider.MicrosoftSoftwareKeyStorageProvider));
dsa.HashAlgorithm = CngAlgorithm.Sha384;
byte[] sig = dsa.SignData(data);
TextWriter signatureFile = new StreamWriter("signature.txt");
signatureFile.WriteLine("-----BEGIN SHA384 SIGNATURE-----" +
ByteArrayToString(sig) +
"-----END SHA384 SIGNATURE-----");
signatureFile.Close();
}
我得到了一个错误
System.NotSupportedException:不支持证书密钥算法。
我的证书是具有以下扩展名的ECDSA_P256 sha384ECDSA:
Digital Signature, Non-repudiation, independent signing revocation list (CRL), CRL Signing (CRL) (c2)
Server Authentication (1.3.6.1.5.5.7.3.1)
Client Authentication (1.3.6.1.5.5.7.3.2)
Code Signing (1.3.6.1.5.5.7.3.3)
Unknown Key Usage (1.3.6.1.4.1.311.2.1.22)
Unknown Key Usage (1.3.6.1.4.1.311.2.1.21)
IKE-intermediary IP-security (1.3.6.1.5.5.8.2.2)
看起来好像是证书出了问题,但我不确定是不是代码出了问题。
这是我的证书和公钥:
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 2 (0x2)
Signature Algorithm: ecdsa-with-SHA384
Issuer: C=##, O=#######, OU=#####, OU=#####, CN=###########
Validity
Not Before: Apr 27 16:35:51 2012 GMT
Not After : Apr 26 16:35:51 2017 GMT
Subject: C=##, O=###########, OU=#####, CN=#############
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:fc:d5:ce:ad:1f:0c:19:b9:3d:2b:bd:7d:f0:8c:
44:46:db:e3:42:14:b1:1a:9f:7c:ab:e1:be:ad:a5:
0c:03:2d:0f:ff:3f:10:d4:69:eb:4c:82:a1:2a:61:
56:45:03:04:a6:49:f7:16:6e:dd:60:22:c6:20:c5:
4d:44:49:21:41
ASN1 OID: prime256v1
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Non Repudiation, CRL Sign
X509v3 Extended Key Usage: critical
TLS Web Server Authentication, TLS Web Client Authentication, Co
de Signing, Microsoft Commercial Code Signing, Microsoft Individual Code Signing
, 1.3.6.1.5.5.8.2.2
X509v3 Authority Key Identifier:
DirName:/C=##/O=#######/OU=#####/OU=#####/CN=######
serial:01
X509v3 Subject Key Identifier:
B7:A8:F9:55:9A:43:9E:BE:1C:4B:62:52:91:C2:F1:39:72:E1:CE:1B
X509v3 Basic Constraints: critical
CA:FALSE
Signature Algorithm: ecdsa-with-SHA384
30:81:88:02:42:01:75:55:f3:64:f9:aa:2a:66:55:b1:ca:dc:
86:ac:1f:7d:2a:ec:10:87:db:74:88:0e:77:e3:18:82:15:a7:
32:91:1a:2d:ea:07:2e:78:8d:dc:8a:18:3c:2b:5a:9b:6a:0f:
97:f6:f8:8d:c5:fc:0e:9f:20:e9:b0:16:90:1a:c4:58:ac:02:
42:01:dc:b3:88:ae:44:54:c4:e0:b7:c2:37:88:0b:19:6b:96:
99:f7:21:12:45:12:21:e5:ab:83:39:a6:47:3a:08:87:b0:fa:
0e:31:1b:97:83:8d:65:30:a1:43:c1:82:27:77:6e:93:89:1b:
bd:57:b1:7a:54:9e:cc:e1:44:cc:74:16:c5
发布于 2014-03-28 03:36:48
我已经用X509证书与ECDsa和CngKey斗争了很长一段时间,也遇到了完全相同的问题。我们最终与ECDsa_P256 SHA256一起创建了我们自己的CngKeys,但我相信我在CryptoApi中学到了一些东西:
当您的证书标记为"Server Authentication (1.3.6.1.5.5.7.3.1)“(用作SSL证书)时,您的证书将包含密钥交换算法ECDH。而且不知何故,这“优先于”ECDsa算法组。因此,你得到了可怕的“证书密钥算法不受支持”。
我花了一个多小时与赛门铁克交流,他们无法解决这个难题,所以他们放弃了,说“对不起,我们不支持SSL以外的任何东西使用SSL证书”。
您可以使用CLRSecurity from Codeplex (http://clrsecurity.codeplex.com/)从证书中获取您的私有CngKey。这将为您的x509Certificate2提供一个允许以下代码的扩展:
X509Certificate cer = <getyourcertcode>;
CngKey k = cer.GetCngPrivateKey();
检查"k“,发现您的算法组可能不是预期的。我的是ECDH。
我现在尝试的解决方案是设置一个新的CA服务器,强制它做我想做的事情。基本上,这是一个仅用于代码签名的X509证书……
"X509v3密钥用法:关键数字签名“可能必须是唯一允许的用法...
希望这对其他人有帮助:-)
发布于 2016-08-19 22:53:26
.NET 4.6.1解决了这个问题的核心需求。新的代码将是
...
byte[] sig;
using (ECDsa ecdsa = cert.GetECDsaPrivateKey())
{
if (ecdsa == null) throw new Exception("Not an ECDSA cert, or has no private key");
sig = ecdsa.SignData(data, HashAlgorithmName.SHA384);
}
.NET 4.6.1还修复了一些证书密钥作为ECDH返回并因此失败的问题。(好吧,它没有解决一些私钥被认为是ECDH的问题--这与服务器身份验证EKU没有任何关系,但这是一个很好的猜测--但现在认为这些密钥是有效的)。
发布于 2012-08-23 01:03:55
如果您运行的是Windows Vista或Windows2008,则不支持CngKeyBlobFormat.EccPrivateBlob。您使用的是什么操作系统?CngKey.Import throws CryptographicException only on some machines
https://stackoverflow.com/questions/10490263
复制相似问题