Сейчас на фоне уязвимости Logjam все в индустрии в очередной раз обсуждают проблемы и особенности TLS. Я хочу воспользоваться этой возможностью, чтобы поговорить об одной из них, а именно — о настройке ciphersiutes. Мы уже не раз писали на Хабре о том, как внедряем шифрование трафика на сервисах Яндекса: например, об этом весьма подробно рассказывал Эльдар kyprizel Заитов, но ciphersiutes были одной из вещей, которые в тот раз остались в основном за кадром. Кстати, хочу всех успокоить и сказать, что на серверах Яндекса никогда не использовался экспортный вариант алгоритма Диффи-Хеллмана.

Итак, Ciphersuite — это совокупность алгоритмов, используемых в конкретной TLS–сессии. Сюда относятся:

  • алгоритм выработки сессионных ключей шифрования;
  • алгоритм, используемый для аутентификации сервера;
  • собственно симметричный алгоритм шифрования трафика;
  • и, наконец, алгоритм контроля целостности (MAC, message authentication code).

Для того чтобы понять, какова роль каждого из алгоритмов, давайте вкратце рассмотрим процесс инициализации TLS–соединения в применении к HTTPS (разумеется, TLS возможен и для других TCP и UDP протоколов, но сейчас мы это рассматривать не будем). За подробностями можно обратиться в RFC5246.

image


В TLS есть собственный механизм деления на сообщения, называемый record protocol. Каждое TLS-сообщение не обязано быть равно TCP-сегменту, оно может быть больше или меньше.

TLS соединение начинает клиент — пересылкой сообщения ClientHello. Самая интересная для нас часть сообщения ClientHello — как раз список поддерживаемых клиентом ciphersuite. Также клиент посылает список известных ему эллиптических кривых.

ClientHello

В ответ сервер пересылает сообщение ServerHello, содержащее выбранный ciphersuite:

ServerHello

В данном случае это TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Этот вариант означает, что для генерации сеансовых ключей будет использован алгоритм Диффи-Хеллмана на эллиптических кривых, аутентификация сервера будет производится с помощью RSA, а в качестве алгоритма шифрования трафика будет использоваться AES с длиной ключа 128 бит в режиме GCM. Внимательный читатель заметит, что GCM является AEAD-алгоритмом и таким образом не требует дополнительной функции MAC. Зачем же она нужна? Ответ кроется в механизме выработки сеансовых ключей, но сначала давайте обсудим некоторые варианты каждого алгоритма в ciphersuite. С полным списком всех возможных вариантов можно ознакомиться на сайте IANA.

Итак, в качестве алгоритма выработки сеансовых ключей могут использоваться:
  • классический алгоритм Диффи-Хеллмана, он обозначается DH и DHE;
  • вариант алгоритма Диффи-Хеллмана на эллиптических кривых, он обозначается ECDH и ECDHE;
  • генерация случайного числа клиентом и последующее его шифрование на публичном ключе сервера, в реальных ситуациях почти всегда применяется RSA.

Разница между вариантами DH без суффикса E и с суффиксом E состоит в эфемерности ключа. В случае DHE и ECDHE ключ действительно вырабатывается в ходе полноценного DH-обмена, где параметры шифрования не сохраняются и таким образом достигается свойство PFS. В ciphersuites DH и ECDH приватный ключ сервера (и клиента, если он есть) является приватным ключом для DH-обмена и таким образом свойство PFS не достигается.

В качестве алгоритма аутентификации в практических реалиях используется почти исключительно RSA, ECDSA делает первые шаги, но мы надеемся, что он будет больше распространен.

В качестве симметричных алгоритмов шифрования широко распространены AES с длиной ключа 128 и 256 бит в режимах CBC и GCM, RC4 и 3DES. Можно встретить ciphersuite с одиночным DES, CHACHA20 и даже NULL — этот означает, что никакого шифрования на самом деле применяться не будет.

В качестве алгоритмов MAC встречаются MD5, SHA1, SHA256 и, редко, SHA384.

Как было сказано выше, в случае алгоритма шифрования AES в режиме GCM контроль целостности обеспечивается собственно режимом шифрования. Поэтому необходимости в отдельной MAC–функции нет. В RFC на TLS1.2 специально указано, что помимо собственно функции аутентификации MAC-алгоритм в ciphersuite выполняет еще и роль псевдослучайной функции (PRF). Когда общее между клиентом и сервером случайное число вырабатывается за счет того или иного варианта DH или просто генерируется клиентом, оно носит название pre-master key. После получения pre-master key на его основе (а также на основе случайных значений из сообщений ClientHello и ServerHello) вырабатывается master key путем применения PRF функции: master_secret = PRF(pre_master_secret, «master secret», ClientHello.random + ServerHello.random). Впоследствии из master key с помощью той же функции PRF вычисляется весь необходимый ключевой материал: ключи для алгоритмов шифрования, ключи для MAC, инициализационные векторы.

