Загрузить ключи сертификата в класс CngKey для использования с DiffieHellman (класс ECDiffieHellmanCng)

Это связано с .NET / C #. Предположим, что внутри файла PFX или PKCS # 12 есть сертификат + закрытый ключ (P521 ECC). Мы загрузили этот сертификат и его закрытый ключ в хранилище сертификатов Windows, установив его (либо дважды щелкнув PFX, либо запустив certutil -f -p myPfxPassword -importPFX MY SomeEcCert.pfx). Я заметил, что если сертификат совместим (например, кривая p521), он автоматически устанавливается как сертификат / ключ CNG.

Теперь, как мне загрузить закрытый ключ в CngKey, чтобы затем использовать его внутри класса ECDiffieHellmanCng? Я также хотел бы загрузить сертификат X509 (CNG), чтобы прочитать его серийный номер, эмитент, общее имя и т. Д. Для некоторой бухгалтерии.

var myCngKey = SomehowLoadTheCngKey("my ecc certificate"); // <== ??
var myDH = new ECDiffieHellmanCng(myCngKey);

person DeepSpace101    schedule 29.07.2013    source источник


Ответы (1)


Что ж, у .NET нет хорошего API для CNG. Если вы даже поцарапаете поверхность их API, вы сразу увидите, что это немного смешно, особенно учитывая, что оба они от Microsoft, а CNG - самый серьезный из всех Crypto API на всей платформе Windows.

Поэтому вам нужно использовать CLRSecurity, который предоставляет интерфейсы C # (через P / Invoke) в C ++ CNG API. Даже с учетом этого, это не самый лучший дизайн API; но это помогает.

// Load the cert, many ways, one implementation
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
var certs = store.Certificates.Find(X509FindType.FindBySubjectName, "My cert subject name", true);
store.Close();

if (certs.Count > 0)
    cert = certs[0];
else
    return;

// Magic happens here! We load the private CngKey (if it exists)
// You need CLR Security for this, it manages the P/Invoke
// into the C++ api behind the scenes. 
var pvtCngKey = cert.GetCngPrivateKey(); 

// Create the DiffieHellman helper
var ecDh = new ECDiffieHellmanCng(ourPvtEcCngKey)
{
   KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash,
   HashAlgorithm = CngAlgorithm.Sha256
};

ECDiffieHellmanCngPublicKey theirPubCngKey = LoadOtherPartiesCngPublicKey(theirCert);
byte[] symKey = ecDh.DeriveKeyMaterial(theirPubCngKey);
person DeepSpace101    schedule 05.02.2014
comment
А как выглядит реализация LoadOtherPartiesCngPublicKey(theirCert)? - person Dan Turner; 28.03.2014
comment
Обратите внимание, что CLRSecurity доступен через NuGet для .NET Framework: Security.Cryptography. - person Christian Davén; 05.02.2021