2017-05-09 31 views
7

我想做一个RRSIG验证,我想在PHP中使用openssl库。但是我有一个问题将公钥传递给openssl_verify函数。验证RRSIG与PHP使用openssl

这是一个基本代码, 使用Net/DNS2库来执行带有DNSSEC选项的DNS查询。 并获得DNSKEY和RRSIG。

<?php 

require_once 'Net/DNS2.php'; 

$r = new Net_DNS2_Resolver(array('nameservers' => array('127.0.0.1'))); 
$r->dnssec = true; 

try { 
     $result = $r->query('ip4afrika.nl', 'DNSKEY'); 

} catch(Net_DNS2_Exception $e) { 

     echo "::query() failed: ", $e->getMessage(), "\n"; 
     die(); // 
} 

// print_r($result->answer); 

$public_key_bin = base64_decode($result->answer[0]->key) ; 
$public_key_str = $result->answer[0]->key; //echo $public_key_str; die(); 
// $public_key_res = openssl_x509_parse($public_key_bin); 
$public_key_res = openssl_x509_read($public_key_str); 
// $public_key_res = openssl_pkey_get_public($public_key_str); 

while ($msg = openssl_error_string()) echo $msg . PHP_EOL; 

我收到此错误信息,

时使用:

$public_key_res = openssl_x509_read($public_key_str); 

PHP Warning: openssl_x509_read(): supplied parameter cannot be 
coerced into an X509 certificate! in /src/Net_DNS2-1.4.3/i.php on line 
34 PHP Stack trace: PHP 1. {main}() /src/Net_DNS2-1.4.3/i.php:0 PHP 
2. openssl_x509_read() /src/Net_DNS2-1.4.3/i.php:34 error:0906D06C:PEM routines:PEM_read_bio:no start line 

所以我尝试添加BEGIN/END头

$public_key_str = '-----BEGIN CERTIFICATE-----' . PHP_EOL . $result->answer[0]->key . PHP_EOL . '-----END CERTIFICATE-----' ; 

,并得到该错误消息,

error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag 
error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error 
error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib 

因此,我似乎喂了功能错误的格式,我仍然使用谷歌搜索,但任何帮助将受到欢迎。

最后,我想用验证签名:

openssl_verify($data, $signature, $public_key_res, 'RSA-SHA256'); 
+0

难道你看@ http://php.net/manual/en/function.openssl-verify.php。他们有很好的例子 –

+0

是的,我做了@E_p,我的问题是如何将我从DNS查询中获得的密钥传递给函数,无论我尝试使用哪种格式,我都会在某种方式中得到有关密钥格式不正确的错误。 – Rabin

+0

是否有可能,当你获得密钥时,它有额外的空白或其他可以创建该问题的东西? –

回答

0

PHP_EOL是平台,不知道是什么平台,你正在测试这个代码,但尝试'\n'明确更换不变。看看是否有帮助。

+0

没有任何不同。 – Rabin

2

简短的回答:

如果你只需要在PHP中的能力,你可以只使用https://github.com/metaregistrar/php-dnssec-validator

龙答:

原因无法加载密钥数据是因为它是在一个稍微不同的格式。据rfc3110

Field    Size 
-----    ---- 
exponent length 1 or 3 octets (see text) 
exponent   as specified by length field 
modulus   remaining space 

而RSA公共密钥是一个有点复杂 - 除了指数和模量,你需要用正确的OID as such (2nd answer)前缀它。

之后,该过程是有点粗糙:

  1. 获取RRSIG记录,以获得签名和密钥标签(以确定使用哪个密钥)

  2. 使用来自公钥正确的DNSKEY RR来验证签名。

还有一个过程描述here(在python)

+0

感谢第三个链接到其他SO帖子非常丰富。我也遇到了Python的实现,但我不明白它,最后一点定义如何确定它是否是一个有效的签名是非常模糊的,PHP也有问题处理这样长的数字,所以这就是原因我想在openssl库中使用build,这应该能够完成这项工作。你能帮我理解如何解析返回的RRSIG和它组成的人吗? – Rabin