Как стать автором
Обновить

Валидируем X509 сертификат с OpenSSL C++

Уровень сложностиПростой
Время на прочтение3 мин
Количество просмотров5K

Данная статья является логическим продолжением статьи про генерацию сертификата. В ней мы рассмотрим, как мы можем провалидировать сертификат используя OpenSSL и C++.

В OpenSSL, для работы с сертификатами используется понятие storage. Давайте создадим его используя X509_STORE_new();

std::unique_ptr<X509_STORE, decltype(&::X509_STORE_free)> store(
  X509_STORE_new(), &::X509_STORE_free);

Далее, нам нужно "заполнить" наше хранилище сертификатами, которыми мы планируем проверять наш целевой сертификат. Если наш сертификат подписан сертификатом, который уже находится в trusted storage, то нам достаточно вызвать лишь одну функцию - X509_STORE_load_path(). В нее необходимо передать указатель на наш сторадж, а также полный путь к сертификатам. Для линукса такой путь может быть: /etc/ssl/certs.

bool addCAPath(X509_STORE* store, const char* path) {
    return X509_STORE_load_path(store, path) == 1;
}

Также, в OpenSSL есть возможность загрузить файл с несколькими сертификатами, используя функцию X509_STORE_load_file(). В нее также передаем указатель на сторадж, а также имя файла. Например, /etc/ssl/certs/ca-certificates.crt.

bool addCABundle(X509_STORE* store, const char* path) {
    X509_STORE_load_file(store, path) == 1;
}

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

bool addCert(X509_STORE* store, X509* cert) {
    return X509_STORE_add_cert(store, cert) == 1;
}

Далее, мы можем начинать процесс валидации сертификата. Для начала, нам необходимо сконструировать контекcт X509_CTX. К слову сказать, почти все новое АПИ OpenSSL 3.0.0 строится вокруг различных контекстов. Чтобы не мучиться с управлением ресурсами, создадим нашему контексту специальный делитор, состоящий из вызова двух функций: очистить контекст и освободить память под контекст.

auto storeContextDeleter = [](X509_STORE_CTX* ctx) {
    X509_STORE_CTX_cleanup(ctx);
    X509_STORE_CTX_free(ctx);
};

std::unique_ptr<X509_STORE_CTX, decltype(storeContextDeleter)>
        storeCtx(X509_STORE_CTX_new(), storeContextDeleter);
if (storeCtx == nullptr) {
    std::cerr << "Failed X509_STORE_CTX_new" << std::endl;
    return -1;
}

Итак, мы создали контекст, далее, мы можем выставить колбек, который будет вызываться OpenSSL после валидации сертификата. Вы спросите - зачем это нужно, а нужно это затем, что в этом колбеке мы можем подавить различные ошибки OpenSSL, чтобы валидация считалась успешной. Например, если OpenSSL вернул нам в этом колбеке ошибку - X509_V_ERR_CERT_HAS_EXPIRED, что значит, что сертификат уже "протух", но мы по своим причинам хотим разрешить такое непотребство, то мы можем на нее просто вернуть OK.

static int verifyCallback(int ok, X509_STORE_CTX *ctx) {
    const int err = X509_STORE_CTX_get_error(ctx);
    if (err != 0) {
        std::cerr << "Failed to verify cert " << err << std::endl;
    }
    return ok;
}
///
X509_STORE_set_verify_cb_func(store.get(), verifyCallback);

Далее, инициализируем наш контекст и вызываем функцию валидации:

if (X509_STORE_CTX_init(storeCtx.get(), store.get(), cert.get(), nullptr) == 0) {
    std::cerr << "Failed X509_STORE_CTX_init" << std::endl;
    return -1;
}

if (X509_verify_cert(storeCtx.get()) != 1) {
    std::cerr << "Failed X509_verify_cert" << std::endl;
    return -1;
}

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

Теги:
Хабы:
Всего голосов 3: ↑1 и ↓2-1
Комментарии6

Публикации

Истории

Работа

QT разработчик
4 вакансии
Программист C++
106 вакансий

Ближайшие события

7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань