Как получить PrivateKey для X509Certificate2 с oid отличается от 1.2.840 ....? - PullRequest
0 голосов
/ 30 сентября 2019

Я создал самозаверяющий сертификат с помощью команды приглашения

csptest -keyset -newkeyset -makecert -container test3 -keytype exchange

Затем я установил его с помощью стороннего приложения. Когда я пытаюсь получить сертификат PrivateKey в основном приложении asp.net, он выдает NotSupportedException.

var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
certificates = store1.Certificates;
var certificate = GetCertificateByThumbprint(certificates, "51F9748FE7DDE895DD100AAD0BE54C1ACF6B4DCC");

if (certificate.HasPrivateKey)
{
    var kayAlgorithm = = _certificate.GetKeyAlgorithm(); // same as certificate.PublicKey.Oid.Value;
    var rsaPrivateKey = certificate.GetRSAPrivateKey();
    var dsaPrivateKey = _certificate.GetDSAPrivateKey();
    var ecdsaPrivateKey = _certificate.GetECDsaPrivateKey();
    var privateKey = certificate.PrivateKey;
}

HasPrivateKey, возвращает true. GetRSAPrivateKey, GetDSAPrivateKey и GetECDsaPrivateKey возвращают ноль. Однако GetKeyAlgorithm (oid.value) возвращает «1.2.643.7.1.1.1.1». Я углубился в библиотеку System.Security.Cryptography.X509Certificates.X509Certificate2 и обнаружил там жестко закодированную проверку только для алгоритмов "1.2.840.113549.1.1.1" или "1.2.840.10040.4.1".

public AsymmetricAlgorithm PrivateKey
{
  get
  {
    this.ThrowIfInvalid();
    if (!this.HasPrivateKey)
      return (AsymmetricAlgorithm) null;
    if (this._lazyPrivateKey == null)
    {
      string keyAlgorithm = this.GetKeyAlgorithm();
      if (!(keyAlgorithm == "1.2.840.113549.1.1.1"))
      {
        if (!(keyAlgorithm == "1.2.840.10040.4.1"))
          throw new NotSupportedException(SR.NotSupported_KeyAlgorithm);
        this._lazyPrivateKey = (AsymmetricAlgorithm) this.Pal.GetDSAPrivateKey();
      }
      else
        this._lazyPrivateKey = (AsymmetricAlgorithm) this.Pal.GetRSAPrivateKey();
    }
    return this._lazyPrivateKey;
  }
  set
  {
    throw new PlatformNotSupportedException();
  }
}

В .net framework получается PrivateKey выдает то же исключение. System.Security.Cryptography.X509Certificates.X509Certificate2 выглядит иначе.

public AsymmetricAlgorithm PrivateKey
{
  get
  {
    if (!this.HasPrivateKey)
      return (AsymmetricAlgorithm) null;
    if (this.m_privateKey == null)
    {
      CspParameters parameters = new CspParameters();
      if (!X509Certificate2.GetPrivateKeyInfo(this.m_safeCertContext, ref parameters))
        return (AsymmetricAlgorithm) null;
      parameters.Flags |= CspProviderFlags.UseExistingKey;
      switch (this.PublicKey.AlgorithmId)
      {
        case 8704:
          this.m_privateKey = (AsymmetricAlgorithm) new DSACryptoServiceProvider(parameters);
          break;
        case 9216:
        case 41984:
          this.m_privateKey = (AsymmetricAlgorithm) new RSACryptoServiceProvider(parameters);
          break;
        default:
          throw new NotSupportedException(SR.GetString("NotSupported_KeyAlgorithm"));
      }
    }
    return this.m_privateKey;
  }
  set
  {
    ...
  }
}

Итак, как я могу получить PrivateKey для другого алгоритма или я что-то не так сделал раньше?

GetCertificateByThumbprint исходный код метода только вкейс. (Я не смог использовать метод X509Certificate2Collection.Find, поскольку он не возвращает мой сертификат, поскольку он недействителен)

private X509Certificate2 GetCertificateByThumbprint(X509Certificate2Collection certifcates, string thumbprint)
    {
        foreach (var certificate in certifcates)
        {
            if (certificate.Thumbprint == thumbprint)
                return certificate;
        }
    }

1 Ответ

0 голосов
/ 09 октября 2019

Так как .NET не имеет представления GOST, на самом деле нет ничего полезного, что свойство PrivateKey могло бы вернуть (если оно еще не было эффективно объявлено устаревшим).

Из объекта X509Certificate2 вы можете прочитать Handle свойство для получения значения базовой ОС (PCERT_CONTEXT в Windows). Затем вы можете использовать это для P / Invoke в функции ОС, например CryptAcquireCertificatePrivateKey . Предполагая, что GOST CSP зарегистрирован в Windows, эта функция должна успешно вернуть обратно дескриптор ключа CAPI или CNG (как определено возвратом dwKeySpec), который затем необходимо будет продолжить использовать с P / Invokes (возможно, через класс GOST). ты заставляешь это управлять).

...