AFNetworking 2.2 Закрепление SSL с самозаверяющим сертификатом

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

Сначала я попытался создать самозаверяющий сертификат в соответствии с эти инструкции:

Генерация закрытого ключа:

sudo openssl genrsa -des3 -out server.key 2048

Создание запроса на подпись и использование доменного имени при запросе общего имени:

sudo openssl req -new -key server.key -out server.csr

Генерация сертификата:

sudo openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Наконец, преобразование его в формат der (поскольку AFNetworking требует его)

sudo openssl x509 -outform der -in server.crt -out server.der

Сервер — Ubuntu 12.04, на котором работает ngninx+passenger для обслуживания приложения Rails 4. Вот часть конфигурации моего сервера nginx для включения SSL:

server {
  listen 80;
  listen 443;
  server_name myapp.com;
  passenger_enabled on;
  root /var/www/myapp/current/public;
  rails_env production;
  ssl on;
  ssl_certificate /etc/nginx/ssl/server.crt;
  ssl_certificate_key /etc/nginx/ssl/server.key;
}

После перезапуска nginx, загрузки файла der, добавления его в мой проект и переименования в «server.cer» (поскольку AFNetworking требует, чтобы сертификат использовал расширение .cer), я использую этот код, чтобы включить закрепление SSL для моего подкласса AFHTTPSessionManager :

client.securityPolicy = [AFSecurityPolicy 
                          policyWithPinningMode:AFSSLPinningModeCertificate];

Затем при первом запросе к серверу AFNetworking пытается проверить, что «доверие» действительно в функции AFServerTrustIsValid:

static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) {
    SecTrustResultType result = 0;

    OSStatus status = SecTrustEvaluate(serverTrust, &result);
    NSCAssert(status == errSecSuccess, @"SecTrustEvaluate error: %ld", (long int)status);

    return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
}

Если я поставлю точку останова на выходе, я вижу, что результат всегда kSecTrustResultRecoverableTrustFailure.

Если я пропущу функцию AFServerTrustIsValid, установив allowInvalidCertificates в YES в политике безопасности, запрос будет успешным. Но я действительно не хочу разрешать недействительные сертификаты, если мне это не нужно.

Вернемся к чертежной доске: этот ТАК вопрос привел меня к это руководство по созданию самозаверяющего сертификата с созданием ЦС. Я настраиваю свой файл openssl.cnf следующим образом:

[ req ]
default_md = sha1
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
countryName = United Kingdon
countryName_default = UK
countryName_min = 2
countryName_max = 2
localityName = Locality
localityName_default = London
organizationName = Organization
organizationName_default = Eric Organization
commonName = Common Name
commonName_max = 64

[ certauth ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
crlDistributionPoints = @crl

[ server ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
nsCertType = server
subjectAltName = DNS:myapp.com
crlDistributionPoints = @crl

[ crl ]
URI=http://testca.local/ca.crl

А затем использовал эти команды для генерации всего. Сначала материал CA:

sudo openssl req -config ./openssl.cnf -newkey rsa:2048 -nodes -keyform PEM -keyout ca.key -x509 -days 3650 -extensions certauth -outform PEM -out ca.cer

Затем снова закрытый ключ сервера:

sudo openssl genrsa -out server.key 2048

Запрос на подпись:

sudo openssl req -config ./openssl.cnf -new -key server.key -out server.req

Сертификат:

sudo openssl x509 -req -in server.req -CA ca.cer -CAkey ca.key -set_serial 100 -extfile openssl.cnf -extensions server -days 365 -outform PEM -out server.cer

И, наконец, файл der:

sudo openssl x509 -outform der -in server.cer -out stopcastapp.com.der

Когда я обновляю и перезапускаю nginx, загружаю и добавляю server.der в свой проект (не забудьте переименовать его в server.cer и сбросить симулятор), я получаю точно такой же результат.

Страшный kSecTrustResultRecoverableTrustFailure снова поднимает свою уродливую голову.

Что я делаю неправильно? Мне ОЧЕНЬ не по себе от того, как все это работает, или мне нужно настроить всего одну мелочь, чтобы все заработало? Если бы вы могли как-то помочь, я был бы очень, очень признателен (я занимаюсь этой проблемой уже два дня). Спасибо!


person Eric Allam    schedule 07.03.2014    source источник


Ответы (1)


Где-то в вашем коде вам нужно указать это или что-то подобное. Вам нужно сообщить коду, чтобы он принимал недействительные сертификаты (самоподписанные).

self.allowsInvalidSSLCertificate = YES;
person Marcel Gruber    schedule 07.02.2015