2012-05-07 11 views
19

Tôi đang cố ký một tệp với ECDSA bằng API CNG và chứng chỉ từ Cửa hàng chứng chỉ Microsoft. Tôi đã đọc qua rất nhiều tài liệu và gần xong nhưng tôi bị treo lên khi nhập khóa riêng tư từ chứng chỉ. Tôi đã làm điều này rất giống với RSA nhưng nó dường như được thực hiện rất khác nhau. Dưới đây là đoạn code tôi có cho đến nay:Tệp ký kết ECDSA có khóa từ cửa hàng 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(); 
    } 

Và tôi nhận được lỗi

System.NotSupportedException: Giấy chứng nhận thuật toán quan trọng không được hỗ trợ.

giấy chứng nhận của tôi là ECDSA_P256 sha384ECDSA với các phần mở rộng sau:

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) 

Nó sẽ xuất hiện như là nếu giấy chứng nhận là vấn đề nhưng tôi không chắc chắn nếu nó có thể là mã hay không.


Dưới đây là giấy chứng nhận của tôi với khóa công khai:

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 
+0

Microsoft có hỗ trợ mã hóa đường cong Elliptic Curve (ECC) rất hạn chế. Nó chỉ cung cấp "đường cong elliptic DSA (ECDSA) qua các đường chuẩn chuẩn NIST P-256, P-384 và P-521." và những đường này nên được đặt tên là "đường cong". Bạn có biết thông số tên miền EC nào trong chứng chỉ không? Hoặc bạn có thể dán văn bản thập lục phân, base64 hoặc ASN.1 của chứng chỉ để chúng tôi có thể tìm ra. –

+0

Bạn có thể chỉnh sửa câu hỏi của mình thay vì trả lời để cung cấp thêm thông tin. Đọc lại câu hỏi, bản thân chứng chỉ không chứa khóa cá nhân. Nói chung, bạn tạo một cặp khóa, tạo một yêu cầu chứng chỉ chứa khóa công khai và ký rằng với khóa riêng. Sau đó, CA sẽ lấy một chứng chỉ từ nó và gửi lại. Chứng chỉ đó chỉ chứa khóa công cộng. Vì vậy, khi bạn cố gắng nhập khóa riêng tư, ở định dạng nào? PKCS # 12? Đó sẽ là phần mở rộng tệp '.pkf' hoặc' .p12'. –

+0

Ah, tôi thấy nơi bạn đi sai, nên đặt kính của tôi vào. ToString không mã hóa khóa riêng. Nó chỉ đơn giản là in một số thông tin về khóa riêng. Bạn có thể sử dụng 'DSACryptoServiceProvider' mà thuộc tính PrivateKey thực sự mở rộng thay vì mã hóa/reencoding khóa riêng. –

Trả lời

2

Nếu bạn đang chạy Windows Vista hoặc Windows 2008, CngKeyBlobFormat.EccPrivateBlob không được hỗ trợ. Bạn đang sử dụng hệ điều hành nào? CngKey.Import throws CryptographicException only on some machines

+1

Tôi đã sử dụng Windows 7 nhưng bây giờ tôi đã "nâng cấp" lên 8. –

+0

Ok, bạn có thể bỏ qua câu trả lời của tôi vì vấn đề đó sẽ không xảy ra trong Windows 7, và có lẽ nó cũng sẽ không xảy ra trong Windows 8. – Anssssss

5

Tôi đã chiến đấu ECDsa và CngKey với chứng chỉ X509 trong một thời gian dài và có cùng vấn đề tương tự. Chúng tôi đã tạo ra CngKey của riêng mình với ECDsa_P256 SHA256, nhưng tôi tin rằng tôi đã học được điều gì đó đào sâu vào CryptoApi:

Khi bạn có chứng chỉ được đánh dấu là "Xác thực máy chủ (1.3.6.1.5.5.7.3.1)) "(sử dụng như chứng chỉ SSL), chứng chỉ của bạn sẽ chứa thuật toán trao đổi khóa ECDH. Và bằng cách nào đó điều này "được ưu tiên" trong nhóm thuật toán ECDsa. Vì vậy, bạn nhận được sợ hãi "Thuật toán khóa chứng chỉ không được hỗ trợ".

Tôi đã dành hơn một giờ với Symantec nhìn qua vai tôi và họ không thể giải quyết câu đố, vì vậy họ đã từ bỏ "Rất tiếc, chúng tôi không hỗ trợ sử dụng SSL certs cho bất kỳ thứ gì ngoài SSL".

Bạn có thể lấy CngKey riêng của mình từ cert với CLRSecurity từ Codeplex (http://clrsecurity.codeplex.com/). Điều này cung cấp cho bạn một tiện ích mở rộng cho phép mã này:

X509Certificate cer = <getyourcertcode>; 
CngKey k = cer.GetCngPrivateKey(); 

Kiểm tra "k" và xem nhóm thuật toán của bạn có thể khác với dự kiến. Tôi là ECDH ...

Giải pháp Tôi đang cố gắng bây giờ là thiết lập một máy chủ CA mới buộc nó phải làm chính xác những gì tôi muốn. Về cơ bản đó sẽ là một cert X509 được CHỈ dùng để ký mã ...

"Key Usage X509v3: quan trọng Digital Signature" có thể phải được phép sử dụng CHỈ ...

Hy vọng điều này sẽ giúp người khác ngoài đó :-)

+0

Bạn làm cách nào để tạo CngKey từ một khóa công khai? Thư viện CLRSecurity đó dường như không cung cấp phần mở rộng 'GetCngPublicKey()'. Làm cách nào tôi có thể xác minh chữ ký ECDsa bằng khóa công khai của người ký trong X509Certificate trong cửa hàng cert? –

+0

Hãy xem câu trả lời của tôi ở đây: http://stackoverflow.com/questions/10264770/creating-an-ecc-private-public-key-with-native-c-sharp/22637599#22637599. Xác minh như thế này: sử dụng (ECDsaCng ecsdKey = new ECDsaCng (CngKey.Import (khóa, CngKeyBlobFormat.EccPublicBlob))) { nếu (ecsdKey.VerifyData (dữ liệu, chữ ký)) Console.WriteLine ("Dữ liệu tốt"); else Console.WriteLine ("Dữ liệu xấu"); } –

+0

Câu trả lời của bạn dường như không liên quan gì đến X509Certificates trong cửa hàng cert? –

2

.NET 4.6.1 giải quyết các nhu cầu cốt lõi của vấn đề này.Mã mới sẽ là

... 
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 cũng khắc phục sự cố trong đó một số khóa cert trở lại dưới dạng ECDH và do đó không thành công. (Vâng, nó không giải quyết được vấn đề của một số khóa riêng tư được coi là ECDH - mà không có gì liên quan đến Server Auth EKU, nhưng là một dự đoán tốt - nhưng xem xét các khóa đó có hiệu lực ngay bây giờ).

Các vấn đề liên quan