Ciphersuites в реальной жизни


Теперь, когда базовая теория понятна, давайте рассмотрим настройки ciphersuites на некоторых популярных сайтах. Для этого можно использовать сканер SSLLabs, хотя у нас в Яндексе для внутренних нужд используется написанный kyprizel инструмент. В принципе, можно использовать команду openssl s_client с ключом -cipher или попробовать cipherscan, который по сути является оберткой на bash для вызова openssl.

Для того что бы тестировать варианты ciphersuites локально, удобно использовать команду openssl ciphers, которая позволит посмотреть, во что именно превратится предлагаемый набор условий для ciphersuite.

Итак, собственно, Яндекс. Список поддерживаемых сервером ciphersuites довольно велик:

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_RC4_128_SHA (0x5)
TLS_ECDHE_RSA_WITH_RC4_128_SHA


Сначала идут современные ciphersuites с выработкой pre-master ключа через ECDHE. Мы предпочитаем AES-128 в режиме GCM. Я лично не вижу большой пользы от AES256, но для yandex.ru мы сохранили этот набор шифров для более параноидальных пользователей. После различных вариантов ECDHE ciphersuites идут варианты с шифрованием AES, но без PFS. Такие варианты используются браузерами типа старой Opera (версии 12.x), и поэтому мы вынуждены их сохранить.

Затем идет два варианта с шифрованием 3DES: их мы сохраняем в первую очередь для браузеров Internet Explorer на Windows XP с установленным SP3. Internet Explorer использует системную библиотеку Schannel, и в XP с SP3 наконец появилась поддержка 3DES — устаревшего, но все еще устойчивого алгоритма шифрования. Наконец, для несчастных с Internet Explorer 6 на XP мы сохраняем шифры RC4 — других вариантов на этой платформе просто нет. При этом мы осознаем вероятность того, что этот шифр уязвим, поэтому доступен он только в случае хендшейка по протоколу SSLv3. Если клиент подключается с более современным протоколом — TLS 1.0, TLS 1.1 или TLS 1.2 — ciphersuite на основе RC4 не предлагается.

Серверы поиска таким образом предлагают трейдофф между безопасностью для современных клиентов и необходимостью поддерживать старые.

Иная ситуация на серверах Яндекс.Почты. Здесь, например, команда приняла продуктовое решение не поддерживать IE6 (даже в так называемой «легкой» верстке) и это отразилось в поддержке на уровне TLS:

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA


Логика сохранена той же, но трейдофф сдвинут в сторону большей безопасности и меньшей совместимости с устаревшими браузерами. Сначала — современные ciphersuite для TLS1.2: наш любимый ECDHE + AES128 в режиме GCM, затем то же самое, но в режиме CBC и, наконец, вариант с более слабым SHA1. Следующие три варианта — то же самое, но без PFS. Замыкает набор ciphersuite для IE8: 3DES в режиме CBC с SHA1 и без PFS. Очень хотим от него отказаться, поэтому в Почте мы начали кампанию по обновлению браузеров пользователей. Если вы настраиваете компьютеры своим родителям, не поленитесь — установите современный браузер. Проделайте то же самое и в своей организации.

Еще один вариант — Яндекс.Паспорт. Здесь мы пробовали сохранить классический DH, поскольку замечали ситуации, когда находились браузеры, которые все таки предпочитали его и, возможно, не имели поддержки ECDH (одно время это относилось к Firefox на RedHat Linux, где по юридическим соображениям отсутствовали протоколы с эллиптической криптографией). При этом задолго до публикации атаки Logjam мы понимали необходимость выравнивания длин ключей и бесполезность использования 1024-битного DH при 2048-битных RSA ключах в сертификатах. Поэтому на passport.yandex.ru доступен DHE, но 2048-битный, сгенерированный специально для этого случая, и сервис не подвержен Logjam. Остальная логика такая же: сначала ECDH с AES в различных вариантах, потом DH с AES, потом AES без PFS и, наконец, fallback в 3DES без PFS.

Давайте посмотрим и на «их нравы». Вот пример с gmail.com.

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 
TLS_ECDHE_RSA_WITH_RC4_128_SHA 
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_RC4_128_MD5
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA


