Почему OpenSSL говорит, что сертификат является доверенным, если он выдан самозаверяющим ненадежным сертификатом? - PullRequest
1 голос
/ 27 февраля 2020

Для теста у меня есть 3 сертификата: один доверенный самоподписанный сертификат root, один ненадежный самоподписанный сертификат и один сертификат, выданный ненадежным самоподписанным сертификатом (поэтому не следует также доверять). Однако, если я проверяю последний сертификат, используя OpenSSL (1.1.1d), он говорит, что он действителен. Я ожидал, что проверка не удастся, поскольку root, к которой она относится, не является доверенной. Что я делаю не так?

Вот фрагмент кода (не обращайте внимания на утечки или отсутствующие проверки, он предназначен только для этой демонстрации):

const char* const rootPem =
"-----BEGIN CERTIFICATE-----\n"
"MIIB3jCCAYSgAwIBAgIJAPHf5UibUrNZMAoGCCqGSM49BAMCMEIxCzAJBgNVBAYT\n"
"AkdCMRAwDgYDVQQIDAdFbmdsYW5kMRIwEAYDVQQKDAlBbGljZSBMdGQxDTALBgNV\n"
"BAMMBFJPT1QwHhcNMjAwMjE5MTc1NDE5WhcNMjEwMjE4MTc1NDE5WjBCMQswCQYD\n"
"VQQGEwJHQjEQMA4GA1UECAwHRW5nbGFuZDESMBAGA1UECgwJQWxpY2UgTHRkMQ0w\n"
"CwYDVQQDDARST09UMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAErwct49VH1jQZ\n"
"kA8bZsENcn5kRjVabz9ZjewKXO1QmjE3Uqz9GjBaaH+H+OsZmVST+NQjX4XF6g/K\n"
"o1BmXoqs+qNjMGEwHQYDVR0OBBYEFO91oq/ncaT3AiZC3q0jHmptro3LMB8GA1Ud\n"
"IwQYMBaAFO91oq/ncaT3AiZC3q0jHmptro3LMA8GA1UdEwEB/wQFMAMBAf8wDgYD\n"
"VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA0gAMEUCIDy3A4BP27GviTbXBtDrxvQD\n"
"0y0KwkjawXTb13euL9YGAiEA583y9AAUagppAejYTDIsurdFdRulUqVzPy6H5JCq\n"
"yb8=\n"
"-----END CERTIFICATE-----\n";

const char* const fakeRootPem =
"-----BEGIN CERTIFICATE-----\n"
"MIIB4zCCAYqgAwIBAgIJAI9ickj5XUpqMAoGCCqGSM49BAMCMEUxCzAJBgNVBAYT\n"
"AkdCMRAwDgYDVQQIDAdFbmdsYW5kMRIwEAYDVQQKDAlBbGljZSBMdGQxEDAOBgNV\n"
"BAMMB0ZBS0VfQ0EwHhcNMjAwMjI3MTAyNjQ2WhcNMjEwMjI2MTAyNjQ2WjBFMQsw\n"
"CQYDVQQGEwJHQjEQMA4GA1UECAwHRW5nbGFuZDESMBAGA1UECgwJQWxpY2UgTHRk\n"
"MRAwDgYDVQQDDAdGQUtFX0NBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMD93\n"
"rwESh/AZLTrvWStRAujiHePnID2zuYnXSkOhh0KiIs+tOyQmQXv16gwYvRF1X0v7\n"
"Q6cWK4pOe1No5U5tlaNjMGEwHQYDVR0OBBYEFGfD4rQgCqDvO1U9Tvg/qVHrIaTn\n"
"MB8GA1UdIwQYMBaAFGfD4rQgCqDvO1U9Tvg/qVHrIaTnMA8GA1UdEwEB/wQFMAMB\n"
"Af8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA0cAMEQCIE+cGjmuzPvPE2Kh\n"
"uyP7mH2k7CBu99nQ9P0X+ecd5uynAiAa2g1+uweZ/lLbrH32dfnvNlfa29uTqVjX\n"
"SEXodEo78Q==\n"
"-----END CERTIFICATE-----\n";

