SSLPeerUnverifiedException при использовании самозаверяющего сертификата в Android - PullRequest
0 голосов
/ 14 февраля 2020

Я пытаюсь выполнить SSL-закрепление в своем приложении и следую инструкциям на https://developer.android.com/training/articles/security-ssl, а также создаю свой собственный сертификат с https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-nginx-in-ubuntu-16-04 на моем сервере по адресу https://coursescraper.tookmund.com/

Однако, когда я пытаюсь подключиться к своему серверу, я получаю исключение:

javax.net.ssl.SSLPeerUnverifiedException: Hostname coursescraper.tookmund.com not verified:
        certificate: sha1/Uax3JSsdPAGgCg5XyWPR8mhrjRU=
        DN: CN=coursescraper.tookmund.com
        subjectAltNames: []

Затем я добавил конфигурацию безопасности сети в свое приложение как указано https://developer.android.com/training/articles/security-config

Это позволяет мне удалить все содержимое SSLContext, но все равно выдает точно такую ​​же ошибку.

Я пытался отключить верификатор имени хоста только для посмотрим, что произойдет, но я получаю ту же ошибку, не видя VERIFY в журналах, поэтому верификатор имени хоста даже не участвует:

        // TODO: FIX THIS!!! THIS IS BAD!!!
    connection.setDefaultHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    Log.v("VERIFY", s);
                    return true;
                }
            });

Когда я переключаю файл сертификата в приложении на другой сертификат, я вместо этого получаю a SSLHandshakeException:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Таким образом, похоже, что закрепление работает, в моем сертификате что-то не так.

Общее имя - это имя домена, как видно из ошибки, поэтому Я не с что я делаю не так.

Подключение с помощью curl работает нормально:

$ curl -v --cacert school/mobilesecCSCI420/nginx-selfsigned.crt https://coursescraper.tookmund.com
* Expire in 0 ms for 6 (transfer 0x558aada3ef50)
* Expire in 1 ms for 1 (transfer 0x558aada3ef50)
...
* Expire in 50 ms for 1 (transfer 0x558aada3ef50)
*   Trying 54.165.223.53...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x558aada3ef50)
* Connected to coursescraper.tookmund.com (54.165.223.53) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: school/mobilesecCSCI420/nginx-selfsigned.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=coursescraper.tookmund.com
*  start date: Feb 13 05:51:45 2020 GMT
*  expire date: Feb 12 05:51:45 2021 GMT
*  common name: coursescraper.tookmund.com (matched)
*  issuer: CN=coursescraper.tookmund.com
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x558aada3ef50)
> GET / HTTP/2
> Host: coursescraper.tookmund.com
> User-Agent: curl/7.64.0
> Accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200 
< server: nginx/1.10.3
< date: Thu, 13 Feb 2020 16:35:28 GMT
< content-type: text/html
< content-length: 691
< last-modified: Sun, 09 Feb 2020 21:13:06 GMT
< etag: "5e4075e2-2b3"
< accept-ranges: bytes
< 
<!DOCTYPE html>
<html>
...

1 Ответ

0 голосов
/ 14 февраля 2020

Я наконец понял это. В сертификате отсутствует альтернативное имя субъекта DNS.

Как только я сгенерировал новый сертификат, он работал отлично.

Для тех, кому это может понадобиться, вот мой ssl.cnf


RANDFILE                = /dev/urandom

[ req ]
default_bits            = 4096
default_keyfile         = privkey.pem
distinguished_name      = req_distinguished_name
prompt                  = no
policy            = policy_anything
req_extensions          = req_ext
x509_extensions         = req_ext

[ req_distinguished_name ]
commonName                      = coursescraper.tookmund.com

[ req_ext ]
basicConstraints        = CA:TRUE
subjectAltName = @alt_names

[alt_names]
DNS.1   = coursescraper.tookmund.com

Замените имя хоста своим собственным и затем запустите


sudo openssl req -x509 -nodes -days 365 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt -config ssl.cnf

, чтобы сгенерировать новый сертификат

...