Я думаю, что здесь что-то не хватает, но как отправить клиентские сертификаты на сайт SSL, для которого требуется сертификат клиента.
Я использую HttpClient и передаю AndroidClientHandler
Есть много ответов, которые содержат код, но не говорят мне, почему он работает или когда его следует вызывать. Я потратил на это больше недели.
Может ли кто-нибудь просто предоставить простой пример кода и простое объяснение, почему это должно быть сделано именно так.
Я использую самоподписанные сертификаты. Мне удалось проигнорировать любую проверку сертификата, и я могу вызвать на сайт SSL, когда он настроен так, чтобы не требовать сертификат клиента.
Но теперь мне нужно знать, как передать сертификат клиента.
Я просмотрел много статей и решений, но не вижу, куда передается сертификат клиента.
Любая помощь будет оценена. Спасибо
Глядя на это, он упоминает самоподписанный сертификат. Они говорят о сертификате SSL в веб-приложении или о сертификате клиента? В статье снова неясно, зачем мне это нужно, я хочу понять принципы, а не просто копировать код в свое приложение. К сожалению, на данный момент все, что у меня есть, это самоподписанные сертификаты, поэтому я застрял в этой ситуации.
Я прихожу к выводу, что вы не можете использовать Xamarin HttpClient и AndroidClientHandler для отправки клиентских сертификатов в запросе HTTPS. Кто-нибудь может подтвердить?
Я могу подтвердить, что если вы используете AndroidClientHandler, то System.Net.ServicePointManager.ServerCertificateValidationCa llback никогда не будет вызван. Если вам нужно установить и использовать этот обратный вызов, вы должны использовать управляемый обработчик HttpClient.
Привет, @jgoldberger, не совсем понимаю, что ты имеешь в виду. Как это связано с использованием Xamarin HttpClient и AndroidClientHandler для отправки клиентских сертификатов в запросе HTTPS
В примерах 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;
}
}
Это отлично работает для меня. Мне также удалось добавить сертификат клиента из хранилища ключей учетных данных пользователя.
Возможно, попробуйте то, что написано в этом блоге: dotnetdevaddict.co.za/2015/07/31/…. Обычно рекомендуется не использовать самоподписанные сертификаты, поскольку официальные сертификаты, выпущенные центром сертификации, дешевы или бесплатны. Самоподписанные сертификаты усложняют ситуацию.