Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validate RRSIG with PHP using openssl

I'm trying to do a RRSIG validation, I'm trying to use the openssl lib in PHP. But I'm having a problem to pass the public key to the openssl_verify function.

This is a base code, using the Net/DNS2 library to do a DNS query with DNSSEC option. and get the DNSKEY and 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;

I get this error messages,

when using:

$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

so i tried adding the BEGIN/END headers

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

And got this error messages,

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

So it seems I'm feeding the function the wrong format, I'm still googling but any help would be welcome.

Eventually I like to validate the signature with:

openssl_verify($data, $signature, $public_key_res, 'RSA-SHA256');
like image 574
Rabin Avatar asked May 09 '17 11:05

Rabin


1 Answers

Short answer:

If you just need the capability in PHP, you can just use https://github.com/metaregistrar/php-dnssec-validator .

Long Answer:

The reason you can't load the KEY data is because it's in a slightly different format. According to rfc3110:

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

Whereas RSA public keys are a bit more complex -- aside from the exponent and modulus, you need to prefix it with the correct OID as such (2nd answer).

After that the process is a bit gnarly:

  1. Get the RRSIG record to get the signature and key tag (to determine which key to use)

  2. Use the public keys from the correct DNSKEY RR to verify the signature against.

There's also a process described here (in python)

like image 189
aljo f Avatar answered Oct 03 '22 17:10

aljo f