File Coverage

blib/lib/Net/ACME2/Challenge/tls_alpn_01.pm
Criterion Covered Total %
statement 31 31 100.0
branch 1 2 50.0
condition n/a
subroutine 7 7 100.0
pod 1 1 100.0
total 40 41 97.5


line stmt bran cond sub pod time code
1             package Net::ACME2::Challenge::tls_alpn_01;
2              
3 3     3   17 use strict;
  3         5  
  3         72  
4 3     3   14 use warnings;
  3         5  
  3         76  
5              
6             =encoding utf-8
7              
8             =head1 NAME
9              
10             Net::ACME2::Challenge::tls_alpn_01
11              
12             =head1 DESCRIPTION
13              
14             This module is instantiated by L and is a
15             subclass of L.
16              
17             This module is EXPERIMENTAL, subject to finalization of the challenge
18             method described at L.
19              
20             =cut
21              
22 3     3   12 use parent qw( Net::ACME2::Challenge );
  3         6  
  3         13  
23              
24             use constant {
25 3         273 _VALIDITY_DELTA => 2 * 86400,
26 3     3   233 };
  3         6  
27              
28             =head1 METHODS
29              
30             =head2 I->KEY()
31              
32             Returns the private key (in PEM format) that is used to sign the
33             certificates that this module generates. The key does not need to be kept
34             secret; it’s just here because TLS implementations want it.
35              
36             =cut
37              
38             # NB: tls-alpn-01 doesn’t set any requirement for the key that signs
39             # the certificate. prime256v1 will get us the smallest certificate in
40             # the least amount of time. There’s no need to protect the key itself.
41 3     3   19 use constant KEY => <
  3         6  
  3         143  
42             -----BEGIN PRIVATE KEY-----
43             MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg+ja8vtIRQUTb11MC
44             elKer3JSgd3SYqNuSpQO+wTSkLGhRANCAATM+733J/pbsQASVQm08GoqHX4B7TKS
45             jijjtiQfzx/O9Dbr982LcWk1eaiYL/s3gzy5zodiIWu82PmorYkyJzLf
46             -----END PRIVATE KEY-----
47             END
48              
49             # This will depend on the key length.
50 3     3   23 use constant _SIGNATURE_ALGORITHM => 'sha256';
  3         5  
  3         701  
51              
52             =head2 I->create_certificate( $ACME, $DOMAIN )
53              
54             Returns an X.509 certificate that you can use to complete the challenge.
55              
56             The certificate is given in PEM encoding; L can easily
57             convert it to DER if you prefer.
58              
59             =cut
60              
61             sub create_certificate {
62 1     1 1 13153 my ($self, $acme, $domain) = @_;
63              
64 1 50       5 die "Need a domain!" if !$domain;
65              
66 1         9 require Crypt::Perl::PK;
67 1         492 require Crypt::Perl::X509v3;
68 1         6355 require Digest::SHA;
69              
70 1         5 my $priv_key = Crypt::Perl::PK::parse_key( KEY() );
71              
72 1         118326 my $now = time;
73              
74 1         7 my $key_authz = $acme->make_key_authorization($self);
75              
76 1         14 my $key_authz_sha = Digest::SHA::sha256($key_authz);
77              
78 1         4 my @name = ( [ commonName => $domain ] );
79              
80 1         6 my $cert = Crypt::Perl::X509v3->new(
81             key => $priv_key->get_public_key(),
82             subject => \@name,
83             issuer => \@name,
84             not_after => $now + _VALIDITY_DELTA(),
85             not_before => $now - _VALIDITY_DELTA(),
86             extensions => [
87             [ subjectAltName => [ dNSName => $domain ] ],
88             [ 'acmeValidation-v1' => Digest::SHA::sha256($key_authz) ],
89             ],
90             );
91              
92 1         22332 $cert->sign( $priv_key, _SIGNATURE_ALGORITHM() );
93              
94 1         5599756 return $cert->to_pem();
95             }
96              
97             1;