Dns-01 challenge using PHP


#1

Hi All.

I was able to create cretificates using the PHP script

https://github.com/analogic/lescript.

Now i am trying to validate my domain using dns-01 challenge.
I was trying to do that uisng the same script.

For that i made
public $challenge = ‘dns-01’;

Then when i call the challenge, i got below response.

{“type”:“dns-01”,“status”:“invalid”,“error”:{“type”:“urn:acme:error:unauthorized”,“detail”:“Correct
value not found for DNS
challenge”,“status”:403},“uri”:“https://acme-staging.api.letsencrypt.org/acme/challenge/rwacA84nvPu6PjSC3E9sk_R4z-lvm4tJvbZfBpExiUk/30578727",“token”:“kV9xEIGZGkvuAFgAgZ5l3ErYpMkFxfmzCJ3GZlsWoro”,“keyAuthorization”:"kV9xEIGZGkvuAFgAgZ5l3ErYpMkFxfmzCJ3GZlsWoro.ZxQta-m1faIfA7ZBtwtNxXDNb2liAVx6QF8sP2w1jn0”},

Used below code call to call the challenge.

$result = $this->signedRequest_dns(
$challenge_uri, array(
“resource” => “challenge”,
“type” => “dns-01”,
“keyAuthorization” => $payload,
“token” => $token
)
);

Any idea why getting an error with message Correct value not found for DNS challenge.

My challenge with type http-01 works fine, used same code except type
is http-01. But when i change type to dns-01, it’s not working.


#3

The script Lescript.php is entirely based upon the http-01 challenge. In signedRequest() there’s coded explicit for and only for the http-01 challenge.

You used signedRequest_dns() in your piece of code, which is not in the original script.

Did you rewrite that entire function to add the DNS token to your authorative DNS server? Or just add the _dns to the function name?


#4

As you mentioned, Lescript.php is entirely based upon the http-01 challenge.
signedRequest_dns() is not in the original script.

To get dns challenge url, token and payload i used below code.

       //get dns token details
        $dns_challenge = array_reduce($response['challenges'], function ($v, $w) use (&$self) {
            return $v ? $v : ($w['type'] == "dns-01" ? $w : false);
        });
        $dns_token = $dns_challenge['token'];
        $dns_payload = $dns_token . '.' 
                . Base64UrlSafeEncoder::encode(hash('sha256', json_encode($header), true));

       $challenge_uri = $dns_challenge['uri'];

Those details are used in the below request.

$result = $this->signedRequest_dns(
$challenge_uri, array(
“resource” => “challenge”,
“type” => “dns-01”,
“keyAuthorization” => $payload,
“token” => $token
)
);

Anything wrong in the approach?


#5

How do you send the token to your DNS server? I don’t see any DNS provider API nor some manual step.


#6

What i am planning to do is, add two TXT fields.

For eg:

TXT Record Name: _acme-challenge.domain.com
Value: l4GComvOw2CThSwxo_1ROS-q58QV-01sjeefLfLeoMI

TXT Record Name: _acme-challenge.www.domain.com
Value: -9rCtFSF5qjCKv_QUInv0rQf3O5NNV5oEGlCeX-ojPc

Then call the challenge, that’s enough?


#7

If I’m reading the ACME draft closely, it says the following about the dns-01 challenge:

A client responds to this challenge by constructing a key
authorization from the “token” value provided in the challenge and
the client’s account key. The client then computes the SHA-256
digest of the key authorization.

If you compare this with the http-01 challenge (section 7.2 of the draft):

The path at which the resource is provisioned is comprised of the
fixed prefix “.well-known/acme-challenge/”, followed by the "token"
value in the challenge. The value of the resource MUST be the ASCII
representation of the key authorization.

It doesn’t mention the extra SHA-256 step (the hash('sha256'...) currently in the code resembles the generation of the key authorization). So that’s a difference I’m not seeing in your code.

You can also see this difference in existing clients:


#8

Thanks for your quick reply.

So for dns-01, we have to create SHA-256 of the $dns_payload?

//get dns token details
$dns_challenge = array_reduce($response[‘challenges’], function ($v, $w) use (&$self) {
return $v ? $v : ($w[‘type’] == “dns-01” ? $w : false);
});
$dns_token = $dns_challenge[‘token’];
$dns_payload = $dns_token . ‘.’
. Base64UrlSafeEncoder::encode(hash(‘sha256’, json_encode($header), true));

   //SHA-256 of key authorization. Below step is correct?
   $final = hash('sha256',$dns_payload);

   $challenge_uri = $dns_challenge['uri'];

#9

Once you get this worked, please post your entire script.


#10

Yes - please do post the entire script!


#11

Sure,
Still working on it. I would like to know weather any of you have some time to spend with me
to test the code doing.

One issue i am facing now is, even though i added the txt record, i am not getting those values
from the below code.

$result = dns_get_record(“cooloffers.in”);
print_r($result);


#12

Thanks for the reply, i tried as you mentioned. But now i am getting the below error when i try to verify.

Array
(
[type] => urn:acme:error:malformed
[detail] => Unable to update challenge :: provided key authorization was incorrect
[status] => 400
)

Any idea why it’s so?


#13

I got it working :slight_smile:

I will share my code once i complete it, so please wait.


#14

Hi,

Here explained what i did for dns-01 challenge.

http://whmcstools.com/domain-verification-using-lets-encrypt-dns-challenge-type-dns-01/


#15

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.