2016-04-14 42 views
3

ECDSA kullanarak özel anahtarlı (kendinden imzalı) sertifika oluşturmaya çalışıyorum. gol openssl kullanırken olarak "aynı" (pkcs12) sertifikası elde etmektir:ECDSA kullanarak sertifika oluştur C#

openssl ecparam -genkey -name secp256r1 -out mykey.key 
openssl req -new -key mykey.key -out myreq.csr 
openssl req -x509 -days 7 -key mykey.key -in myreq.csr -out mycert.crt 
openssl pkcs12 -export -out mycert.pfx -inkey mykey.key -in mycert.crt 
Zaten az çok takip RSA tabanlı sertifika (lar) oluşturma ile öylesine sonraki adımları bana yardım BouncyCastle kullanmak

RSA certs oluşturmak için kullanıyorum.

BC.IAsymmetricCipherKeyPairGenerator bcKpGen = BC.GeneratorUtilities.GetKeyPairGenerator("ECDSA"); 
bcKpGen.Init(new BC.ECKeyGenerationParameters(BC.SecObjectIdentifiers.SecP256r1, new BC.SecureRandom())); 
BC.AsymmetricCipherKeyPair bcSubjKeys = bcKpGen.GenerateKeyPair(); 

kullanımı özel anahtar, kamu ve özel anahtarlar:

anahtar çifti oluşturmak (BC önek NET sınıfları için BouncyCastle, MS gelen sınıfları için kullanılan dikkat edin) bazı ek verilerle genel anahtarı imzalamak için (konu, geçerlilik süresi vb.)

BC.X509V3CertificateGenerator bcXgen = new BC.X509V3CertificateGenerator(); 
// .. set subject, validity period etc 
bcXgen.SetPublicKey(bcSubjKeys.Public); 
BC.ISignatureFactory bcSigFac = new BC.Asn1SignatureFactory("SHA256WITHECDSA", bcSubjKeys.Private); 
BC.X509Certificate bcCert = bcXgen.Generate(bcSigFac); 

Özel anahtarla sertifika almak için adım 1'den özel anahtarı ve adım 2'den sertifikaya katılın. Ben özel anahtar olmadan sertifika ile ok isem

, şöyle bir şey yapabilirsiniz:

MS.X509Certificate mcCert = new MS.X509Certificate2(bcCert.GetEncoded(), null); 

ve ben bittim.

msCert.PrivateKey = ConvertBouncyToNetSomehow(bcSubjKeys.Private) 

uygun bir yol gibi görünüyor

(typeof msCert.PrivateKeyMS.AsymmetricAlgorithm ve bcSubjKeys.Private tipi BC.ECPrivateKeyParameters olduğuna dikkat edin): Özel anahtar ayarları yapmaya çalışırken

sorun (lar) gelip

tek yolu ettiğini göstermiştir: MS.ECDsaCng (MS.AsymmetricAlgorithm devralan) sınıfı, fakat ound pkcs8 biçimi aracılığıyla BC.ECPrivateKeyParameters (MS.ECDsaCng tarafından gerekli) MS.CngKey etmektir dönüştürmek için:

BC.PrivateKeyInfo bcPKInfo = BC.PrivateKeyInfoFactory.CreatePrivateKeyInfo(bcSubjKeys.Private); 
byte[] pkArr = bcPKInfo.GetDerEncoded(); 
MS.CngKey msPKCng = MS.CngKey.Import(pkArr, MS.CngKeyBlobFormat.Pkcs8PrivateBlob); 

ama bcSubjKeys.Private.AlgorithmName"ECDSA" diyor ederken bazı bilgiler kaybolur bu yaklaşımı kullanarak msPKCng.AlgorithmGroup değeri "ECDH" çünkü. Ayrıca ECDH anahtarı MS.ECDsaCng ile kullanılamaz.

Yine .. ben MS.X509Certificate2.set_PrivateKey ait

uygulama nesne arayüzü MS.ICspAsymmetricAlgorithm uygulayan gerektirir .. MS.ECDiffieHellmanCng devam yerine MS.ECDsaCng eğer talep olabilir. Ancak bunlardan hiçbiri (ECDsaCng, ECDiffieHellmanCng) onu uygulamamaktadır. Farklı bir yaklaşım görünen bu noktada

, örneğin (nedeniyle MS.ICspAsymmetricAlgorithm durumun) kullanılmalıdır ihracat sertifikası ve özel anahtar pkcs dosyasına ve X509Certificate2.Import(..) kullanın.

Herhangi bir ipucu? Saygılar

cevap

4

Maalesef şu anda kutudan doğrudan çıkmak mümkün değil. Yolun geri kalanını P/Invokes ve .NET 4.6.2 (şu anda önizlemede) ile alabilirsiniz. Veya .NET Core aracılığıyla bir sapma ile .NET 4.6.1'de çalışan bir PFX oluşturabilirsiniz. "ECDH"

