2015-03-24 3 views
1

Я использую библиотеку xmlsec, чтобы проверить подпись SAML. Мой код почти идентичен примеру verify4.c, представленному на веб-странице xmlsec.xmlsec library - получить предмет подписания ключа

Я связываюсь с библиотекой xmlsec-openssl, поэтому с помощью openssl в качестве криптовального движка.

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

Однако подпись считается действительной, если она подписана с ЛЮБЫМ сертификатом, который может быть проверен с помощью openssl. Это означает, что кто-то может подделать ответ SAML, просто купив сертификат из доверенного корневого ЦС и используя это, чтобы подписать любой ответ, который они хотят.

Не только это, но линия инструмент xmlsec1 команда при условии, с библиотекой, кажется, делает то же самое:

xmlsec1 --verify --dtd-file saml.dtd --pubkey-cert-pem my_cert.cer sample_saml_assertion.xml 

... 
OK 
SignedInfo References (ok/all): 1/1 
Manifests References (ok/all): 0/0 

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

Если это не удается, могу ли я принять только те сертификаты, которые я указал при проверке подписи?

ответ

0

При написании вопроса я понял, что не пробовал вариант --print-debug для xmlsec1. Когда я попробовал это, я обнаружил, что он действительно распечатает тему и эмитента сертификата, который использовался для проверки подписи.

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

/* If signature is valid, then the list dsigCtx->signKey contains 
    the signing key, data dsigCtx->signKey->dataList contains the certificate */ 
xmlSecPtrListPtr keyDataList = dsigCtx->signKey->dataList; 

/* Iterate through the data list to find the X509 cert */ 
xmlSecSize n = xmlSecPtrListGetSize(keyDataList); 
xmlSecSize i; 
for (i=0; i<n; i++) { 
    xmlSecKeyDataPtr item = xmlSecPtrListGetItem(keyDataList, i); 
    if (xmlSecKeyDataIsValid(item) && xmlSecKeyDataCheckId(item, xmlSecOpenSSLKeyDataX509Id)) { 

     /* Extract openssl cert */ 
     X509* cert = xmlSecOpenSSLKeyDataX509GetKeyCert(item); 
     char cn_buff[256]; 
     if(cert != NULL) { 
      /* Get the CN */ 
      X509_NAME * subject_name = X509_get_subject_name(cert); 
      int nid_cn = OBJ_txt2nid("CN"); 
      X509_NAME_get_text_by_NID(subject_name, nid_cn, cn_buff, 255); 

      /* Here you would compare it to the expected certificate */ 
      fprintf(stdout, "CN=%s\n", cn_buff); 
     } else { 
      fprintf(stdout, "Failed to obtain signing key cert\n"); 
     } 
    } 
} 

Это кажется очень сложный способ получить что-то такое фундаментальное, так что я уверен, что должен быть более простой способ.

 Смежные вопросы

  • Нет связанных вопросов^_^