File Coverage

blib/lib/Authen/HTTP/Signature/Method/HMAC.pm
Criterion Covered Total %
statement 18 24 75.0
branch 0 2 0.0
condition n/a
subroutine 6 7 85.7
pod n/a
total 24 33 72.7


line stmt bran cond sub pod time code
1             package Authen::HTTP::Signature::Method::HMAC;
2              
3 2     2   58 use 5.010;
  2         5  
  2         66  
4 2     2   9 use warnings;
  2         3  
  2         44  
5 2     2   11 use strict;
  2         4  
  2         65  
6              
7 2     2   10 use Moo;
  2         3  
  2         27  
8 2     2   2480 use Digest::SHA qw(hmac_sha1_base64 hmac_sha256_base64 hmac_sha512_base64);
  2         8317  
  2         219  
9 2     2   19 use Carp qw(confess);
  2         4  
  2         8291  
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.02';
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 0     0     my $self = shift;
79 0           my $b64_str = shift;
80              
81 0           my $n = length($b64_str) % 4;
82              
83 0 0         if ( $n ) {
84 0           $b64_str .= '=' x $n;
85             }
86              
87 0           return $b64_str;
88             }
89              
90             sub _get_digest {
91             my $self = shift;
92             my $algo = shift;
93             my $data = shift;
94             my $key = shift;
95              
96             my $digest;
97             for ( $algo ) {
98             when ( /sha1/ ) {
99             $digest = hmac_sha1_base64($data, $key);
100             }
101             when ( /sha256/ ) {
102             $digest = hmac_sha256_base64($data, $key);
103             }
104             when ( /sha512/ ) {
105             $digest = hmac_sha512_base64($data, $key);
106             }
107             }
108              
109             confess "I couldn't get a $algo digest\n" unless defined $digest && length $digest;
110              
111             return $digest;
112             }
113              
114             =over
115              
116             =item sign()
117              
118             Signs C with C using C.
119              
120             Returns a Base 64 encoded digest.
121              
122             =back
123              
124             =cut
125              
126             sub sign {
127             my $self = shift;
128              
129             return $self->_generate_signature();
130             }
131              
132             sub _generate_signature {
133             my $self = shift;
134              
135             return $self->_pad_base64(
136             $self->_get_digest(
137             $self->hash,
138             $self->data,
139             $self->key
140             )
141             );
142             }
143              
144             =over
145              
146             =item verify()
147              
148             Compares the given signature to a computed one. Returns true if they are the same. False otherwise.
149              
150             =back
151              
152             =cut
153              
154             sub verify {
155             my $self = shift;
156             my $candidate = shift;
157              
158             confess "How can I validate anything without a signature?" unless $candidate;
159              
160             return $self->_generate_signature() eq $candidate;
161             }
162              
163             =head1 SEE ALSO
164              
165             L
166              
167             =cut
168              
169             1;