Мне в целом понятна логика приоритетов: сначала ECDH и AES. Обратите внимание, что Google решил попробовать шифр CHACHA20, о котором я писал выше. Мне кажется, что главная его цель — облегчить нагрузку на CPU (и, соответственно, расход энергии) в смартфонах на Android. Что и говорить, доминирование имеет свои преимущества — контролируя и сервис, и платформу можно делать недоступные другим вещи. Интересно, что Google использует свой форк OpenSSL под названием BoringSSL. Его полезное свойство — возможность задавать ciphersuites равных приоритетов. Так в этом случае (хотя ssllabs этого не показывает), TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 и TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 имеют равный приоритет и среди них клиент определяет, какой ciphersuite считает приоритетным.

Вот twitter.com:

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA


И снова понятная логика, очень похожая на нашу в Почте: сначала ECDHE, зачем AES без PFS и fallback на 3DES.

Логика на vk.com мне непонятна. Кажется, тут просто взяли все шифры и выкинули из них MD5 и RC4. Думаю, похожий набор можно получить командой openssl ciphers 'ALL:!RC4:!MD5'. Шифр CAMELLIA? Are serious?

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA


У mail.ru сначала ECDHE, потом DHE, потом — шифры без PFS, но опять же — CAMELLIA, SEED. Кажется, и тут никто не выбирал ciphersuites, а положился на варианты, предлагаемые OpenSSL по умолчанию.

Интересно, что до недавнего времени сервер nsa.gov имел очень слабый набор ciphersuites, самым лучшим вариантом там был RC4 без PFS, но сейчас ситуацию исправили с той же самой логикой, что и у нас: ECDHE и AES, RSA и AES, fallback на 3DES. Аналогично выглядит https на сайте ЦРУ. Забавно, что на сайтах ФСБ и СВР вообще не работает https.

Впрочем, по моей личной оценке, сайтом с самыми плохими ciphersuites в интернете был сайт Госуслуг правительства Москвы login.mos.ru. В свое время он предлагал ciphersuite TLS_NULL_WITH_NULL_NULL — то есть без аутентификации и без шифрования. Впрочем, сейчас приняты меры: задержка на установку TLS соединения с sslabs.com установлен таким образом, что сканер отваливается по таймауту. Но и ciphersuites поправлены, хотя высшим приоритетом стоят RC4-MD5, RC4-SHA и 3DES-SHA, в списке можно найти ECDH — это можно проверить вручную командой openssl s_client с ключом -cipher.

Рекомендации по выбору ciphersuite


Какие настройки можно порекомендовать обычному сайту? Вот такой рекомендованный конфиг nginx мы используем в Яндексе по умолчанию:

ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers kEECDH+AESGCM+AES128:kEECDH+AES128:kRSA+AESGCM+AES128:kRSA+AES128:!RC4:!aNULL:!eNULL:!MD5:!EXPORT:!LOW:!SEED:!CAMELLIA:!IDEA:!PSK:!SRP:!SSLv2;


Если необходима поддержка IE8 на XP, можно использовать такой набор, он включит 3DES:
ssl_ciphers kEECDH+AESGCM+AES128:kEECDH+AES128:kRSA+AESGCM+AES128:kRSA+AES128:kRSA+3DES:!RC4:!aNULL:!eNULL:!MD5:!EXPORT:!LOW:!SEED:!CAMELLIA:!IDEA:!PSK:!SRP:!SSLv2;


Если нужна поддержка IE6 на XP, можно включить RC4, но в таких случаях мы рекомендуем нашим системным администраторам проконсультироваться со службой информационной безопасности, чтобы точно представлять свои риски. Я не уверен, что каким-то сайтам за пределами первой полусотни самых популярных в рунете действительно необходима такая поддержка.

Кстати, найдете интересные настройки ciphersuite в интернете, пишите.

