2013-11-26 3 views
3

Я работаю над ниже вещи:Проверка сертификатов SSL с использованием OpenSSL в PHP

Generate CSR(Certificate Signing Request) 
Upload SSL Certificates 

Для генерации сертификата SSL Я использую что-то вроде:

 $privkey = openssl_pkey_new(); 
     $csr = openssl_csr_new($dn, $privkey); 
     $sscert = openssl_csr_sign($csr, null, $privkey, $days); 
     openssl_csr_export($csr, $csrout); 
     openssl_pkey_export($privkey, $pkeyout, $_POST['password']); 
     openssl_pkey_export_to_file($privkey, "<path/to/store/server.key>"); 
     openssl_csr_export_to_file($csr, "/tmp/".<domain-name>.".csr"); 

Теперь, используя этот запрос CSR, я могу для генерации (domain-name.cer), (DigitalCert.cer).

Теперь, когда я загружаю эти (.cer) сертификаты, мне нужно проверить эти сертификаты.

Причина: Кто-то сгенерировал эти сертификаты, скажем, «a.com» и пытается загрузить на «b.com». это не должно происходить, поэтому я хочу проверить сертификаты загруженных SSL.

В PHP есть

$ ок = openssl_verify ($ данные, $ подпись, $ pubkeyid);

но я не могу получить то, что будет обрабатываться как $ data, $ signature и $ pubkeyid на основе вышеупомянутого процесса генерации сертификата.

+1

http://stackoverflow.com/q/19955922/569976 Я думаю, что делает то, что вы пытаясь сделать? – neubert

+0

В вашем коде выше, я не уверен, почему вы экспортируете CSR вместо $ sscert. Используете ли вы выходной CSR для создания другого сертификата? Метод openssl_verify() обычно не используется для проверки подписей сертификатов. – gtrig

+0

thanks @gtrig, я использую выходной CSR для создания другого сертификата. –

ответ

0

это, как я могу это сделать ...

system('openssl x509 -noout -modulus -in '.$crt.' | openssl md5', $crt_md5); 
system('openssl rsa -noout -modulus -in '.$key.' | openssl md5', $key_md5); 

if($crt_md5 != $key_md5){ 
echo 'BAD'; 
} 
+0

Спасибо @dagon за быстрый ответ .. но как я могу получить $ key .. это открытый ключ или закрытый ключ .. и $ key - это действительный ключ или его ссылка. Спасибо. –

+0

Я пробовал с помощью вышеприведенного фрагмента и предположил, что это закрытый ключ (контент не ссылка) .. он всегда давал мне матч. Я сгенерировал сертификат из одного домена и попытался загрузить и проверить вышеуказанный код для другого домена. В идеале это должно дать «BAD». Но это дало мне «ХОРОШО» в другом состоянии. Я повторил $ ​​crt_md5 и $ key_md5, оба равны «1», поэтому дал мне «Хороший результат». Я использовал закрытый ключ из 1 домена и сертификата другого домена. Я также пробовал с CSR MD5, все еще получил матч. Почему это так? –

+0

@ VirenH.Ajmera, закрытый ключ и открытый ключ будут иметь одинаковый модуль.Как вы генерируете сертификаты домена? Используете ли вы один и тот же закрытый ключ для создания CSRs/Certificates? Если это так, то вы всегда получите совпадение с этой проверкой. Модуль частного ключа совпадает с модулем открытого ключа, который вводится в CSR и, в конечном счете, в сертификат. Поэтому, если вы используете один и тот же закрытый ключ для нескольких сертификатов, все они будут иметь один и тот же открытый ключ и будут иметь одинаковый модуль. – gtrig

0

Это работает для меня

$crt_md5=exec('openssl x509 -noout -modulus -in /path/to/domain.crt/ | openssl md5 | sed "s/^.* //"'); 
$key_md5=exec('openssl rsa -noout -modulus -in /path/to/server.key | openssl md5 | sed "s/^.* //"'); 

if($crt_md5 != $key_md5){ 
    echo 'BAD'; 
} 
else{ 
    echo "GOOD"; 
} 

SED "s /^.* //" - будут удалены (STDIN) = вещь от выхода, так что вы получите точную md5

снабжать струной, тетивой и т.п.
2

Проверьте это: Verify SMTP in PHP

<?php 
$server = "smtp.gmail.com";  // Who I connect to 
$myself = "my_server.example.com"; // Who I am 
$cabundle = '/etc/ssl/cacert.pem'; // Where my root certificates are 

