Im currently developing a perl client. However, DNS-PERSIST-01 doesn't appear in the list of challenges, even on the staging.
Here is my code:
#!/usr/bin/perl
use Net::ACME2;
use Net::ACME2::LetsEncrypt;
use Digest::SHA qw(sha384_hex);
use MIME::Base64;
use Crypt::PK::ECC;
$inpass = $ARGV[0];
$certpassword = encode_base64(pack("H*", "303e0201010430".sha384_hex($inpass)."a00706052b81040022"),"");
$certprivatekey = "-----BEGIN EC PRIVATE KEY-----\n".substr($certpassword, 0, 64)."\n".substr($certpassword, 64, length($certpassword) - 64)."\n-----END EC PRIVATE KEY-----";
$acctpassword = pack("H*", sha384_hex($inpass."-"));
$acct = Crypt::PK::ECC->new();
$acct->import_key_raw($acctpassword, "secp384r1");
$acme = Net::ACME2::LetsEncrypt->new( key => $acct->export_key_pem('private'), environment => 'staging');
$acme->create_account( termsOfServiceAgreed => 1 );
print "Add the following DNS record to your DNS:\n";
print "_validation-persist.YOURDOMAIN.TLD 3600 IN TXT \"letsencrypt.org;accounturi=".$acme->key_id.";policy=wildcard\"\n\n";
@ids = ();
for ($i = 1; $i < $#ARGV + 1; $i++) {
push(@ids, { type => 'dns', value => $ARGV[$i] } );
push(@ids, { type => 'dns', value => "*.".$ARGV[$i] } );
}
$order = $acme->create_order( identifiers => [@ids] );
foreach $dauth ($order->authorizations()) {
$fdauth = $acme->get_authorization( $dauth );
foreach $chtype ($fdauth->challenges()) {
print "FOUND challenge type: ".$chtype->type()." STATUS: " .$chtype->status()."\n";
if ($chtype->type() eq "dns-persist-01") {
print "Found DNS-PERSIST-01 challenge, submitting...\n";
push(@pendingcompletion, $chtype);
}
}
}
However, when running, I get:
root@sebastian-desktop:~/ecctest# ./ecctest.pl sebbe_testar sebbe.eu
Add the following DNS record to your DNS:
_validation-persist.YOURDOMAIN.TLD 3600 IN TXT "letsencrypt.org;accounturi=https://acme-staging-v02.api.letsencrypt.org/acme/acct/280207343;policy=wildcard"
FOUND challenge type: dns-01 STATUS: pending
FOUND challenge type: http-01 STATUS: pending
FOUND challenge type: dns-01 STATUS: pending
FOUND challenge type: tls-alpn-01 STATUS: pending
What im doing wrong? Do I need to do something "special" to get the system to understand I want DNS-PERSIST-01?
I know the DNS-PERSIST-01 isn't live in production yet, but according to this document:
Q1 have passed and DNS-PERSIST-01 should be in staging.
uacme: challenge=dns-persist-01 ident=test.abnoeh.eu.org token=letsencrypt.org key_auth="letsencrypt.org; accounturi=https://acme-staging-v02.api.letsencrypt.org/acme/acct/251051293"
uacme: type 'y' followed by a newline to accept challenge, anything else to skip
n
uacme: challenge=tls-alpn-01 ident=test.abnoeh.eu.org token=ahhr6XnIEl-EnouzuNwNQHPzV97kBmmjV-1Eoy4MxMY key_auth=NnM_E1oQLA731hULHdYVArZw-s_JUgnvkspBuc8is6c
uacme: type 'y' followed by a newline to accept challenge, anything else to skip
n
uacme: challenge=dns-01 ident=test.abnoeh.eu.org token=ahhr6XnIEl-EnouzuNwNQHPzV97kBmmjV-1Eoy4MxMY key_auth=NnM_E1oQLA731hULHdYVArZw-s_JUgnvkspBuc8is6c
uacme: type 'y' followed by a newline to accept challenge, anything else to skip
n
uacme: challenge=http-01 ident=test.abnoeh.eu.org token=ahhr6XnIEl-EnouzuNwNQHPzV97kBmmjV-1Eoy4MxMY key_auth=ahhr6XnIEl-EnouzuNwNQHPzV97kBmmjV-1Eoy4MxMY.yNQNkNjErzlMcx7j7tD1k305_8FTQt7IxNchoAjdW2w
uacme: type 'y' followed by a newline to accept challenge, anything else to skip
n
uacme: no challenge completed
uacme: failed to authorize order at https://acme-staging-v02.api.letsencrypt.org/acme/order/251051293/35594374633
looks like your client compare by first few only and dns-persist-01 matched 'dns' and client thinks it's dns?
It might be some weirdness with the Net::ACME2 library then. As you see, the $chtype->type() should return the challenge type as string, but it might, as you said, be something in Net::ACME2 that is "comparing the 3 first characters" or similiar.
Should see if I can get it to print the authz url and then look manually.
Be wary against testing too closely to Staging's implementation right now though. It's still using the draft-00 spec which doesn't include accounturi in the challenge object like draft-01 does. Anyone know if Pebble has updated for draft-01?
It shows the dns-persist-01 is actually there, but for some reason, the iterator are completely ignoring them. Its not detecting the "dns-" and misinterpreting them as dns-01.
Reason dns-01 is two times is because I requesting a wildcard, then it creates two authz objects.
Sure, but ignoring the accounturi value in the challenge prevents you from being able to utilize the Account URI Privacy feature that the CA may or may not choose to implement.
not sure how that helps privacy: it get a challenge object only allows one string in accounturi field so it must uri at persistent record so it fails at giving multiple identifier to hide two domain share a acme account
I'm having trouble mentally parsing what you wrote. Is there a typo or two?
In any case, think of it like this. You own two different domains:
my-public-facing-persona.test
my-private-anon.test
You don't want the general public to be able to know that you own both sites. Using dns-persist-01 with the actual ACME account URI from your account on both domains means anyone who queries the _validation-persist record on both domains now knows the same person owns/controls both because the URI is the same in both. So if they know who controls one, they know who controls the other. Obviously, you could work around it by using different ACME accounts or CAs for each site. But that's a hassle and a waste of time.
With Account URI Privacy, the CA gives you a domain or identifier specific account URI you can use instead of your actual account URI. Only you and the CA know these values map back to your account. The rest of the world doesn't. So the values in your TXT records no longer match and there's no way to tie the ownership of one to the ownership of the other without other external information.
problem is, current wording doesn't allow that: challenge's accounturi field is single string, and ACME server MUST accept actual actual account URI, so that field is now fixed with actual account uri without any place to fit any alternative.
Intend would be what you write, but actual rule is poorly worded that doesn't allow it
You get a Autz object per domain. Each Autz object displays what you MUST complete (AND). Inside each Autz object, there is multiple challenges, you can complete ANY of them (OR).
So if you request 2 domains, you will have 2 dns-persist-01 objects containing each own AccountURI.
In my opinion the feature is pretty useless, you can easily see on IP which sites are hosted on the same machine.
The draft is carefully worded to ensure that none of this is a problem.
The challenge object provides an accounturi to ensure that the client knows what accounturi the server wants to see. The client shouldn't need this -- it can easily know its own account uri through a variety of mechanisms -- but it makes completing the challenge stateless, which is nice.
However the server is explicitly allowed to accept any accounturi that is uniquely associated with the account. So if the client has populated a dns-persist-01 record with an old-style account uri from before the server changed its format, or if the client has used an obfuscated accounturi to prevent correlation of domains with accounts (or if the server provided an obfuscated uri but the client used its normal accounturi), it can still complete validation successfully.
Correct me if I'm wrong, but this also means the CA could choose to generate accounturi values that don't reference the CA at all even things that aren't DNS resolvable such as http://<GUID> where GUID is some sort of randomized token generated and associated with the account+identifier when the order is created.
Of course. No one is disputing that. All I was saying is that if you're developing a client that is intended to be used with dns-persist-01, you shouldn't ignore the accounturi value in the challenge. The user should have a choice whether to use the real account URI or whatever is presented in the challenge. And the default should probably be to use what is presented in the challenge.