File Coverage

blib/lib/Mail/Simple/DKIM/Signer.pm
Criterion Covered Total %
statement 15 79 18.9
branch 0 12 0.0
condition 0 14 0.0
subroutine 5 10 50.0
pod 0 5 0.0
total 20 120 16.6


line stmt bran cond sub pod time code
1             package Mail::Simple::DKIM::Signer;
2            
3 1     1   21676 use strict;
  1         4  
  1         45  
4 1     1   6 use warnings;
  1         2  
  1         35  
5 1     1   2457 use Digest::SHA qw/sha1/;
  1         4154  
  1         86  
6 1     1   896 use MIME::Base64;
  1         734  
  1         70  
7 1     1   889 use Crypt::OpenSSL::RSA;
  1         10096  
  1         1041  
8             our $VERSION = '0.01';
9            
10            
11             sub new {
12            
13 0     0 0   my $class = shift;
14 0           my $options = shift;
15 0           my $self = {};
16            
17 0           my $private_key = $options->{key};
18 0           $self->{headers} = $options->{headers};
19            
20 0           my $rsa_priv = new_private_key Crypt::OpenSSL::RSA($private_key);
21            
22 0           $self->{rsa} = $rsa_priv;
23            
24 0           $self->{BodyCanonicalization} = 'simplebody';
25 0           $self->{HeadersCanonicalization} = 'simpleheader';
26            
27            
28 0           $self->{d} = $options->{domain};
29            
30 0   0       $self->{s} = $options->{selector} || 'dkim';
31            
32 0   0       $self->{c} = $options->{c} || 'simple/simple';
33            
34 0   0       $self->{l} = $options->{l} || '0';
35            
36             ###get each methods
37 0           my @methods = split(/\//, $self->{c});
38            
39 0   0       $self->{HeadersC} = $methods[0] || 'simple';
40 0   0       $self->{BodyC} = $methods[1] || 'simple';
41            
42 0   0       $self->{a} = $options->{a} || 'rsa-sha1';
43 0   0       $self->{q} = $options->{q} || 'dns/txt';
44            
45 0           $self->{i} = $options->{i};
46            
47 0           return bless($self, $class);
48             }
49            
50            
51            
52             sub sign {
53            
54 0     0 0   my ($self,$headers,$body) =@_;
55            
56             ####convert body with simple Canonicalization
57             #$body = $self->SimpleBodyCanonicalization($body);
58            
59 0           $body = $self->SimpleBodyCanonicalization($body);
60            
61             ##get body length
62 0           my $body_length = length($body);
63            
64             ####generate body ahsh key (bh)
65 0           my $bh = pack("H*", $body);
66 0           $bh = encode_base64(sha1($body));
67            
68             ###remove unwanted spaces from body hash
69 0 0         $bh =~ tr/\015\012 \t//d if defined $bh;
70            
71            
72             ####start genrating signature of headers
73            
74             ##first run Canonicalization
75 0           $headers = SimpleHeaderCanonicalization($headers);
76            
77             ##add headers to array
78 0           my @headers = split(/\r\n/, $headers);
79 0           my @str;
80             my @headers_to_be_signed;
81            
82             ##loop throug headers
83 0           foreach my $header (@headers){
84            
85             ###remove embty leading and ending lines
86 0           $header = $self->trim($header);
87            
88             ##exlude headers with x- and dkim- part
89 0 0         push @headers_to_be_signed,$header if $header !~/^X-|^Dkim-/i;
90             #push @to_be_signed,$header;
91            
92             ##get name part of headers
93 0           $header =~ m/(.*?): (.*?)/;
94 0 0         push @str,$1 if $1 !~/^X-|^Dkim-/i;
95            
96             }
97            
98             ###join header values we want to sign this will go to the h= tag
99 0           my $str = join(":",@str);
100            
101             ##getting i= tag
102 0           my $i_part = '';
103 0           my $l_part = '';
104            
105 0 0         if ($self->{i}){
106 0           $i_part = " i=".$self->{i}.";";
107             }
108            
109 0 0         if ($self->{l}){
110 0           $l_part = " l=$body_length;";
111             }
112            
113             ###create dkim string
114 0           my $dkim="v=1; a=$self->{a}; q=$self->{q};$l_part s=$self->{s};\r\n".
115             "\tc=$self->{c};\r\n".
116             "\th=$str;\r\n".
117             "\td=$self->{d};$i_part\r\n".
118             "\tbh=$bh;\r\n".
119             "\tb=";
120            
121            
122             ##push dkim string to the headers_to_be_signed array
123 0           push (@headers_to_be_signed,"DKIM-Signature: ".$dkim);
124            
125             ##get headers to be signed as string
126 0           my $headers_to_be_signed = join("\r\n",@headers_to_be_signed);
127            
128            
129             ##generate signature
130 0           my $signature = $self->{rsa}->sign($headers_to_be_signed);
131            
132            
133             ##encode segnature
134 0           my $b = encode_base64($signature);
135            
136             ##remove unwanted new lines
137 0 0         $b =~ tr/\015\012 \t//d if defined $b;
138            
139             ###add signature to the dkim string
140 0           $dkim = $dkim.$b;
141            
142             #return $dkim;
143             return {
144 0           string => "DKIM-Signature: ".$dkim,
145             value => $dkim,
146             key => "DKIM-Signature"
147             };
148            
149            
150             }
151            
152            
153            
154            
155             sub SimpleBodyCanonicalization {
156            
157 0     0 0   my ($self,$body) = @_;
158            
159             ##convert \r\n to \n just in case if this came from windows
160 0           $body =~s /\r\n/\n/g;
161            
162 0           $body =~s /\n/\r\n/g;
163            
164             #$body = length($body);
165 0           my $bodylength = length($body);
166            
167             ###remove embty lines from the end of the message body
168            
169 0           while (substr($body,$bodylength-4,4) =~ m/\r\n\r\n/){
170 0           $body = substr($body,0,length($body)-2);
171             }
172            
173 0           return $body;
174            
175             }
176            
177            
178            
179             sub SimpleHeaderCanonicalization {
180            
181 0     0 0   my $header =shift;
182            
183             ##convert \r\n to \n just in case if this came from windows
184 0           $header =~s /\r\n/\n/g;
185 0           $header =~s /\n/\r\n/g;
186            
187             ###nothing else to do with headers as this is what simple header Canonicalization
188             ##documents say
189            
190 0           return $header;
191            
192             }
193            
194            
195            
196             sub trim($) {
197            
198 0     0 0   my ($self,$string) = @_;
199            
200 0           $string =~ s/^\s+//;
201 0           $string =~ s/\s+$//;
202            
203 0           return $string;
204             }
205            
206            
207            
208             1;
209             __END__