CNG, Windows kütüphaneler vs

"ECDSA" ECDSA ve ECDH içine ECC bölün. ECDSA anahtar nesneleri sadece ECDSA için kullanılabilir; ancak Windows, bir PFX içe aktarma (veya PKCS # 8 içe aktarma) sırasında kullanımı belirleyemediğinde, özel bir anahtar ECDH çağırır. Niye ya? Windows, ECDH anahtar nesnelerinin hem anahtar anlaşmasını (ECDH) hem de dijital imzayı (ECDSA) yapmasını sağladığından ECDH daha esnektir.

Ancak .NET 4.6.1 bunu bilmiyordu.

.NET Core bu kısıtlamaya sahip değil (bkz. https://github.com/dotnet/corefx/pull/5850) ve .NET 4.6.2 de kısıtlamayı kaldırdı(). yerine "ECDH" nin

Yaratma "ECDSA" tuşları,

NET Çekirdek şimdi ECDSA bir ImportParameters yöntemi vardır. BC.ECPrivateKeyProperty nesnesini bir MS.ECParameters yapısına çevirebilirseniz, bloğu bir ECDsaCng nesnesine alabilirsiniz. (Tüm eğri parametrelerini açıkça kopyalamak yerine, onu adlandırılmış eğri olarak kullandığınızdan emin olun). Bir ECDsa nesnesine kasıtlı olarak aktarıldığından, bir ECDSA anahtarı alır ve bu bilgi PFX'e gömülecektir. PFX'i Bina

Eğer geçici bir anahtarı kullanarak bir PFX'i inşa etmek Windows'u ikna edebilir çağırma/P ile biraz

(Hepsini bir araya bağlama). Sen sahip olmak .NET 4.6.1 (veya daha yeni) gerekir

[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] 
private static extern unsafe bool CertSetCertificateContextProperty(IntPtr pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, SafeNCryptKeyHandle pvData); 

internal enum CertContextPropId : int 
{ 
    CERT_NCRYPT_KEY_HANDLE_PROP_ID = 78, 
} 

[Flags] 
internal enum CertSetPropertyFlags : int 
{ 
    None = 0, 
} 

private static X509Certificate2 MateECDsaPrivateKey(
    X509Certificate2 cert, 
    CngKey privateKey) 
{ 
    // Make a new certificate instance which isn't tied to the current one 
    using (var tmpCert = new X509Certificate2(cert.RawData)) 
    { 
     SafeNCryptKeyHandle keyHandle = privateKey.Handle; 

     // Set the ephemeral key handle property 
     if (!CertSetCertificateContextProperty(
      tmpCert.Handle, 
      CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID, 
      CertSetPropertyFlags.None, 
      keyHandle)) 
     { 
      throw new CryptographicException(Marshal.GetLastWin32Error()); 
     } 

     // You could emit this, if you prefer. 
     byte[] pfxBytes = tmpCert.Export(X509ContentType.Pkcs12); 

     // Clear the key handle out again to prevent double-free 
     keyHandle = new SafeNCryptKeyHandle(); 

     if (!CertSetCertificateContextProperty(
      tmpCert.Handle, 
      CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID, 
      CertSetPropertyFlags.None, 
      keyHandle)) 
     { 
      throw new CryptographicException(Marshal.GetLastWin32Error()); 
     } 

     // Now load a new certificate which has a temporary keyfile on disk. 
     // Note: If you don't want exportability here, don't request it. 
     var matedCert = new X509Certificate2(pfxBytes, (string)null, X509KeyStorageFlags.Exportable); 

     using (ECDsa ecdsa = matedCert.GetECDsaPrivateKey()) 
     { 
      if (ecdsa == null) 
      { 
       throw new InvalidOperationException("It didn't work"); 
      } 
     } 

     return matedCert; 
    } 
} 

: .NET sertifikalarından kısa ömürlü özel anahtarlara erişmek edemesek bir pfx yüklenen, eğer bunu kullanmak mümkün olacak GetECDsaPrivateKey() öğesine erişim.

+0

İşe yaramadı :-(Herhangi bir ipucu? @bartonjs Çalıştığınız bir örnek var .net 4.6.1/2 –

+0

@DanielFisherlennybacon Bir & hata (ve bir çift yazım hatası) vardı gibi görünüyor. Geçerli bir geçerli Geçerli bir cert blob ait PKCS8 blob, https://gist.github.com/bartonjs/fac9ea9108dd184a7a66be77f0af3fef benim için çalıştı – bartonjs

+0

Bir göz atacağım.Şimdiden teşekkürler! –

İlgili konular