diff options
author | dakkar <dakkar@thenautilus.net> | 2014-12-20 15:57:32 +0000 |
---|---|---|
committer | dakkar <dakkar@thenautilus.net> | 2014-12-20 15:57:32 +0000 |
commit | 6782c342f77cdcc1802bff69fbdd8897ba082386 (patch) | |
tree | 9f154b262855ad0e5f5c33719f6e78e8ec391701 | |
parent | more crypto tests (diff) | |
download | net-hawk-6782c342f77cdcc1802bff69fbdd8897ba082386.tar.gz net-hawk-6782c342f77cdcc1802bff69fbdd8897ba082386.tar.bz2 net-hawk-6782c342f77cdcc1802bff69fbdd8897ba082386.zip |
more client tests
-rw-r--r-- | lib/Net/Hawk/Client.pm | 2 | ||||
-rw-r--r-- | lib/Net/Hawk/Crypto.pm | 51 | ||||
-rw-r--r-- | lib/Net/Hawk/Types.pm | 14 | ||||
-rw-r--r-- | t/tests/Net/Hawk/Client.t | 48 |
4 files changed, 87 insertions, 28 deletions
diff --git a/lib/Net/Hawk/Client.pm b/lib/Net/Hawk/Client.pm index deec11d..b35d6d2 100644 --- a/lib/Net/Hawk/Client.pm +++ b/lib/Net/Hawk/Client.pm @@ -26,7 +26,7 @@ sub header { ], nonce => Optional[Str], hash => Optional[Str], - ext => Optional[Str], + ext => Optional[Str|Undef], app => Optional[Str], dlg => Optional[Str], payload => Optional[Str], diff --git a/lib/Net/Hawk/Crypto.pm b/lib/Net/Hawk/Crypto.pm index 57ac4bc..9c53148 100644 --- a/lib/Net/Hawk/Crypto.pm +++ b/lib/Net/Hawk/Crypto.pm @@ -7,9 +7,9 @@ use Types::Standard 1.000003 qw(Str Int Object Dict Optional Undef Any HasMethod use Types::URI qw(Uri); use Type::Params qw(compile); use Try::Tiny; -use Digest; -use Digest::HMAC; +use Digest::SHA qw(hmac_sha1_base64 hmac_sha256_base64); use Net::Hawk::Role::WithUtils; +use Net::Hawk::Types qw(Algorithm); with WithUtils(qw(parse_content_type)); @@ -24,7 +24,7 @@ sub generate_normalized_string { host => Str, port => Int, hash => Optional[Str], - ext => Optional[Str], + ext => Optional[Str|Undef], app => Optional[Str], dlg => Optional[Str], slurpy Any, @@ -56,7 +56,7 @@ sub generate_normalized_string { } sub calculate_payload_hash { - state $argcheck = compile(Object,Str|Undef,Str,Str|Undef); + state $argcheck = compile(Object,Str|Undef,Algorithm,Str|Undef); my ($self,$payload,$algorithm,$content_type) = $argcheck->(@_); my $hash = $self->initialize_payload_hash($algorithm,$content_type); @@ -68,7 +68,7 @@ sub calculate_mac { state $argcheck = compile( Object,Str, Dict[ - algorithm => Str, + algorithm => Algorithm, key => Str, slurpy Any, ], @@ -77,35 +77,34 @@ sub calculate_mac { my ($self,$type,$credentials,$options) = $argcheck->(@_); my $normalized = $self->generate_normalized_string($type,$options); - my $hmac = Digest::HMAC->new( - $credentials->{key}, - $self->make_digest($credentials->{algorithm}), + + state $function_map = { + sha1 => \&hmac_sha1_base64, + sha256 => \&hmac_sha256_base64, + }; + + my $mac = $function_map->{$credentials->{algorithm}}->( + $normalized,$credentials->{key}, ); - $hmac->add($normalized); - return $self->finalize_digest($hmac); + + return _pad_b64($mac); } sub make_digest { - state $argcheck = compile(Object,Str); + state $argcheck = compile(Object,Algorithm); my ($self,$algorithm) = $argcheck->(@_); - return try { - Digest->new($algorithm); - } - catch { - $algorithm =~ s{(?<=[a-z])(?=[0-9])}{-}; - Digest->new(uc($algorithm)); - }; + return Digest::SHA->new($algorithm =~ s{^sha}{}r); } sub initialize_payload_hash { - state $argcheck = compile(Object,Str,Str|Undef); + state $argcheck = compile(Object,Algorithm,Str|Undef); my ($self,$algorithm,$content_type) = $argcheck->(@_); my $digest = $self->make_digest($algorithm); $digest->add(sprintf("hawk.%d.payload\n",header_version())); - $digest->add($self->_utils->parse_content_type($content_type),"\n"); + $digest->add($self->_utils->parse_content_type($content_type)."\n"); return $digest; } @@ -114,16 +113,14 @@ sub finalize_payload_hash { my ($self,$digest) = $argcheck->(@_); $digest->add("\n"); - return $self->finalize_digest($digest); + return _pad_b64($digest->b64digest); } -sub finalize_digest { - state $argcheck = compile(Object,HasMethods[qw(b64digest)]); - my ($self,$digest) = $argcheck->(@_); +sub _pad_b64 { + my ($b64) = @_; - my $ret = $digest->b64digest(); - $ret .= '=' while length($ret) % 4; - return $ret; + $b64 .= '=' while length($b64) % 4; + return $b64; } 1; diff --git a/lib/Net/Hawk/Types.pm b/lib/Net/Hawk/Types.pm new file mode 100644 index 0000000..e1caec3 --- /dev/null +++ b/lib/Net/Hawk/Types.pm @@ -0,0 +1,14 @@ +package Net::Hawk::Types; +use strict; +use warnings; +use 5.010; +use Type::Library + -base, + -declare => qw(Algorithm); +use Type::Utils -all; +use Types::Standard qw(Str Enum); + +declare Algorithm, as Enum[qw(sha1 sha256)]; + +1; + diff --git a/t/tests/Net/Hawk/Client.t b/t/tests/Net/Hawk/Client.t index 77f63a0..e4c0dbb 100644 --- a/t/tests/Net/Hawk/Client.t +++ b/t/tests/Net/Hawk/Client.t @@ -49,4 +49,52 @@ subtest POST => sub { ); }; +subtest header => sub { + my $uri = 'http://example.net/somewhere/over/the/rainbow'; + my $uri_s = 'https://example.net/somewhere/over/the/rainbow'; + my %args = ( + credentials => { + id => '123456', + key => '2983d45yun89q', + algorithm => 'sha1', + }, + ext => 'Bazinga!', + timestamp => 1353809207, + nonce => 'Ygvqdz', + payload => 'something to write about', + ); + + my $header = $c->header($uri,POST => \%args); + is( + $header->{field}, + 'Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="', + 'valid authorization header (sha1)', + ); + + $args{credentials}{algorithm}='sha256'; + $args{content_type} = 'text/plain'; + $header = $c->header($uri_s,POST => \%args); + is( + $header->{field}, + 'Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="', + 'valid authorization header (sha256)', + ); + + delete $args{ext}; + $header = $c->header($uri_s,POST => \%args); + is( + $header->{field}, + 'Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="', + 'valid authorization header (no ext)', + ); + + $args{ext}=undef; + $header = $c->header($uri_s,POST => \%args); + is( + $header->{field}, + 'Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="', + 'valid authorization header (null ext)', + ); +}; + done_testing(); |