Комментарии (53)


  1. GliX
    26.05.2015 17:33

    Лучше бы какой-то другой тэг использовать — Хабр обрезает строки с ssl_ciphers примерно на половине.


    1. wrewolf
      26.05.2015 18:15

      но тем не менее копировать можно


  1. Ivan_83
    26.05.2015 18:00

    «Если вы настраиваете компьютеры своим родителям, не поленитесь — установите современный браузер. Проделайте то же самое и в своей организации.» — в организациях не совсем канает. Есть всякие АктивХ поделия для гос сайтов которые только в ИЕ8 работают. Пользователи имеют альтернативу в виде мозилы и прочих, но не всегда ей пользуются.
    Полагаю ещё лет 5 с этим ничего сделать будет нельзя, а потом вин7 кончится и госам придётся что то менять с их АктивХ.


    1. ivlad Автор
      26.05.2015 18:05
      +2

      На самом деле, на нашей статистике IE8 не так много. Куда больше, в разы, Opera 12. И IE8 сам по себе не плох — плох только IE на XP, потому, что шифрование в IE зависит от библиотеки SChannel, а в XP она не умеет ни одного пристойного шифра. IE8 выходил, кажется, вместе с SP3, с которым пришло и обновление SChannel — появилась поддержка 3DES и SNI.

      XP уже не поддерживается, а браузеры остались. :(


  1. major
    26.05.2015 19:29
    +2

    А что не так с CAMELLIA?


    1. ivlad Автор
      26.05.2015 20:18
      +1

      Если бы мы были в Японии, его бы имело смысл поддержать. А так — сначала нужно понять, какую пользу он приносит, помимо увеличения attack surface.


      1. dmitrmax
        27.05.2015 01:27

        Внезапно: ГОСТ? )


        1. Disen
          27.05.2015 09:04
          +2

          Использовать шифрсьюты на основе ГОСТов имеет смысл ради экспериментов разве что, или когда сверху сказали (законодательно), что надо. Иные варианты использования даже в голову не приходят. :)
          Поправьте, если не прав.


          1. dmitrmax
            27.05.2015 11:20

            Там же смайлик ;-)


        1. ivlad Автор
          27.05.2015 10:36
          +4

          У ГОСТ 28147–89 есть несколько недостатков: во–первых, он медленнее AES даже без учета AES-NI, во–вторых, малый размер блока (64 бита) переносит в область практической достижимости атаки с учетом коллизий CBC, хотя для HTTPS–сессий это менее актуально, чем для VPN–соединений, где объемы трафика куда больше, в–третьих, проблема с тем, что S–боксы не являются частью стандарта (ТК26, наконец, пришел в сознание и опубликовал рекомендацию, но я, честно говоря, не в курсе, насколько она обязательна к исполнению) в–четвертых, если хочется, что бы его считали действительно криптографией, нужно купить сертифицированные криптобиблиотеки

          Остановлюсь подробнее на последнем. У нас, как уже писал kyprizel, есть свой HTTP–балансер под названием balancer. Он же терминируетTLS. В качестве библиотек он использует OpenSSL, значит, что не пришлось переписывать, надо бы иметь сертифицированный вариант OpenSSL. Такой, конечно, есть, да и собственно поддержка ГОСТ в ванильном OpenSSL сделана теми же людьми, так что можно было бы использовать, но тут возникает беспокойство о необходимости получения лицензии в ФСБ.

          В общем, я про это думал и решил, что с технической стороны алгоритм тридцатилетней давности уже показывает свой возраст и не выглядит достаточно привлекательным на фоне более новых разработок, а со стороны юридической добавляет проблем. И все это ради того, чтобы поддержать 1-2% браузеров с установленным КриптоПРО. Так что, как верно заметил соседний комментатор, пока законодательно не обяжут, связываться не хочется.


          1. dmitrmax
            27.05.2015 11:18
            +1

            1) Это была шутка юмора, относящаяся к «Если бы мы были в Японии».

            2) Справедливости ради, ЕМНИП, сертифицированная ФСБ библиотека необходима лишь там, где использование криптографии обязательно согласно законодательству. У вас же нет сертификата NIST на реализацию AES, RSA и SHA, и ни у кого вопроса не возникает. А даже если бы и была, то проверить, что именно эта реализация у вас воткнута в бою ваш клиент никак не может.

            3) Проблема не столько в рекоммендации ТК26, а в полном его нежелании взаимодействовать с IANA, IETF и TLS WG.


          1. ac_dev
            27.05.2015 12:16

            А в Яндекс.Браузере поддержку ГОСТ не планируете сделать?


            1. dmitrmax
              27.05.2015 12:34
              +2

              Для этого надо добавить поддержку ГОСТ в libnss. Предлагаю вам почитать for fun эту баталию.


              1. ac_dev
                27.05.2015 12:40

                Если абстрагироваться от баталии, то проект atoken предлагает работающее решение. Правда для устаревшей версии NSS.


                1. dmitrmax
                  27.05.2015 12:42

                  Там про него упомянуто в самом конце. Всё не дойдут руки в нём поковыряться.


                  1. ac_dev
                    27.05.2015 12:45

                    А другой путь — в качестве криптоядра chromium использовать openssl вы не рассматривали? В этом случае патч будет существенно меньше.


                    1. dmitrmax
                      27.05.2015 14:33

                      Возможно, что я создал ложное впечатление, что я принимаю какие-то решения в разработке libnss или chromium, или имею какое-то отношению к Yandex и их браузеру. Это всё не так, поэтому я такие вещи рассматривать могу только в своих фантазиях ) Я был готов помочь с реализацией ГОСТ в libnss, но это как видно, оказалось никому не нужно.

                      Возвращаясь к вашему вопросу:
                      1) Как мне кажется, libnss довольно глубоко вшит в хромиум и его отпрысков.
                      2) Есть некий проект по приведению инициализации криптографии в Linux к одному знаменателю, и там в фаворе systemd NSS.

                      Касательно использования того или иного криптографического framework'а, могу лишь сказать, что мне они одинаково не нравятся. NSS очень не нравится тем, что у него глобальное состояние. OpenSSL по-мимо своей дурной славы своим неполноценным API. Например, вы не можете с помощью него сделать сертификат на ГОСТовский ключ, который удовлетворяет приказу ФСБ из-за того, что ему нельзя указать тип у полей у тэгов ИНН, СНИЛС и ОГРН.


                      1. ac_dev
                        27.05.2015 15:22

                        OpenSSL по-мимо своей дурной славы своим неполноценным API. Например, вы не можете с помощью него сделать сертификат на ГОСТовский ключ, который удовлетворяет приказу ФСБ из-за того, что ему нельзя указать тип у полей у тэгов ИНН, СНИЛС и ОГРН.

                        Почему же. Можно.


                        1. dmitrmax
                          27.05.2015 15:29

                          Тогда реквестую конфиг.


                          1. ac_dev
                            28.05.2015 14:03
                            +1

                            Приведу вам выдержки из кода, использующего API OpenSSL.

                            1. Собственно таблица «русских» полей:

                            OpensslObject ruOpensslObjects[] =
                            {
                            	{"INN", "INN", "1.2.643.3.131.1.1", V_ASN1_NUMERICSTRING},
                            	{"OGRN", "OGRN", "1.2.643.100.1", V_ASN1_NUMERICSTRING},
                            	{"OGRNIP", "OGRNIP", "1.2.643.100.5", V_ASN1_NUMERICSTRING},
                            	{"SNILS", "SNILS", "1.2.643.100.3", V_ASN1_NUMERICSTRING},
                            	{"kpFSS", "KP FSS", "1.2.643.3.141.1.2", V_ASN1_UTF8STRING},
                            	{"rnsFSS", "RNS FSS", "1.2.643.3.141.1.1", V_ASN1_UTF8STRING},
                            	{"KC1", "KC1", "1.2.643.100.113.1", -1},
                            	{"KC2", "KC2", "1.2.643.100.113.2", -1}, // TODO: check  sn and ln names for russian policy
                            	{"KC3", "KC3", "1.2.643.100.113.3", -1},
                            	{"KB1", "KB1", "1.2.643.100.113.4", -1},
                            	{"KB2", "KB2", "1.2.643.100.113.5", -1},
                            	{"KA1", "KA1", "1.2.643.100.113.6", -1},
                            	{"subjectSignTool", "Subject Sign Tool", "1.2.643.100.111", -1},
                            }; 
                            


                            2. Регистрируем «объекты», связанные с «русскими» полями

                            try {
                            		for (int i = 0; i != boost::size(ruOpensslObjects); i++)
                            		{
                            			int nid = m_openssl->OBJ_create(ruOpensslObjects[i].oid, ruOpensslObjects[i].sn,
                            			                                ruOpensslObjects[i].ln);
                            			m_objectsMap[nid] = &(ruOpensslObjects[i]);
                            		}
                            	} catch (std::exception& exc) {
                            		e = exc;
                            		exceptionThrown = true;
                            		goto opensslEngineFinish;
                            	}
                            


                            3. Собственно функция формирования subject в PKCS#10. «Русские» поля обрабатываются в default.

                            void Pkcs10Request::addSubjectEntry(const string& name, const string& value)
                            {
                            	if (name.empty() || value.empty())
                            		BOOST_THROW_EXCEPTION(BadParamsException());
                            
                            	const OpensslWrapper* openssl = m_crypto->openssl();
                            	int nid = openssl->OBJ_txt2nid(name.c_str());
                            	int encodingType = 0;
                            	switch (nid)
                            	{
                            		case NID_commonName:
                            		case NID_organizationName:
                            		case NID_organizationalUnitName:
                            		case NID_title:
                            		case NID_localityName:
                            		case NID_stateOrProvinceName:
                            		case NID_surname:
                            		case NID_givenName:
                            		case NID_streetAddress:
                            		case NID_postalAddress:
                            		case NID_pseudonym:
                            			encodingType = MBSTRING_UTF8;
                            			break;
                            		case NID_pkcs9_emailAddress:
                            			encodingType = V_ASN1_IA5STRING;
                            			break;
                            		case NID_countryName:
                            			encodingType = V_ASN1_PRINTABLESTRING;
                            			break;
                            		default:
                            			const OpensslObject* obj = m_crypto->object(nid);
                            			encodingType = obj->asn1enc;
                            	}
                            
                            	if (!openssl->X509_NAME_add_entry_by_NID(m_subject, nid, encodingType,
                            	                                         reinterpret_cast<unsigned char*>(const_cast<char*>(value.c_str())),
                            	                                         -1, -1, 0))
                            		BOOST_THROW_EXCEPTION(OpensslException(openssl));
                            }
                            


                            Через тулзу openssl сделать то же самое с ходу не удалось, как-то там мутно конфигурируются типы новых OID-ов.


                            1. dmitrmax
                              28.05.2015 14:11

                              Каюсь, я имел ввиду не API, а тулзу. С тулзой и её конфигом протрахался долго, пока в глубоко в доке не прочитал, что дополнительным полям присвается всегда фиксированный тип, сейчас не вспомню какой: то ли DisplayString, то ли Utf8String.


                      1. grossws
                        27.05.2015 16:04

                        Ещё nss смотрит в environment в поисках прекрасной переменной SSLKEYLOGFILE, после чего начинает писать pre-master в указанный файл.

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


                        1. dmitrmax
                          27.05.2015 16:08

                          Вы шутите? Это же прекрасная мегафича, которая позволяет вам дебажить https соединения с помощью Wireshark.


                          1. grossws
                            27.05.2015 19:06

                            Эта мегафича крайне удобна для дебага (и я её активно использую, т. к. у меня на серверах предпочтение отдано ECDHE+AESGCM), но очень хочется, чтобы её использование требовало, как минимум, запуска браузера со специальным ключом.


                            1. dmitrmax
                              27.05.2015 19:32

                              Это, можно сказать, следствие глобальности контекста. В данном случае монопенисуально параметр браузера или переменная среды. Вот openssl позволяет двум независимым сущностям в процессе оперировать либой с совершенно разными наборами настроек. А NSS — нет. Поэтому особой разницы как прокидывать эту настройку в NSS я не вижу. А вы?

                              SSLKEYLOGFILE=/tmp/my.keylog chrome
                              

                              или
                              chrome --ssl-keylog-file=/tmp.keylog
                              


                              Кроме того, представьте себе ситуацию, когда приложение, использующее nss не умеет такого ключа коммандной строки, а поглядеть shark'ом очень надо…


                              1. grossws
                                27.05.2015 20:02

                                При использовании env vars есть неявная конфигурация, которая незаметна при запуске chrome/firefox (надо дополнительно проверять наличие установленных env vars). При использовании ключа при запуске конфигурация явная.


                                1. dmitrmax
                                  27.05.2015 20:32

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


                                  1. grossws
                                    28.05.2015 03:00
                                    +1

                                    Вы при запуске каждого приложения проверяете env? Я — нет. И мне не нравится подход мозилловцев в этом кейсе.

                                    Это похоже на то, если бы mkfs --help выполнял форматирование, если в env проставлено MKFS_TARGET несмотря на то, что у него всего-лишь запросили справку. Даже, если про это знает каждый, это прописано в документации и т. п., но шанс ошибки резко возрастает.


                                    1. dmitrmax
                                      28.05.2015 08:27

                                      Объясните мне, зачем проверять перед каждым запуском проставленно ли что-либо в env?

                                      Если вы сами имеете свойство проставлять в окружение шелла такие опасные переменные, то это лечится самодисциплиной. Так же как и лечится привычка не сидеть под рутом.

                                      Или вы боитесь, что у вас переменная заведется в env без вашего ведома? Тогда как?


                                1. ivlad Автор
                                  28.05.2015 09:34

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

                                  А вы, как принято говорить в Яндексе, нерепрезентативны. :)


    1. dmitrmax
      27.05.2015 07:43

      За что минусанули ivlad не понятно, но ради интереса посмотрел: из популярных браузеров только Firefox поддерживает CAMELLIA, но в силу приоритета предпочтений он никогда не выбирется. Таким образом, вам придется найти/настроить браузер, чтобы CAMELLIA там стояла на первом месте в списке. Эдакий япона-браузер, я бы сказал ) То есть это носит сугубо теоретический характер для Яндекса.

      А, например, Гугл выпилил из Chrome все ciphersuite и не протестует против добавления ГОСТового ciphersuite именно по причине, описанной ivlad — увеличение attack surface.


      1. merlin-vrn
        27.05.2015 11:18

        у меня в Fx как раз CAMELLIA и выбирается, если ничего специально не настраивал ни на клиенте, ни на сервере


        1. dmitrmax
          27.05.2015 11:29

          Значит, либо такие дефолтовые настройки сервера, либо в Fx произошли какие-то изменения в предпочтении ciphersuite'ов. Давайте посмотрим, что скажет тест вашего браузера.


          1. merlin-vrn
            27.05.2015 11:34

            Видимо, это так было раньше. Сейчас первая CAMELLIA встречается на 12-й позиции, что практически нереально.


            1. dmitrmax
              27.05.2015 11:37

              Если в сервере включена только она, то почему бы и нет )


      1. MyHabrahabr
        31.05.2015 19:07

        Firefox поддерживает CAMELLIA, но в силу приоритета предпочтений он никогда не выбирется
        Набор шифра всегда выбирает сервер, но он может либо выбрать первый попавшийся среди поддерживаемых браузером, либо выбрать первый попавшийся из своего списка, если настроено серверное предпочтение.

        Наивысший приоритет CAMELLIA отдан на контент-серверах Adriver, так что у пользователей Tor Browser и старого Firefox реклама загружается с использованием именно этого шифра.


  1. Yan169
    26.05.2015 21:45
    +2

    Чем AES_GCM принципиально лучше AES_CBC?
    Не требуется отдельный подсчет MAC? ОК, допустим, выигрыш в производительности.
    И там и там с каждым пакетом посылаются и IV и MAC (для GCM аналог — authentication tag). Т.е. на первый взгляд в плане оверхеда тоже примерный паритет.

    Было бы интересно, если б кто-нибудь раскрыл этот вопрос подробнее.


    1. ivlad Автор
      26.05.2015 22:13
      +3

      Ну, навскидку:

      1. CBC позволяет существовать уязвимостям типа POODLE, более широко — предскаузуемость влияния изменения одного блока на шифрование следующего — плохая идея,
      2. CBC делает уязвимыми коллизии блоков, для AES это не очень применимо, потому что размер блока большой, а для ГОСТ 28147–89 атака представляется практически реализуемой,
      3. GCM можно шифровать параллельно, на нескольких ядрах, в CBC — только последовательно.


      1. d00kie
        26.05.2015 22:25

        Да тот же Beast был реализуем был, за счет последовательного XORа блоков в CBC.


      1. dmitrmax
        27.05.2015 07:46

        Зачем же его тогда оставили в своих настройках?


        1. ivlad Автор
          27.05.2015 10:38

          Примерно по той же причине, по которой есть 3DES. Мы же в реальном мире живем, где есть браузеры, не поддерживающие TLS1.2 и самые модные–трендовые ciphersuites. Им тоже надо обеспечить поддержку.


          1. Yan169
            27.05.2015 11:03

            Например, все версии Safari на iOS (в том числе 8.3) GCM не поддерживают.


          1. merlin-vrn
            27.05.2015 11:15

            У 3DES кстати абсолютно та же болячка, что и ГОСТа: 64-битный блок.


      1. mejedi
        27.05.2015 09:50

        Начиная с TLS1.1 при использовании шифра в режиме CBC для шифрования каждого блока используется независимый IV, передается явно и лежит в начале зашифрованного блока. Тем самым решая проблемы 1 и 3.


        1. ivlad Автор
          27.05.2015 10:50
          +1

          Проблему 3 это не решает, потому, что запрос помещается в один TLS record, и его распаралелить нельзя. А во сколько TLS records поместится ответ — depends. Это неудобно. И все это не отменяет принципиально проблемы CBC.

          И не отменяет того, что есть браузеры с максимум TLS1.0 (впрочем, они и режимы GCM не умеют).

          Я не говорю, что CBC плох до неприемлемости — если бы мы так считали, не держали бы его у себя. Но у него, как у режима есть недостатки в сравнении с другими режимами. Их можно компенсировать реализацией, но они остаются. Я сам в общем–то долго противился AEAD, дубовая схема с отдельным HMAC выглядит более понятной и потому — более надежной: сначала проверяешь HMAC и только если он сошелся, делаешь что–то еще. Но жизнь внесла свои коррективы и я соглашусь с Адамом Ленгли — «everything less than TLS 1.2 with an AEAD cipher suite is cryptographically broken».


          1. Yan169
            27.05.2015 12:38

            На сколько я понимаю CBC имеет проблемы в плане безопасности именно в контексте реализации в SSL/TLS, а именно потому, что там MAC then CBC.
            Реализация AES в режиме CBC then MAC со случайным IV для каждого record, отдельными ключами для шифрования/MAC, и надежной hash-функцией для HMAC выявленных проблем не имеет. Верно?


          1. mejedi
            27.05.2015 13:07

            Возможно я не прав, но мне кажется что параллелизация для AEAD шифров достигается за счет одновременного шифрования соседних блоков на разных процессорах, то есть полностью аналогично CBC. Такие выводы я делаю, исходя из RFC5288 секция 6.2.

            В этом разделе говорится про выбор nonce explicit (фактически кусок iv) при использовании нескольких процессоров. Поскольку nonce explicit имеет смысл только на уровне законченного блока, я делаю вывод, что просто независимо шифруются соседние блоки.


    1. d00kie
      26.05.2015 22:22

      CBC вообще не очень надежен в случае атак с выбором шифртекстом.


  1. grossws
    26.05.2015 22:42
    +1

    Ещё неплохие рекомендации у Мозиллы: wiki.mozilla.org/Security/Server_Side_TLS. Правда, они пишут под довольно широкий набор случаев (там, например, есть DSS для аутентификации, который в сертификатах встречается редко)


    1. MyHabrahabr
      31.05.2015 19:56

      Кстати, в 2015 году ни Chrome, ни Safari, ни сам Firefox не поддерживают DSS, только Explorer остался.


  1. MyHabrahabr
    31.05.2015 18:46
    +2

    Затем идет два варианта с шифрованием 3DES: их мы сохраняем в первую очередь для браузеров Internet Explorer на Windows XP с установленным SP3. Internet Explorer использует системную библиотеку Schannel, и в XP с SP3 наконец появилась поддержка 3DES — устаревшего, но все еще устойчивого алгоритма шифрования. Наконец, для несчастных с Internet Explorer 6 на XP мы сохраняем шифры RC4 — других вариантов на этой платформе просто нет. При этом мы осознаем вероятность того, что этот шифр уязвим, поэтому доступен он только в случае хендшейка по протоколу SSLv3. Если клиент подключается с более современным протоколом — TLS 1.0, TLS 1.1 или TLS 1.2 — ciphersuite на основе RC4 не предлагается.
    Интересно, как Service Pack 3 добавляет поддержку 3DES, если в это время уже аппаратное ускорение AES в процессорах вводят? Наверно, просто перепутали с хотфиксом, который добавляет поддержку AES в Windows Server 2003, всё это в одно и то же время происходило.

    XP даже не первая Windows с поддержкой 3DES из коробки, и у неё поддерживаемые наборы шифров никогда не менялись.


  1. MyHabrahabr
    31.05.2015 20:16
    +1

    Впрочем, по моей личной оценке, сайтом с самыми плохими ciphersuites в интернете был сайт Госуслуг правительства Москвы login.mos.ru. В свое время он предлагал ciphersuite TLS_NULL_WITH_NULL_NULL — то есть без аутентификации и без шифрования. Впрочем, сейчас приняты меры: задержка на установку TLS соединения с sslabs.com установлен таким образом, что сканер отваливается по таймауту. Но и ciphersuites поправлены, хотя высшим приоритетом стоят RC4-MD5, RC4-SHA и 3DES-SHA, в списке можно найти ECDH — это можно проверить вручную командой openssl s_client с ключом -cipher.
    Я с этим сервером уже полтора месяца маюсь. Результаты сканирования доступны здесь: github.com/ssllabs/ssllabs-scan/issues/109
    Приоритет совсем наоборот, наивысший 256-битный AES, затем 3DES, затем 128-битный AES, в самом низу RC4.
    Если нужна поддержка IE6 на XP, можно включить RC4
    Зачем включать RC4, использование которого запрещено, если даже Windows NT 4.0 поддерживает 3DES?


    1. ivlad Автор
      31.05.2015 21:15
      +1

      Зачем включать RC4, использование которого запрещено, если даже Windows NT 4.0 поддерживает 3DES?
      А, да, это я мутно выразился, извините. Нужно поправить статью в этом месте. Спасибо за внимательность. :)

      IE6 умеет по умолчанию только SSLv3 (TLS 1.0 включается где-то в настройках, AFAIR). То есть, у нас две проблемы, на самом деле: ciphesuites и версии SSL/TLS. С SSLv3 и TLSv1 использование блочных шифров открывает уязвимость BEAST. Поэтому если нужно поддерживать IE6, приходится только для SSLv3 делать доступным RC4.

      У нас балансер специальным образом запатчен: если подключиться к тему с SSLv3, то RC4 доступен, а если с любым TLS — то нет.

      Что касается login.mos.ru, главный анекдот про TLS_NULL_WITH_NULL_NULL все-таки. Возможно, они меняют настройки. Когда я пробовал их вручную проверить, первым выбирался RC4. Но такого хозяйства много, так что это уже не очень занимательно.