Xamarin AndroidClientHandler отправка сертификата клиента

Я думаю, что здесь что-то не хватает, но как отправить клиентские сертификаты на сайт SSL, для которого требуется сертификат клиента.

Я использую HttpClient и передаю AndroidClientHandler

Есть много ответов, которые содержат код, но не говорят мне, почему он работает или когда его следует вызывать. Я потратил на это больше недели.

Может ли кто-нибудь просто предоставить простой пример кода и простое объяснение, почему это должно быть сделано именно так.

Я использую самоподписанные сертификаты. Мне удалось проигнорировать любую проверку сертификата, и я могу вызвать на сайт SSL, когда он настроен так, чтобы не требовать сертификат клиента.

Но теперь мне нужно знать, как передать сертификат клиента.

Я просмотрел много статей и решений, но не вижу, куда передается сертификат клиента.

Любая помощь будет оценена. Спасибо

Возможно, попробуйте то, что написано в этом блоге: dotnetdevaddict.co.za/2015/07/31/…. Обычно рекомендуется не использовать самоподписанные сертификаты, поскольку официальные сертификаты, выпущенные центром сертификации, дешевы или бесплатны. Самоподписанные сертификаты усложняют ситуацию.

jgoldberger - MSFT 29.11.2018 22:16

Глядя на это, он упоминает самоподписанный сертификат. Они говорят о сертификате SSL в веб-приложении или о сертификате клиента? В статье снова неясно, зачем мне это нужно, я хочу понять принципы, а не просто копировать код в свое приложение. К сожалению, на данный момент все, что у меня есть, это самоподписанные сертификаты, поэтому я застрял в этой ситуации.

rideintothesun 30.11.2018 12:07

Я прихожу к выводу, что вы не можете использовать Xamarin HttpClient и AndroidClientHandler для отправки клиентских сертификатов в запросе HTTPS. Кто-нибудь может подтвердить?

rideintothesun 04.12.2018 17:35

Я могу подтвердить, что если вы используете AndroidClientHandler, то System.Net.ServicePointManager.ServerCertificateValidationCa‌ llback никогда не будет вызван. Если вам нужно установить и использовать этот обратный вызов, вы должны использовать управляемый обработчик HttpClient.

jgoldberger - MSFT 04.12.2018 20:52

Привет, @jgoldberger, не совсем понимаю, что ты имеешь в виду. Как это связано с использованием Xamarin HttpClient и AndroidClientHandler для отправки клиентских сертификатов в запросе HTTPS

rideintothesun 05.12.2018 21:08
2
5
378
1

Ответы 1

В примерах Xamarin, которые я видел, не учитывается добавление IPrivateKey в KeyStore, который используется для заполнения KeyManagerFactory.

/// <summary>
/// Represents a Java X509Certificate with private key
/// </summary>
public class CertificateDetails
{
    public CertificateDetails(IPrivateKey privateKey, X509Certificate[] chain)
    {
        PrivateKey = privateKey;
        Chain = chain;
    }

    /// <summary>
    /// Gets the private key
    /// </summary>
    public IPrivateKey PrivateKey { get; }

    /// <summary>
    /// Gets certificate chain
    /// </summary>
    public IReadOnlyCollection<X509Certificate> Chain { get; }
}


/// <summary>
/// HttpClientHandler based on native Android  <see cref = "Java.Net.HttpURLConnection"/> that uses a client certificate
/// </summary>
public class AuthAndroidClientHander : AndroidClientHandler
{
    readonly CertificateDetails _certificateDetails;

    public AuthAndroidClientHander(CertificateDetails certificateDetails)
    {
        if (certificateDetails is null)
        {
            throw new ArgumentNullException(nameof(certificateDetails));
        }
        _certificateDetails = certificateDetails;

        //get root certs
        var trustManagerFactory = TrustManagerFactory.GetInstance(TrustManagerFactory.DefaultAlgorithm);
        trustManagerFactory.Init((KeyStore)null);
        var x509trustManager = trustManagerFactory.GetTrustManagers().OfType<IX509TrustManager>().First();
        var acceptedIssuers = x509trustManager.GetAcceptedIssuers();

        //trust both default issuers and chain of client certifiate
        TrustedCerts = _certificateDetails.Chain.Concat(acceptedIssuers).ToList<Certificate>();
    }

    /// <summary>
    /// Configure keyStore passed into <see cref = "AndroidClientHandler.ConfigureKeyManagerFactory"/> and <see cref = "AndroidClientHandler.ConfigureTrustManagerFactory"/>
    /// </summary>
    /// <param name = "keyStore"></param>
    /// <returns></returns>
    protected override KeyStore ConfigureKeyStore(KeyStore keyStore)
    {
        // replace keyStore generated by base class with a PKCS12 instead of the default KeyStore.DefaultType
        keyStore = KeyStore.GetInstance("PKCS12");

        //replicate base's SetupSSL() behavior of adding all TrustedCerts to keystore in  
        keyStore.Load(null, null);

        if (TrustedCerts?.Any() == true)
        {

            for (var i = 0; i < TrustedCerts.Count; i++)
            {

                Certificate cert = TrustedCerts[i];
                if (cert == null)
                {
                    continue;
                }
                keyStore.SetCertificateEntry($"ca{i}", cert);

            }

        }

        //add private key to keystore
        keyStore.SetKeyEntry("privateKey", _certificateDetails.PrivateKey, null, _certificateDetails.Chain.ToArray());

        return keyStore;
    }

    protected override KeyManagerFactory ConfigureKeyManagerFactory(KeyStore keyStore)
    {
        var kmf = KeyManagerFactory.GetInstance("x509");
        kmf.Init(keyStore, null);
        return kmf;
    }

    protected override TrustManagerFactory ConfigureTrustManagerFactory(KeyStore keyStore)
    {
        var tmf = TrustManagerFactory.GetInstance(TrustManagerFactory.DefaultAlgorithm);
        tmf.Init(keyStore);
        return tmf;
    }
}

Это отлично работает для меня. Мне также удалось добавить сертификат клиента из хранилища ключей учетных данных пользователя.

RnDrx 19.04.2021 18:29

Другие вопросы по теме