Реализация X509TrustManager - PullRequest
       53

Реализация X509TrustManager

0 голосов
/ 24 сентября 2018

В настоящее время я пытаюсь передать данные через Интернет через SSL / TLS в Java, и я хочу, чтобы обе стороны аутентифицировались.Я сам реализовал KeyManager, чтобы загрузить пару ключей и представить другой стороне соответствующий сертификат.

Теперь я пытаюсь проверить сертификат, и я делаю это, внедряя свой собственный TrustManager (обе стороныдержите сертификат другой стороны, все самоподписано).Однако getAcceptedIssuers не работает так, как я хочу, потому что даже когда я не возвращаю ни одного, соединение все равно устанавливается без проблем.

Почему в сертификате не отказывают?

protected static class SelectingTrustManager implements X509TrustManager{
    final X509TrustManager delegate;

    private String[] trustedAliases;
    private final KeyStore keystore;

    public SelectingTrustManager(X509TrustManager delegate, KeyStore keystore, String[] trustedAliases) {
        this.trustedAliases = trustedAliases;
        this.keystore = keystore;
        this.delegate = delegate;
    }

    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException{
        delegate.checkClientTrusted(chain, authType);
    }

    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException{
        delegate.checkServerTrusted(chain, authType);
    }

    public X509Certificate[] getAcceptedIssuers(){
        return new X509Certificate[0];
    }

}

1 Ответ

0 голосов
/ 25 сентября 2018

Вам не ясно, является ли ваш код клиентским или серверным, поэтому я отвечаю на оба вопроса, хотя в значительной степени это имеет значение только для сервера.

Хотя Javadoc не является конкретным, X509TM.getAcceptedIssuers НЕ используется, чтобы решить, доверять ли полученному сертификату или цепочке;это делается исключительно checkServerTrusted на клиенте или checkClientTrusted на сервере.

Значение getAcceptedIssuers используется и влияет только на две вещи:

  • на сервере (только), если включена аутентификация клиента (путем вызова needClientAuth(true) или wantClientAuth(true)), имена субъектов из его элементов используются для создания списка CA на сервере CertificateRequest сообщение .Это не обязательно должно совпадать со списком CA, которые будут использоваться в качестве якорей доверия для цепочки сертификатов клиента, если таковой получен;на самом деле, диспетчер доверия на самом деле не обязан использовать список якорей доверия или даже остальную часть стандартного алгоритма проверки - хотя, если ваш «делегат» - это стандарт X509[Extended]TrustManager, который использует стандартCertPathValidator , что делает.Однако, если вы скажете клиенту (-ам) использовать сертификат (ы) из определенных центров сертификации, а затем не примете действительные цепочки сертификатов из этих центров сертификации, у вас, скорее всего, будут несчастные клиенты, которые могут прийти после вас сразличные тяжелые, острые и / или другие неприятные предметы.

    В конкретном случае no 'CA' (массив длиной 0, как у вас), клиент может отправить сертификат из любого CA, который он выберет, и сервер приметэто зависит только от checkClientTrusted.

    Для полноты заметки, RFC определяют расширение для клиента, чтобы указать, какие CA он хочет использовать для сертификата сервера, но я не знаю какой-либо реализации, которая поддерживает это расширение, и Java / JSSE определенно неТаким образом, на практике сервер либо имеет только один сертификат (для каждого алгоритма), либо выбирает его на основе SNI (и ничего больше), и если этот сертификат слишком ненадежен для клиента.

  • если у вас действуют ограничения алгоритма в действии (и в настоящее время вы обычно делаете это по умолчанию, даже если вы не устанавливаете их явно), они не применяются к последнему сертификату в цепочке (предполагаемый якорь), если он входит в число сертификатов, возвращаемых getAcceptedIssuers, которые предположительно являются (фактическими) якорями.Другими словами, если сертификат является якорем доверия, предположительно, пользователь решил доверять ему, даже если он может использовать алгоритмы, которые не соответствуют современным стандартам (например, MD5 или RSA меньше 1024).

    Ли человек, который поместил сертификат в доверенное хранилище или иным образом сделал его якорем, действительно правильно оценил его безопасность, это другой вопрос, на который Java не пытается ответить.Даже Stackexchange, возможно, не сможет этого сделать, хотя я уверен, что здесь будут люди, которые будут рады попробовать.(Я не беру на себя обязательства, буду ли я одним из них.)

...