Сертификат клиента не работает с Android - как отладить?

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

Я следил за кодом и кодом из этого сообщения в блоге , описывающий тот же сценарий, более или менее безрезультатно.

Что не работает: открытие SSL-соединения (HttpsURLConnection) между клиентом Android и сервером заставляет сервер возвращать код состояния 403.
AFAIK, это 403 связано с тем, что сервер не получает или не доверяет полученному сертификату клиента, и я не уверен как его отлаживать.

Что работает:

  • Создание запроса PKCS # 10, отправка его в центр сертификации и получение подписанного PKCS # 7 (P7B)
  • Сохранение полученного P7B с закрытым ключом в KeyStore и его экспорт в PKCS # 12 (P12)
  • (Самое неприятное) выбор P12 с устройства, установка его в Windows, соединение с сервером и получение связного (200 HTTP-OK) ответа.

Что я изменил: из примеров кода, которые я получил (из здесь и здесь), мне пришлось кое-что изменить. Я использую HttpsURLConnection, а не OkHttpClient, как там использовал @Than (но это не имеет значения), я не могу предоставить сертификаты, как это сделал Рич Фридман (у него был сертификат, а я получение его через PKCS # 10 и # 7), поэтому я создал CustomTrustManager, который будет доверять сертификату сервера, и по этой причине я использую SpongyCastle (v1.5.0.0, если это важно, установите как поставщик, вставленный в 0) а также не сохранять сертификат, но все делается в памяти.

Вопрос в том, что делать дальше:

  • Как я могу узнать, что ожидает сервер (с точки зрения сертификата клиента)?
  • Как я могу узнать, какие клиентские сертификаты (если есть) отправляются на сервер?
  • Как вообще отладить этот сценарий? (Прокси, такие как Fiddler, бесполезны для базового SSL)

Спасибо!


person Felix    schedule 29.06.2014    source источник


Ответы (1)


Это плохой ответ, но здесь слишком много, чтобы размещать его в качестве комментария.

Для ведения журнала и отладки вы можете создать свой собственный X509KeyManager, который использует обычный менеджер ключей, полученный из KeyManagerFactory:

@DebugLog аннотация взята из библиотеки Hugo, созданной Джейком Уортоном. Он печатает аргументы функции и то, что она возвращает. Вы можете использовать обычный Log.d или что хотите.

ex:

class MyKeyManager implements X509KeyManager {

    private final X509KeyManager keyManager;

    MyKeyManager(X509KeyManager keyManager) {
        this.keyManager = keyManager;
    }

    @DebugLog
    @Override
    public String chooseClientAlias(String[] strings, Principal[] principals, Socket socket) {
        return this.keyManager.chooseClientAlias(strings, principals, socket);
    }

    @DebugLog
    @Override
    public String chooseServerAlias(String s, Principal[] principals, Socket socket) {
        return keyManager.chooseServerAlias(s, principals, socket);
    }

    @DebugLog
    @Override
    public X509Certificate[] getCertificateChain(String s) {
        return keyManager.getCertificateChain(s);
    }

    @DebugLog
    @Override
    public String[] getClientAliases(String s, Principal[] principals) {
        return keyManager.getClientAliases(s, principals);
    }

    @DebugLog
    @Override
    public String[] getServerAliases(String s, Principal[] principals) {
        return keyManager.getServerAliases(s, principals);
    }

    @DebugLog
    @Override
    public PrivateKey getPrivateKey(String s) {
        return keyManager.getPrivateKey(s);
    }
}

И используйте его для инициализации SSLContext

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, password);

final X509KeyManager origKm = (X509KeyManager) kmf.getKeyManagers()[0];
X509KeyManager km = new MyKeyManager(origKm);

SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(new KeyManager[]{km}, tmf.getTrustManagers(), null);

Вы увидите, какой метод вызывается, каковы аргументы (полученные из сертификата сервера) и какой сертификат и закрытый ключ возвращает ваш менеджер ключей.

person Than    schedule 29.06.2014