---
title: '"сани летом" или "почему именно сейчас - самый подходящий момент для добавления key pinning на сайт"'
url: 'https://ky0uraku.xyz/blog/20160217-sani-letom-hpkp'
markdown: 'https://ky0uraku.xyz/blog/20160217-sani-letom-hpkp.md'
date: '2016-02-17'
description: 'Очередной пост в рубрику "на заметку домохозяйке". Для начала - небольшая преамбула, состоящая из нескольких утверждений: Правительство нашей замечательной страны подумывает о создании государственного удостоверяющего центра, в простонародии известного как CA. В декабре прошлого года стал общедост…'
taxonomy:
  tag:
    - tech
    - privacy
  category:
    - articles
---

# "сани летом" или "почему именно сейчас - самый подходящий момент для добавления key pinning на сайт"

  [Тексты](https://ky0uraku.xyz/blog) / 17 февраля 2016   [tech](https://ky0uraku.xyz/blog/tag:tech) [privacy](https://ky0uraku.xyz/blog/tag:privacy)  

Очередной пост в рубрику "на заметку домохозяйке". Для начала - небольшая преамбула, состоящая из нескольких утверждений:

1. Правительство нашей замечательной страны [подумывает](https://meduza.io/news/2016/02/15/v-rossii-sozdadut-gosudarstvennyy-tsentr-po-vydache-ssl-sertifikatov) о создании государственного удостоверяющего центра, в простонародии известного как [CA](https://ru.wikipedia.org/wiki/%D0%A6%D0%B5%D0%BD%D1%82%D1%80_%D1%81%D0%B5%D1%80%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8).
2. В декабре прошлого года стал общедоступен сервис [Let`s Encrypt](https://letsencrypt.org/), позволяющий любому владельцу домена бесплатно получить валидный SSL-сертификат.
3. В данный момент [HPKP](https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning) (RFC 7469) [поддерживается](https://dev.windows.com/en-us/microsoft-edge/platform/status/publickeypinningextensionforhttp) обоими наиболее распространёнными в интернетах браузерами - хромом и фаерфоксом, остальные на подходе.

[![](https://ky0uraku.xyz/blog/20160217-sani-letom-hpkp/hpkp1.webp)](https://ky0uraku.xyz/blog/20160217-sani-letom-hpkp/hpkp1.webp)

Переводя на церковно-славянский - происходит ровно следующее: некоторое время назад осознав, что производительность зомбирования через традиционные для ОПГ "Озеро" каналы (телевидение, радио, газеты) достигла своего потолка и пошла на спад, а весь этот ваш интернет дружно ржёт над нескладными речами говорящих голов из новостей, попутно козля их на чём свет стоит и генерируя терабайты фотожаб, причём анонимно и без смс, неким светлым головам пришла гениальная мысль вступить своими грязными копытами на просторы рунета и навести порядок, всячески недопущая и пресекая, превратив и этот последний уголок свободы слова и обмена мнениями в ту же постапокалиптическую радиоактивную пустыню, коей сейчас является остальное информационное пространство России.

Не будем сейчас озвучивать всю летопись борьбы, закрытия и смены владельцев всех нормальных СМИ, зверства Роскомнадзора и прочие радости последних лет, остановимся только на широко известном феномене, который является, наверное, самой большой занозой в заднице "недопущателей" - широком распространении в интернете различных форм шифрования, опять же, опуская в рамках данного повествования различные VPN-туннели, Tor, i2p и прочие PGP, сосредоточившись на наиболее распространённом виде, используемом повсеместно - HTTPS.

Как всем известно - HTTPS представляет собой механизм транспортного уровня, позволяющий обычным нешифрованным данным протокола HTTP передаваться внутри SSL/TLS. В прикладном смысле - это не даёт возможности прочитать содержание вашего трафика, даже будучи способным перехватить его где-то на пути между вами и сервером назначения (как обычно и происходит на железках всяких СОРМ`ов). Для шифрования и последующей расшифровки передаваемых данных необходимы два ключа - публичный (он же открытый) и приватный. Первый общедоступен и является частью SSL-сертификата сервера, второй - располагается на веб-сервере и не должен быть известен никому, кроме владельца. Для того, чтобы клиенту подтвердить валидность отдаваемого сервером сертификата, используется так называемая "цепочка доверия", которая представляет собой подпись сертификата веб-сервера одним из доверенных центров сертификации (тем самым CA), коих довольно немного и чьи сертификаты обычно уже находятся в хранилищах браузеров или ОС у пользователей.

Вот мы и подошли к самому интересному. следите за руками - в данный момент все центры сертификации находятся за рубежом и неподконтрольны правительству нашей прекрасной страны, поэтому выпустить валидный сертификат для интересующих их сайтов они не могут. Зачем выпускать такие сертификаты? Ответ очевиден - чтобы мочь организовать расшифровку любого HTTPS-трафика, поскольку сормовское оборудование, поставленное у провайдеров вразрыв или на которое зеркалируется трафик - классический пример атаки [MitM](https://ru.wikipedia.org/wiki/%D0%90%D1%82%D0%B0%D0%BA%D0%B0_%D0%BF%D0%BE%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D0%BA%D0%B0) и пока что наступлению оруэлловского 1984 года препятствует только невозможность незаметной подмены SSL-сертификатов.

В этот момент мы незаметно подошли к разгадке того факта, зачем же "светлым головам" понадобился карманный центр сертификации за миллионы вечнозелёных долларов (не будем обращать внимания на их неубедительные отговорки). Всё просто - добившись добавления своего сертификата в хранилища браузеров и операционных систем, у товарищей непущателей появится возможность в любой момент завернуть трафик любого интересующего их человека через свои железки, подсунуть последнему свой сертификат под видом настоящего, а самим спокойно сидеть и разглядывать его пароли и письма в реальном времени. Хочу добавить, что подобное уже происходило с одним из китайских CA, который выпустил сертификаты для гугловских доменов, после чего был дисквалифицирован. Уверен, что наши не наступят на эти грабли и будут использовать свои возможности точечно, для конкретных целей, поэтому и поймать за руку их будет значительно сложнее.

Итого - если российский CA всё-таки будет введён в эксплуатацию и к этому моменту никто не расчехлит долгожданную [табакерку](https://ru.wikipedia.org/wiki/%D0%A3%D0%B1%D0%B8%D0%B9%D1%81%D1%82%D0%B2%D0%BE_%D0%9F%D0%B0%D0%B2%D0%BB%D0%B0_I#.D0.A3.D0.B1.D0.B8.D0.B9.D1.81.D1.82.D0.B2.D0.BE), одно лишь наличие HTTPS-соединения с ресурсом, имеющим валидный сертификат перестанет быть гарантом безопасности передаваемых данных.

Цитируя классика - кто виноват и что же делать? Первый вопрос очевиден, сосредоточимся на втором. Немного забегая вперёд, обрадую аудиторию - выход есть и довольно безболезненный (без регистрации и смс!). Для восстановления вселенской справедливости нам понадобятся две составляющих успеха:

1. Валидный SSL-сертификат для нашего домена, выданный любым неангажированным с ОПГ "Озеро" центром сертификации.
2. Настроенный на веб-сервере key pinning.

Поскольку мы, как приверженцы открытости и прозрачности во всём, предпочитаем опенсорс и бесплатность, сертификат будем получать у Let`s Encrypt, чем убьём сразу двух зайцев - это бесплатно и может быть легко автоматизировано. Процесс неплохо задокументирован на [соответствующем сайте](https://letsencrypt.readthedocs.org/en/latest/), в этом посте данную тему рассусоливать не будем, возможно когда-нибудь потом.

Относительно [key pinning](https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning)`а, он же HPKP, он же RFC 7469 - это гениальный по своей простоте механизм, заключающийся в следующем: веб-сервер при обращении к нему клиента отправляет в ответе специальные заголовки, унутре которых находятся публичные ключи сертификатов (на самом деле не сами ключи, а их хэшированные подписи) и максимальный срок их действия. Клиент, получив эти подписи, сохраняет их, и в дальнейшем при подключении к данному домену по HTTPS, сравнивает подпись полученного SSL-сертификата с той, из заголовка, а при несовпадении начинаются кровь, кишки, расчленёнка, выражающиеся в отказе от подключения и соответствующем сообщении в браузере, а также (и это меня радует больше всего) опционально - в оповещении владельца домена о попытке подмены с приаттаченными сертификатами плохишей. Таким образом, заблаговременно установив себе HPKP, мы получаем возможность палить контору и сохранять тайну переписки, как и записно в Конституции нашей замечательной страны.

Разумеется, существует нюанс. Нюанс проистекает непосредственно из принципа работы HPKP - если вдруг у вас по какой-то причине изменится подпись сертификата, сайт превратится в тыкву. Простейшим случаем такого поведения является плановый перевыпуск SSL-сертификата домена. Именно поэтому весь интернет рекомендует использовать для формирования подписи ключ не конечного сертификата, а одного из промежуточных (intermediate CA) сертификатов удостоверяющего центра. Более того, в RFC чёрным по белому написано, что использоваться должны хотя бы две подписи - основная, работающая с текущим сертификатом, и резервная, для другого сертификата - это может быть, например, подпись ключа другого CA. Ещё более секьюрным и потенциально отказоустойчивым является альтернативный вариант аж с тремя подписями, первая из которых - так же рабочая, а остальные две - подписи публичных ключей двух других ваших сертификатов, ещё не подписанных никакими CA; при необходимости вы берёте один из двух запасных сертификатов и как обычно делается - подписываете его в любом CA, которому доверяете, а поскольку для HPKP используется подпись публичного ключа, а не самого сертификата - изменения сертификата при подписи в CA ничего не поломают.

В завершение - минутка технических подробностей, как всё это вообще провернуть (только основное):

1. Берём OpenSSL, наш сертификат (или не наш, а intermediate) и вынимаем из него публичный ключ, формируя его sha256-подпись, закодированную в base64: ```
    openssl x509 -noout -in certificate.pem -pubkey | openssl asn1parse -noout -inform pem -out public.key
    openssl dgst -sha256 -binary public.key | openssl enc -base64 > public.key.digest
    ```

    На выходе получается нечто подобное: ```
    klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=
    ```
2. Повторяем то же самое для резервных сертификатов.
3. Добавляем в [конфиг веб-сервера](https://developer.mozilla.org/en-US/docs/Web/Security/Public_Key_Pinning#Setting_up_your_webserver_to_include_the_HPKP_header) соответствующего домена заголовки `Public-Key-Pins`, установив `max-age`, не превышающий периода, оставшегося до "протухания" вашего текущего сертификата.
4. Желающие получать уведомления о происках кровавой гэбни могут также указать в параметре `report-uri` URL, в который будут прилетать оповещения о безобразиях в формате JSON: ```
    {
        "date-time": "2014-12-26T11:52:10Z",
        "hostname": "www.example.org",
        "port": 443,
        "effective-expiration-date": "2014-12-31T12:59:59",
        "include-subdomains": true,
        "served-certificate-chain": [
            "-----BEGINCERTIFICATE-----\nMIIAuyg[...]tqU0CkVDNx\n-----ENDCERTIFICATE-----"
        ],
        "validated-certificate-chain": [
            "-----BEGINCERTIFICATE-----\nEBDCCygAwIBA[...]PX4WecNx\n-----ENDCERTIFICATE-----"
        ],
        "known-pins": [
            "pin-sha256=\"dUezRu9zOECb901Md727xWltNsj0e6qzGk\"",
            "pin-sha256=\"E9CqVKB9+xZ9INDbd+2eRQozqbQ2yXLYc\""
        ]
    }
    ```
5. Желающие получать только уведомления, без расчленёнки и криков, могут использовать вместо `Public-Key-Pins` заголовок `Public-Key-Pins-Report-Only`.

Как-то вот так, всех благодарю за внимание.

---

## Navigation

- Parent: [Последние тексты](https://ky0uraku.xyz/blog.md)
- Previous: [Пятидесятое простое число Мерсенна!](https://ky0uraku.xyz/blog/20180103-50-prostoe-chislo-mersenna.md)