const char* const fakeLeafPem =
"-----BEGIN CERTIFICATE-----\n"
"MIIB6TCCAZCgAwIBAgIRAOzOwVz92cGF99cokc68Gy8wCgYIKoZIzj0EAwIwQjEL\n"
"MAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxEjAQBgNVBAoMCUFsaWNlIEx0\n"
"ZDENMAsGA1UEAwwEUk9PVDAeFw0yMDAyMjcxMDI5MDRaFw0yMTAzMDgxMDI5MDRa\n"
"MEYxCzAJBgNVBAYTAkdCMRAwDgYDVQQIDAdFbmdsYW5kMRIwEAYDVQQKDAlBbGlj\n"
"ZSBMdGQxETAPBgNVBAMMCEZBS0VfQ0ExMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n"
"QgAEOAAD+GG/lNYAYcakWcp3CwT2gMoHH4UZyyzLsr1Ge9QAkEU8eGrdJCwMNA6O\n"
"PVc7+UYPyd8k6opxODOphNKwV6NjMGEwHQYDVR0OBBYEFF+aTSzJFHSFg1r1pNlE\n"
"+1Z6Edi1MB8GA1UdIwQYMBaAFO91oq/ncaT3AiZC3q0jHmptro3LMA8GA1UdEwEB\n"
"/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA0cAMEQCIE7IyY+M\n"
"tXdik8VLsyVJpdgV02VcUpDWECtQ5zBFaqfKAiApHJoxdwGtfyN2gkhcV8uQcjjW\n"
"ccI6BV7gTn/3F8UIsg==\n"
"-----END CERTIFICATE-----\n";

// trusted
BIO* bio = BIO_new(BIO_s_mem());
BIO_write(bio, rootPem, strlen(rootPem));
X509* trusted_root = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
X509_STORE* store = X509_STORE_new();
X509_STORE_add_cert(store, trusted_root);

// untrusted root
bio = BIO_new(BIO_s_mem());
BIO_write(bio, fakeRootPem, strlen(fakeRootPem));
X509* untrusted_root = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
STACK_OF(X509)* untrusted_chain = sk_X509_new_null();
sk_X509_push(untrusted_chain, untrusted_root);

// validation of untrusted cert
bio = BIO_new(BIO_s_mem());
BIO_write(bio, fakeLeafPem, strlen(fakeLeafPem));
X509* untrusted_cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
X509_STORE_CTX* ctx = X509_STORE_CTX_new();
X509_STORE_CTX_init(ctx, store, untrusted_cert, untrusted_chain);
int verified = X509_verify_cert(ctx);

printf("Certificate is %s\n", (verified == 1) ? " VALID" : "NOT VALID");

Я пробовал также передавая ненадежную цепочку, используя X509_STORE_CTX_set0_untrusted, но получил тот же результат.

1 Ответ

1 голос
/ 27 февраля 2020

Похоже, вы не тестируете то, что, по вашему мнению, тестируете.

Добавление следующего в конец своего фрагмента для получения дополнительной информации о ваших сертификатах

#define PRINT_NAMES(cert) \
    printf("\n" #cert " subject name: "); \
    X509_NAME_print_ex_fp(stdout, X509_get_subject_name(cert), 0, 0); \
    printf("\n" #cert " issuer name: "); \
    X509_NAME_print_ex_fp(stdout, X509_get_issuer_name(cert), 0, 0); \
    printf("\n");

PRINT_NAMES(trusted_root);
PRINT_NAMES(untrusted_root);
PRINT_NAMES(untrusted_cert);

результаты в

trusted_root subject name: C=GB, ST=England, O=Alice Ltd, CN=ROOT
trusted_root issuer name: C=GB, ST=England, O=Alice Ltd, CN=ROOT

untrusted_root subject name: C=GB, ST=England, O=Alice Ltd, CN=FAKE_CA
untrusted_root issuer name: C=GB, ST=England, O=Alice Ltd, CN=FAKE_CA

untrusted_cert subject name: C=GB, ST=England, O=Alice Ltd, CN=FAKE_CA1
untrusted_cert issuer name: C=GB, ST=England, O=Alice Ltd, CN=ROOT

Так что untrusted_cert был фактически выдан trusted_root, что объясняет результат.

Чтобы быстро проверить то, что вы намеревались проверить, вы могли бы перевернуть имена два строковых литерала, поэтому определите первый как fakeRootPem, а второй как rootPem. Это сделает ROOT ненадежным и FAKE_CA доверенным для вашего кода и, следовательно, даст желаемый / ожидаемый результат.

...