File Coverage

blib/lib/Authen/HTTP/Signature/Method/HMAC.pm
Criterion Covered Total %
statement 41 42 97.6
branch 6 12 50.0
condition 1 3 33.3
subroutine 11 11 100.0
pod 2 2 100.0
total 61 70 87.1


line stmt bran cond sub pod time code
1             package Authen::HTTP::Signature::Method::HMAC;
2              
3 2     2   76 use 5.010;
  2         8  
4 2     2   12 use warnings;
  2         4  
  2         52  
5 2     2   9 use strict;
  2         3  
  2         41  
6              
7 2     2   14 use Moo;
  2         4  
  2         14  
8 2     2   2383 use Digest::SHA qw(hmac_sha1_base64 hmac_sha256_base64 hmac_sha512_base64);
  2         7536  
  2         198  
9 2     2   14 use Carp qw(confess);
  2         4  
  2         922  
10              
11             =head1 NAME
12              
13             Authen::HTTP::Signature::Method::HMAC - Compute digest using a symmetric key
14              
15             =cut
16              
17             our $VERSION = '0.03';
18              
19             =head1 PURPOSE
20              
21             This class uses a symmetric key to compute a HTTP signature digest. It implements the
22             HMAC-SHA{1, 256, 512} algorithms.
23              
24             =head1 ATTRIBUTES
25              
26             These are Perlish mutators; pass a value to set it, pass no value to get the current value.
27              
28             =over
29              
30             =item key
31              
32             Key material. Read-only. Required.
33              
34             =back
35              
36             =cut
37              
38             has 'key' => (
39             is => 'ro',
40             required => 1,
41             );
42              
43             =over
44              
45             =item data
46              
47             The data to be signed. Read-only. Required.
48              
49             =back
50              
51             =cut
52              
53             has 'data' => (
54             is => 'ro',
55             required => 1,
56             );
57              
58             =over
59              
60             =item hash
61              
62             The algorithm to generate the digest. Read-only. Required.
63              
64             =back
65              
66             =cut
67              
68             has 'hash' => (
69             is => 'ro',
70             required => 1,
71             );
72              
73             =head1 METHODS
74              
75             =cut
76              
77             sub _pad_base64 {
78 7     7   11 my $self = shift;
79 7         10 my $b64_str = shift;
80              
81 7         10 my $n = length($b64_str) % 4;
82              
83 7 50       19 if ( $n ) {
84 7         18 $b64_str .= '=' x (4-$n);
85             }
86              
87 7         91 return $b64_str;
88             }
89              
90             sub _get_digest {
91 7     7   8 my $self = shift;
92 7         12 my $algo = shift;
93 7         9 my $data = shift;
94 7         8 my $key = shift;
95              
96 7         9 my $digest;
97 7 100       27 if ( $algo =~ /sha1/ ) {
    50          
    0          
98 4         67 $digest = hmac_sha1_base64($data, $key);
99             }
100             elsif ( $algo =~ /sha256/ ) {
101 3         53 $digest = hmac_sha256_base64($data, $key);
102             }
103             elsif ( $algo =~ /sha512/ ) {
104 0         0 $digest = hmac_sha512_base64($data, $key);
105             }
106              
107 7 50 33     44 confess "I couldn't get a $algo digest\n" unless defined $digest && length $digest;
108              
109 7         25 return $digest;
110             }
111              
112             =over
113              
114             =item sign()
115              
116             Signs C with C using C.
117              
118             Returns a Base 64 encoded digest.
119              
120             =back
121              
122             =cut
123              
124             sub sign {
125 3     3 1 8 my $self = shift;
126              
127 3         8 return $self->_generate_signature();
128             }
129              
130             sub _generate_signature {
131 7     7   9 my $self = shift;
132              
133 7         35 return $self->_pad_base64(
134             $self->_get_digest(
135             $self->hash,
136             $self->data,
137             $self->key
138             )
139             );
140             }
141              
142             =over
143              
144             =item verify()
145              
146             Compares the given signature to a computed one. Returns true if they are the same. False otherwise.
147              
148             =back
149              
150             =cut
151              
152             sub verify {
153 4     4 1 6 my $self = shift;
154 4         7 my $candidate = shift;
155              
156 4 50       9 confess "How can I validate anything without a signature?" unless $candidate;
157              
158 4         10 return $self->_generate_signature() eq $candidate;
159             }
160              
161             =head1 SEE ALSO
162              
163             L
164              
165             =cut
166              
167             1;