// Verify server. There's not much we can do, if we suppose that an attacker 
// has taken control of the DNS. The most we can hope for is that there will 
// be discrepancies between the expected responses to the following code and 
// the answers from the subverted DNS server. 

// To detect these discrepancies though, implies we knew the proper response 
// and saved it in the code. At that point we might as well save the IP, and 
// decouple from the DNS altogether. 

$match1 = false; 
$addrs = gethostbynamel($server); 
foreach($addrs as $addr) 
{ 
    $name = gethostbyaddr($addr); 
    if ($name == $server) 
    { 
     $match1 = true; 
     break; 
    } 
} 
// Here we must decide what to do if $match1 is false. 
// Which may happen often and for legitimate reasons. 
print "Test 1: " . ($match1 ? "PASSED" : "FAILED") . "\n"; 

$match2 = false; 
$domain = explode('.', $server); 
array_shift($domain); 
$domain = implode('.', $domain); 
getmxrr($domain, $mxhosts); 
foreach($mxhosts as $mxhost) 
{ 
    $tests = gethostbynamel($mxhost); 
    if (0 != count(array_intersect($addrs, $tests))) 
    { 
     // One of the instances of $server is a MX for its domain 
     $match2 = true; 
     break; 
    } 
} 
// Again here we must decide what to do if $match2 is false. 
// Most small ISP pass test 2; very large ISPs and Google fail. 
print "Test 2: " . ($match2 ? "PASSED" : "FAILED") . "\n"; 
// On the other hand, if you have a PASS on a server you use, 
// it's unlikely to become a FAIL anytime soon. 

// End of maybe-they-help-maybe-they-don't checks. 

// Establish the connection 
$smtp = fsockopen("tcp://$server", 25, $errno, $errstr); 
fread($smtp, 512); 

// Here you can check the usual banner from $server (or in general, 
// check whether it contains $server's domain name, or whether the 
// domain it advertises has $server among its MX's. 
// But yet again, Google fails both these tests. 

fwrite($smtp,"HELO $myself\r\n"); 
fread($smtp, 512); 

// Switch to TLS 
fwrite($smtp,"STARTTLS\r\n"); 
fread($smtp, 512); 
stream_set_blocking($smtp, true); 
stream_context_set_option($smtp, 'ssl', 'verify_peer', true); 
stream_context_set_option($smtp, 'ssl', 'allow_self_signed', false); 
stream_context_set_option($smtp, 'ssl', 'capture_peer_cert', true); 
stream_context_set_option($smtp, 'ssl', 'cafile', $cabundle); 
$secure = stream_socket_enable_crypto($smtp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); 
stream_set_blocking($smtp, false); 
$opts = stream_context_get_options($smtp); 
if (!isset($opts["ssl"]["peer_certificate"])) 
    $secure = false; 
else 
{ 
    $cert = openssl_x509_parse($opts["ssl"]["peer_certificate"]); 
    $names = ''; 
    if ('' != $cert) 
    { 
     if (isset($cert['extensions'])) 
      $names = $cert['extensions']['subjectAltName']; 
     elseif (isset($cert['subject'])) 
     { 
      if (isset($cert['subject']['CN'])) 
       $names = 'DNS:' . $cert['subject']['CN']; 
      else 
       $secure = false; // No exts, subject without CN 
     } 
     else 
      $secure = false; // No exts, no subject 
    } 
    $checks = explode(',', $names); 

    // At least one $check must match $server 
    $tmp = explode('.', $server); 
    $fles = array_reverse($tmp); 
    $okay = false; 
    foreach($checks as $check) 
    { 
     $tmp = explode(':', $check); 
     if ('DNS' != $tmp[0]) continue; // candidates must start with DNS: 
     if (!isset($tmp[1]))  continue; // and have something afterwards 
     $tmp = explode('.', $tmp[1]); 
     if (count($tmp) < 3)  continue; // "*.com" is not a valid match 
     $cand = array_reverse($tmp); 
     $okay = true; 
     foreach($cand as $i => $item) 
     { 
      if (!isset($fles[$i])) 
      { 
       // We connected to www.example.com and certificate is for *.www.example.com -- bad. 
       $okay = false; 
       break; 
      } 
      if ($fles[$i] == $item) 
       continue; 
      if ($item == '*') 
       break; 
     } 
     if ($okay) 
      break; 
    } 
    if (!$okay) 
     $secure = false; // No hosts matched our server. 
} 

if (!$secure) 
     die("failed to connect securely\n"); 
print "Success!\n"; 
// Continue with connection... 
?> 
Смежные вопросы