Estoy intentando firmar un archivo con ECDSA utilizando la API de CNG y un certificado de la Tienda de certificados de Microsoft. He leído mucha documentación y casi terminado, pero me obsesiono con la importación de la clave privada del certificado. He hecho lo mismo con RSA, pero parece que se hace de manera muy diferente. Aquí está el código que tengo hasta ahora:Archivo de firma ECDSA con clave de la tienda C# .Net CNG
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();
}
Y me sale el error
System.NotSupportedException: No se admite el algoritmo de clave del certificado.
Mi certificado es ECDSA_P256 sha384ECDSA con las siguientes extensiones:
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)
Parecería como si el certificado era el problema, pero no estoy seguro de si podría ser el código o no.
Aquí está mi certificado con la clave pública:
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
Microsoft tiene bastante limitado el soporte de criptografía de curva elíptica (ECC). Solo proporciona "curva elíptica DSA (ECDSA) sobre las curvas primarias estándar NIST P-256, P-384 y P-521". y esas deberían ser curvas "nombradas". ¿Sabes qué parámetros de dominio de EC están en el certificado? Alternativamente, puede pegar el texto hexadecimal, base64 o ASN.1 del certificado para que podamos averiguarlo. –
Puede editar su pregunta en lugar de responder para proporcionar más información. Al volver a leer la pregunta, un certificado en sí mismo no contiene la clave privada. En general, usted crea un par de claves, crea una solicitud de certificado que contiene la clave pública y lo firma con la clave privada. Luego, la CA elabora un certificado y lo envía de regreso. Ese certificado solo contiene la clave pública. Entonces, cuando intenta importar la clave privada, ¿en qué formato es? PKCS # 12? Eso sería extensiones de archivo '.pkf' o' .p12'. –
Ah, veo dónde te equivocas, debería haberme puesto las gafas. ToString no codifica la clave privada. Simplemente imprime algo de información en la clave privada. Puede usar el 'DSACryptoServiceProvider' que la propiedad PrivateKey realmente extiende en lugar de codificar/volver a codificar la clave privada. –