Генерируем цепочку сертификатов с эллиптическими кривыми при помощи OpenSSL

    график функции y^2 = x^3-x+1Думаю многие слышали о криптографии эллиптических кривых, о том
    что работает она во много раз быстрее RSA и при несоизмеримо меньшей длине ключа обеспечивает несоизмеримо большую стойкость ко взлому. Если не слышали, то можно глянуть на wiki или почитать в книгах А.А. Болотова.
    К сожалению, данный вид шифрования слабо распространен. Я постараюсь объяснить как им пользоваться и поможет мне в этом OpenSSL.

    Чтобы не быть голословным приведу сравнение необходимых длин ключей для обеспечения сравнимой стойкости ко взлому для различных алгоритмов. Нам интересна правая часть.
    Сравнение алгоритмов
    Видно, что популярным сегодня ключам RSA длиной 1024-2048 бит соответствует всего навсего 160-224битный ключ ECC (Elliptic Curve Cryptography)

    Ну а чтобы понять какой RSA тормоз достаточно попробовать сгенерировать самый длинный из предложенных в таблице ключей (и пойти вздремнуть):

    openssl genrsa 15360

    Желающих прикоснуться к «next gen» криптографии, придуманной аж в 1985 году, прошу под кат.

    Перво наперво определимся какой длины ключ нам нужен. В ECC определенной длине ключа соответствуют определенные параметры кривой. Но нам их подбирать не надо, за нас это сделали умные дядьки из NIST.
    Посмотреть список доступных кривых можно командой
    openssl ecparam -list_curves

    Список эта команда выдает внушительный, и если у вас нет определенных предпочтений, выбирайте ту что нравится и больше 160 бит, например одну из самых длинных:
    secp521r1: NIST/SECG curve over a 521 bit prime field

    Создадим папку, например c:\ec\ и будем всё туда складывать. В папку CA всё для корневого сертификата, в папку Client — всё для клиентского сертификата.

    Нам необходимо
    1. Сгенерировать корневой самоподписанный сертификат (CA)
    2. Сгенерировать клиентский сертификат
    3. Подписать клиентский сертификат корневым

    1) Генерируем корневой сертификат.
    1.1) Генерируем ключ для корневого сертификата:
    openssl ecparam -name secp521r1 -genkey -out c:\ec\CA\CA.key

    Получим что то вроде
    -----BEGIN EC PARAMETERS-----
    BgUrgQQAIw==
    -----END EC PARAMETERS-----
    -----BEGIN EC PRIVATE KEY-----
    MIHcAgEBBEIBrtyWCH0+OAZqbr84CLFvsxbB2/AfjKD6+fpXQF5qs7n1yRmxItRH
    vNlylh7dNZEwYwleI5RLQV3pz6p06hgo6c2gBwYFK4EEACOhgYkDgYYABAEx+OTa
    s3/djxFMW7GNcWWVGv5Y7Vwvr2k00gXVyUpSySSudXKSaWYrblBtPKOWRcuHzkq5
    tks3vTKclq3NgPpdjgAPk4ha68UTdX+JI/oK+EMUwCdaCuIYMDeRO1VHByEx+3/1
    XlkYPvEKRkQDLJP22vXE/NEirdZ/WzO6QTWku5q0UQ==
    -----END EC PRIVATE KEY-----
    Вначале идут параметры кривой (её название secp521r1), а потом уже сгенерированный на её основе ключ.

    1.1.1) При желании защищаем его паролем (шифруем по алгоритму AES с длиной ключа 256 бит):
    openssl ec -in c:\ec\CA\CA.key -out c:\ec\CA\ca.protected.key -aes256

    Получаем вот такую красоту (пароль — qwerty):
    -----BEGIN EC PRIVATE KEY-----
    Proc-Type: 4,ENCRYPTED
    DEK-Info: AES-256-CBC,E34E27512B4DCB01524A5F17937DA7D5

    xF7XZyLtpqofqkl0PVCf/1cOEygL82itDrz7k5tVqJLMDYzG9RnTTPwJgOXsZkV1
    dk5MQe9h/ixPkFE/B/Ox1OH5SI4Frb8dgS8mT9mq620A4RJdD6yAZcpicnuyyXma
    1dZ+xoyRiGeHxcnErDJpvA7H6BpIAzinz4lMzY1pz2TXTdGLU+0bK1bMiDFxRvwA
    jyUEsrZA2kZ5v++MZzmxTsJZ6XTCRzeUPhhvNE0VKF8xPSWMEB6WeJPr+rl3zBZ7
    sE71UwiaIddFHkOe3UnlAxjohABpZytUud8uS0Wi+5E=
    -----END EC PRIVATE KEY-----

    2) Генерируем запрос на сертификат. Запрос — это структура из открытого ключа, его хэша и данных о владельце сертификата. Алгоритм хэширования ключа выбираем SHA512:
    openssl req -new -key c:\ec\CA\ca.protected.key -sha512 -out c:\ec\CA\CA.req

    Получаем еще одну красоту:
    -----BEGIN CERTIFICATE REQUEST-----
    MIIBrzCCARACAQAwazELMAkGA1UEBhMCUlUxDzANBgNVBAgMBk1vc2NvdzEPMA0G
    A1UEBwwGTW9zY293MRIwEAYDVQQKDAloYWJyYWhhYnIxCzAJBgNVBAsMAklUMRkw
    FwYDVQQDDBB3d3cuaGFicmFoYWJyLnJ1MIGbMBAGByqGSM49AgEGBSuBBAAjA4GG
    AAQBMfjk2rN/3Y8RTFuxjXFllRr+WO1cL69pNNIF1clKUskkrnVykmlmK25QbTyj
    lkXLh85KubZLN70ynJatzYD6XY4AD5OIWuvFE3V/iSP6CvhDFMAnWgriGDA3kTtV
    RwchMft/9V5ZGD7xCkZEAyyT9tr1xPzRIq3Wf1szukE1pLuatFGgADAKBggqhkjO
    PQQDBAOBjAAwgYgCQgHa0d5nc9UX41jj42lOnv0Hh9EXfROFm7QoUSoKdye7s7uE
    nZPmGTM+h5bRG8Y+hHD3QQyM8vY9TnMVVp0r2xmYHwJCAbE5CTRDoeXf3ZpKUW77
    SpXtPgYEEelkOm3Ua+/0XVoZviBT7wF5nrqTYnMJ2MQtyvKKMCO74qqUiMoudZ7z
    MSgO
    -----END CERTIFICATE REQUEST-----

    3) Финальный шаг. Подписываем наш запрос нашим же закрытым ключом. Подписываться будет не весь запрос, а только его хэш, поэтому мы на предыдущем шаге указывали какой алгоритм хэширования выбрать
    Для этого нам нужно будет
    3.1) Изменить в openssl.cfg в разделе [ CA_default ] dir на «c:/ec» вместо ./DemoCA по умолчанию
    3.2) В папке c:\ec создать 2 файла: пустой index.txt и файл serial, в который записать 01 без пробелов и переносов строк.

    3.3) Выполнить волшебную команду
    openssl ca -days 365 -policy policy_anything -keyfile c:\ec\CA\CA.protected.key -in c:\ec\CA\CA.req -selfsign -out c:\ec\CA\ca.crt -outdir c:\ec\CA

    На вход мы подаем запрос на сертификат, путь до закрытого ключа и говорим, что сертификат будет самоподписанный (-selfsign). На выходе получаем настоящий красивый сертификат (сохранить как ca.crt, потом можно просмотреть средствами windows):
    Certificate:
        Data:
            Version: 3 (0x2)
            Serial Number: 1 (0x1)
            Signature Algorithm: ecdsa-with-SHA1
            Issuer: C=RU, ST=Moscow, L=Moscow, O=habrahabr, OU=IT, CN=www.habrahabr.ru
            Validity
                Not Before: Jun 11 05:12:03 2010 GMT
                Not After: Jun 11 05:12:03 2011 GMT
            Subject: C=RU, ST=Moscow, L=Moscow, O=habrahabr, OU=IT, CN=www.habrahabr.ru
            Subject Public Key Info:
                Public Key Algorithm: id-ecPublicKey
                    Public-Key: (521 bit)
                    pub:
                        04:01:31:f8:e4:da:b3:7f:dd:8f:11:4c:5b:b1:8d:
                        71:65:95:1a:fe:58:ed:5c:2f:af:69:34:d2:05:d5:
                        c9:4a:52:c9:24:ae:75:72:92:69:66:2b:6e:50:6d:
                        3c:a3:96:45:cb:87:ce:4a:b9:b6:4b:37:bd:32:9c:
                        96:ad:cd:80:fa:5d:8e:00:0f:93:88:5a:eb:c5:13:
                        75:7f:89:23:fa:0a:f8:43:14:c0:27:5a:0a:e2:18:
                        30:37:91:3b:55:47:07:21:31:fb:7f:f5:5e:59:18:
                        3e:f1:0a:46:44:03:2c:93:f6:da:f5:c4:fc:d1:22:
                        ad:d6:7f:5b:33:ba:41:35:a4:bb:9a:b4:51
                    ASN1 OID: secp521r1
            X509v3 extensions:
                X509v3 Basic Constraints:
                    CA:FALSE
                Netscape Comment:
                    OpenSSL Generated Certificate
                X509v3 Subject Key Identifier:
                    3D:FF:46:92:1C:7E:C1:F3:84:D0:26:BA:CD:5D:AD:25:B8:CC:DE:44
                X509v3 Authority Key Identifier:
                    keyid:3D:FF:46:92:1C:7E:C1:F3:84:D0:26:BA:CD:5D:AD:25:B8:CC:DE:44

        Signature Algorithm: ecdsa-with-SHA1
            30:81:88:02:42:01:bf:ca:f1:4c:51:85:b4:65:26:de:eb:14:
            ee:07:a1:1f:97:1d:35:1a:c3:61:8a:82:97:96:7b:f4:d4:95:
            73:4d:84:d2:78:b2:35:fd:72:05:ea:6d:a4:49:e1:18:a0:ff:
            13:60:7e:b0:67:ba:7f:cd:8b:ef:15:a6:5d:30:a3:48:9c:02:
            42:01:53:27:2c:2c:b9:79:b1:0f:9a:c3:f6:a0:c9:dc:82:cb:
            2f:3c:d8:0a:c1:53:d7:3c:37:af:54:39:78:de:ae:d9:d7:55:
            6f:de:cc:9c:75:cf:d5:8e:8e:cc:2d:0c:da:d1:be:c5:8d:2d:
            2b:68:94:9d:0d:8c:89:aa:b9:1d:e8:a2:05
    -----BEGIN CERTIFICATE-----
    MIICxjCCAiigAwIBAgIBATAJBgcqhkjOPQQBMGsxCzAJBgNVBAYTAlJVMQ8wDQYD
    VQQIDAZNb3Njb3cxDzANBgNVBAcMBk1vc2NvdzESMBAGA1UECgwJaGFicmFoYWJy
    MQswCQYDVQQLDAJJVDEZMBcGA1UEAwwQd3d3LmhhYnJhaGFici5ydTAeFw0xMDA2
    MTEwNTEyMDNaFw0xMTA2MTEwNTEyMDNaMGsxCzAJBgNVBAYTAlJVMQ8wDQYDVQQI
    DAZNb3Njb3cxDzANBgNVBAcMBk1vc2NvdzESMBAGA1UECgwJaGFicmFoYWJyMQsw
    CQYDVQQLDAJJVDEZMBcGA1UEAwwQd3d3LmhhYnJhaGFici5ydTCBmzAQBgcqhkjO
    PQIBBgUrgQQAIwOBhgAEATH45Nqzf92PEUxbsY1xZZUa/ljtXC+vaTTSBdXJSlLJ
    JK51cpJpZituUG08o5ZFy4fOSrm2Sze9MpyWrc2A+l2OAA+TiFrrxRN1f4kj+gr4
    QxTAJ1oK4hgwN5E7VUcHITH7f/VeWRg+8QpGRAMsk/ba9cT80SKt1n9bM7pBNaS7
    mrRRo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVy
    YXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUPf9Gkhx+wfOE0Ca6zV2tJbjM3kQw
    HwYDVR0jBBgwFoAUPf9Gkhx+wfOE0Ca6zV2tJbjM3kQwCQYHKoZIzj0EAQOBjAAw
    gYgCQgG/yvFMUYW0ZSbe6xTuB6Eflx01GsNhioKXlnv01JVzTYTSeLI1/XIF6m2k
    SeEYoP8TYH6wZ7p/zYvvFaZdMKNInAJCAVMnLCy5ebEPmsP2oMncgssvPNgKwVPX
    PDevVDl43q7Z11Vv3sycdc/Vjo7MLQza0b7FjS0raJSdDYyJqrkd6KIF
    -----END CERTIFICATE-----

    .

    Готово! Теперь давайте сгенерируем клиента.

    Шаги 1-2 очень похожи. Отличаются только пути:
    openssl ecparam -name secp521r1 -genkey -out c:\ec\Client\Client.key
    openssl ec -in c:\ec\Client\Client.key -out c:\ec\Client\Client.protected.key -aes256
    openssl req -new -key c:\ec\Client\Client.protected.key -sha512 -out c:\ec\Client\Client.req

    Шаг 3 отличается кроме путей тем, что на вход мы подаем сертификат CA, закрытый ключ CA, клиентский запрос и убираем -selfsign
    openssl ca -days 365 -policy policy_anything -keyfile c:\ec\CA\CA.protected.key -cert c:\ec\CA\CA.crt -in c:\ec\Client\Client.req -out c:\ec\Client\Client.crt -outdir c:\ec\Client


    Всё! Можно установить CA.crt в хранилище доверенных корневых сертификатов, открыть Client.crt и наслаждаться тем, что все работает (не обращайте внимания на небольшую ругань относительно корневого сертификата, там видимо нужно еще какие то расширения указать)

    Теперь немного о минусах:
    1. По умолчанию не поддерживается в XP. Возможно есть альтернативные security провайдеры
    2. Не всеми браузерами все кривые поддерживаются даже на Vista\7. IE умеет почти всё, Chrome вообще всё, а Opera ничего.


    Протестировать браузер на совместимость с такими сертификатами можно, например на сайте Fedora.

    Have fun!


    UPD:
    Архив содержимого папки ec доступен тут
    Поделиться публикацией

    Комментарии 27

      +3
      Спасибо, открыл для себя «Эллиптическую криптографию».
        +3
        немного непривычно видеть
        openssl ec -in c:\ec\Client\Client.key
        ни разу не приходилось openssl под окнами использовать.
        А за ликбез спасибо, знать-то знал про метод, да как-то всё rsa хватало.
          +1
          Вы молодец) Криптография это круто, жаль что толком в ней разбирается мало людей.
            +4
            Я просто параноик )
            0
            А какое сравнение скоростей потокового шифрования?
              +2
              Вы немного путаете. Эллиптикой (ровно как и RSA) ничего не шифруется. Они используются для согласования общего ключа, который уже используется в каком нибудь быстром симметричном алгоритме типа AES. Ну и для ЭЦП конечно.
                0
                Извиняюсь -)) Понял
              +20
              Вот ТАКИЕ статьи я хочу видеть на хабре, ощущается уровень. Может мне кажется, но раньше таким и был хабр, пока его не засрали и не сделали новостной лентой
                –7
                хабр уже тот :)
                  –9
                  хабр уже не торт

                  :)
                –2
                Вы защитили нас от НЛО!:)
                  –2
                  А на мой взгляд для параноиков безопасности все же лучше использовать белый шум, можно использовать шум от китайского микрофона и т.д. Тут однозначный рандом получим, а не результат какой-либо функции. Ведь функция зачастую занижает конечную ширину ключа. Еще как вариант, использовать слабенькую звуковую карту, у которой выход закинуть на вход (со знакомым так делали, получилось очень хорошо, нужен высокий уровень сигнала или большая чувствительность). Скорость генерации ключей очень высокая, добавив guid к последовательности мы можем гарантировать еще большую уникальность ключа. С другой стороны нет до сих пор звук никто и не пытается использовать и нет готовых полноценных решений.
                    0
                    Проблема одноразовых блокнотов (а вы описали одноразовый блокнот) в том, что
                    1) ключ=размеру сообщения (каждый байт ключа ксорится с байтом сообщения)
                    2) Этот ключ надо каким то образом доставить получателю
                    Зато да, это единственный алгоритм который НЕВОЗМОЖНО взломать при хорошем ГСЧ
                    Можно конечно записать один шум на две болванки и развести их по континентам, но это ессно гемор.
                      0
                      Не совсем то, используется то асиметричный алгоритм, просто белым шумом генерируется закрытый ключ. Ключи генерируются пачками на транзакции со стороны сервера, получилось в итоге довольно интересно. Собирали статистику по качеству генерации, вообще повторов каких-либо не обнаруживается, даже коротких последовательностей.
                        0
                        нельзя просто взять кусок оцифрованного шума и сказать «это — закрытый ключ». Шум в таком случае может использоваться лишь как часть механизма инициализации. Ключ ведь считается, подбираются параметры и.т.д
                          0
                          Согласен. Так в конечной реализации и есть.
                        0
                        ну кстати нам на курсах криптографии читали, что так и делается. Дядечка с чемоданом, который прикован к руке наручниками перевозит таки кучу носителей с одноразовым блокнотом. Мне тогда эта мысль казалась фантастической, но говорят, у нас в РФ это используется.
                      0
                      Только надо обязательно ПРЕДУПРЕЖДАТЬ, что пока не стоит такое крипто использовать в потенциально публичных сервисах. Потому что, например, не на всех почтовых серверах (особенно в каких-нибудь солидных конторах, где админы работают по принципу 'не сделать бы хуже') стоят достаточно свежие версии OpenSSL, но при этом в настройках у этих серверов написано, что передаче сообщения надо пробовать делать STARTTLS.

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

                      Вот. Так что, для своих внутренних нужд вроде openvpn или там сертефикатов для imap или jabber эллиптические кривые можно использовать, но для всяких публичных сервисов, лучше не стоит.
                        0
                        Тьфу, блин. Прошу прощения за свой русский.

                        передаче сообщения надо пробовать делать STARTTLS. — при передаче сообщения…

                        сделать STARTTLS в представлении сервера — … в представлении вашего сервера

                        Сообщения к вам не доходят — Письма к вам не доходят…
                        +1
                        годная и интересная статья. ради таких и читаю хабр :)
                          0
                          Хм.
                          А что известно про криптостойкость этого самого ECC? Wiki что-то молчит. Были ли вообще какие-то специальные исследования на эту тему?
                            0
                            В русской вики написано, 112 бит — наибольший публично взломанный ключ при нечетной характеристике поля, 109 для характеристики 2. Время — 3.5 мес. и 17 мес. соответственно.
                              0
                              Я как-то ни разу не впечатлён такой стойкостью. А это его ещё не начали серьёзно ломать.
                                0
                                Ну, за 3 года 768-, битный RSA тоже расшифровали. Я думаю сложность расшифровки растет экспоненциально, так со стойкостью, а думаю, всё нормально. Тем более, что рекомендуется выбирать ключи >160 бит и скорость алгоритма, как я понял, намного выше, так что можно без проблем генерировать и длинные ключи.
                            0
                            Хотелось бы также увидеть сравнения по производительности и длине ключа с алгоритмом ГОСТ Р 34.10-2001, также основанным на эллипт. кривых, который для нашей страны является актуальным (тем более в OpenSSL он также присутствует с последних версий, однако не поддерживается стандартным образом в ОС и браузерах).

                            Также было бы неплохо представить сравнительные графики производительности по генерации ключевой пары, цифровой подписи и проверки, учитывая разные длины ключей и разные объемы подписываемой информации.
                              0
                              Хм, а не известно, как с поддержкой данного алгоритма у jabber-клиентов?
                                0
                                Если они используют OpenSSL, то вполне возможно, что да. Надо смотреть

                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                Самое читаемое