diff options
author | Guilhem Moulin <guilhem@fripost.org> | 2021-02-21 14:27:50 +0100 |
---|---|---|
committer | Guilhem Moulin <guilhem@fripost.org> | 2021-02-21 19:41:40 +0100 |
commit | ba6addf54cef0b1536dc87c42a41b4dc207ac884 (patch) | |
tree | ab057ee5f4675709e30a88a31aa57ab525c73cdb /lacme-accountd | |
parent | 16f7d75ac8e46a7905779931c871ac85c7e1aa04 (diff) |
accountd: Pass JWA and JWK thumbprint via extended greeting data.
Passing the JWA to the ACME client is required if we want to support
account keys other than RSA. As of 0.7 both lacme-accountd(1) and
lacme(8) hardcode “RS256” (SHA256withRSA per RFC 7518 sec. A.1).
Passing the JWK thumbprint is handy as it gives more flexibility if RFC
8555 sec. 8.1 were to be updated with another digest algorithm (it's
currently hardcoded to SHA-256). A single lacme-account(1) instance
might be used to sign requests from many clients, and it's easier to
upgrade a single ‘lacme-accountd’ than many ‘lacme’. Moreover, in some
restricted environments lacme-accountd might hide the JWK from the
client to prevent ‘newAccount’ requests (such as contact updates);
passing its thumbprint is enough for ‘newOrder’ requests.
Diffstat (limited to 'lacme-accountd')
-rwxr-xr-x | lacme-accountd | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/lacme-accountd b/lacme-accountd index 0f0b0d9..d4521f9 100755 --- a/lacme-accountd +++ b/lacme-accountd @@ -27,6 +27,7 @@ our $VERSION = '0.3'; my $PROTOCOL_VERSION = 1; my $NAME = 'lacme-accountd'; +use Digest::SHA 'sha256'; use Errno 'EINTR'; use File::Basename 'dirname'; use Getopt::Long qw/:config posix_default no_ignore_case gnu_getopt auto_version/; @@ -141,7 +142,7 @@ do { # Build the JSON Web Key (RFC 7517) from the account key's public parameters, # and determine the signing method $SIGN. # -my ($JWK, $SIGN); +my ($EXTRA_GREETING_STR, $JWK_STR, $SIGN); if ($OPTS{privkey} =~ /\A(file|gpg):(\p{Print}+)\z/) { my ($method, $filename) = ($1, spec_expand($2)); my ($fh, @command); @@ -174,13 +175,19 @@ if ($OPTS{privkey} =~ /\A(file|gpg):(\p{Print}+)\z/) { my ($n, $e) = $rsa->get_key_parameters(); # don't include private params! $_ = encode_base64url($_->to_bin()) foreach ($n, $e); - $JWK = { kty => 'RSA', n => $n, e => $e }; + my %extra_greeting; + my %jwk = ( kty => 'RSA', n => $n, e => $e ); + $extra_greeting{alg} = 'RS256'; # SHA256withRSA (RFC 7518 sec. A.1) $SIGN = sub($) { $rsa->sign($_[0]) }; + + # use of SHA-256 digest in the thumbprint is hardcoded, see RFC 8555 sec. 8.1 + $JWK_STR = JSON::->new->utf8->canonical->encode(\%jwk); + $extra_greeting{"jwk-thumbprint"} = encode_base64url(sha256($JWK_STR)); + $EXTRA_GREETING_STR = JSON::->new->encode(\%extra_greeting); } else { error("Unsupported method: $OPTS{privkey}"); } -my $JWK_STR = JSON::->new->encode($JWK); ############################################################################# @@ -219,7 +226,8 @@ unless (defined $OPTS{stdio}) { # sub conn($$$) { my ($in, $out, $id) = @_; - $out->printflush( "$PROTOCOL_VERSION OK", "\r\n", $JWK_STR, "\r\n" ) or warn "print: $!"; + $out->printflush( "$PROTOCOL_VERSION OK ", $EXTRA_GREETING_STR, "\r\n", + $JWK_STR, "\r\n" ) or warn "print: $!"; # sign whatever comes in while (defined (my $data = $in->getline())) { |