diff --git a/lib/Mail/DKIM/Signer.pm b/lib/Mail/DKIM/Signer.pm index 210ca8e..62c5ded 100644 --- a/lib/Mail/DKIM/Signer.pm +++ b/lib/Mail/DKIM/Signer.pm @@ -196,13 +196,9 @@ sub init { $self->{'Algorithm'} = 'rsa-sha1'; } - my $type = 'rsa'; # default - $type = 'ed25519' if ( $self->{'Algorithm'} =~ /^ed25519/ ); - if ( defined $self->{KeyFile} ) { $self->{Key} ||= - Mail::DKIM::PrivateKey->load( File => $self->{KeyFile}, - Type => $type ); + load_private_key( $self->{KeyFile}, $self->{Algorithm} ); } unless ( $self->{'Method'} ) { @@ -275,7 +271,6 @@ sub finish_header { Domain => $self->{'Domain'}, Selector => $self->{'Selector'}, Key => $self->{'Key'}, - KeyFile => $self->{'KeyFile'}, ( $self->{'Identity'} ? ( Identity => $self->{'Identity'} ) : () @@ -314,19 +309,20 @@ sub finish_body { # finished canonicalizing $algorithm->finish_body; - my $type = 'rsa'; # default - $type = 'ed25519' if ( $self->{'Algorithm'} =~ /^ed25519/ ); - # load the private key file if necessary my $signature = $algorithm->signature; - my $key = - $signature->{Key} - || $signature->{KeyFile} - || $self->{Key} - || $self->{KeyFile}; - if ( defined($key) && !ref($key) ) { - $key = Mail::DKIM::PrivateKey->load( File => $key, - Type => $type ); + my $key = $signature->{Key} || $signature->{KeyFile}; + if ( defined($key) ) { + if ( !ref($key) ) { + $key = load_private_key( $key, $signature->algorithm ); + } + } + else { + $key = $self->{Key} || $self->{KeyFile}; + if ( defined($key) && !ref($key) ) { + $key = load_private_key( $key, $self->{Algorithm} ); + $self->{Key} = $key; + } } $key or die "no key available to sign with\n"; @@ -343,6 +339,17 @@ sub finish_body { } } +# Load a private key file for the given algorithm. +sub load_private_key { + my $key_file = shift; + my $algorithm = shift; + + my $type = 'rsa'; # default + $type = 'ed25519' if ( $algorithm =~ /^ed25519/ ); + + return Mail::DKIM::PrivateKey->load( File => $key_file, Type => $type ); +} + =head1 METHODS =head2 PRINT() diff --git a/t/signer_policy.t b/t/signer_policy.t index f06b682..3fa1053 100755 --- a/t/signer_policy.t +++ b/t/signer_policy.t @@ -2,11 +2,13 @@ use strict; use warnings; -use Test::Simple tests => 24; +use Test::Simple tests => 32; use Mail::DKIM::Signer; -my $keyfile = -f "t/test.key" ? "t/test.key" : "test.key"; +my $tdir = -f "t/test.key" ? "t" : "."; +my $keyfile = "$tdir/test.key"; +my $keyfile_ed = "$tdir/test.ed.key"; my $policy; my $dkim; @@ -149,6 +151,89 @@ ok( $multiple[0]->as_string =~ /^DomainKey-Signature/, "first is DomainKeys signature" ); ok( $multiple[1]->as_string =~ /^DKIM-Signature/, "second is DKIM signature" ); +# this policy should produce two DKIM signatures, one rsa and one ed25519 +$policy = sub { + my $signer = shift; + $signer->add_signature( + new Mail::DKIM::Signature( + Algorithm => "rsa-sha256", + Method => "relaxed", + Headers => $signer->headers, + Domain => "different-domain.example", + Selector => "beta", + Key => Mail::DKIM::PrivateKey->load( Type => 'rsa', + File => $keyfile), + ) + ); + $signer->add_signature( + new Mail::DKIM::Signature( + Algorithm => "ed25519-sha256", + Method => "relaxed", + Headers => $signer->headers, + Domain => "different-domain.example", + Selector => "gamma", + Key => Mail::DKIM::PrivateKey->load( Type => 'ed25519', + File => $keyfile_ed), + ) + ); +}; +$dkim = sign_sample_using_args( + Policy => $policy, +); +ok( $dkim, "processed message" ); + +@multiple = $dkim->signatures; +ok( @multiple == 2, "got 2 signatures" ); + +print "# signature=" . $multiple[0]->as_string . "\n"; +ok( $multiple[0]->as_string =~ /a=rsa-sha256/, + "got expected algorithm in first signature" ); + +print "# signature=" . $multiple[1]->as_string . "\n"; +ok( $multiple[1]->as_string =~ /a=ed25519-sha256/, + "got expected algorithm in second signature" ); + +# same test but this time with Signer loading the private keys +$policy = sub { + my $signer = shift; + my $sig = + new Mail::DKIM::Signature( + Algorithm => "rsa-sha256", + Method => "relaxed", + Headers => $signer->headers, + Domain => "different-domain.example", + Selector => "beta", + ); + $sig->{KeyFile} = $keyfile; + $signer->add_signature($sig); + + $sig = + new Mail::DKIM::Signature( + Algorithm => "ed25519-sha256", + Method => "relaxed", + Headers => $signer->headers, + Domain => "different-domain.example", + Selector => "gamma", + ); + $sig->{KeyFile} = $keyfile_ed; + $signer->add_signature($sig); +}; +$dkim = sign_sample_using_args( + Policy => $policy, +); +ok( $dkim, "processed message" ); + +@multiple = $dkim->signatures; +ok( @multiple == 2, "got 2 signatures" ); + +print "# signature=" . $multiple[0]->as_string . "\n"; +ok( $multiple[0]->as_string =~ /a=rsa-sha256/, + "got expected algorithm in first signature" ); + +print "# signature=" . $multiple[1]->as_string . "\n"; +ok( $multiple[1]->as_string =~ /a=ed25519-sha256/, + "got expected algorithm in second signature" ); + sub sign_sample_using_args { my %args = @_;