aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2014-12-20 15:57:32 +0000
committerdakkar <dakkar@thenautilus.net>2014-12-20 15:57:32 +0000
commit6782c342f77cdcc1802bff69fbdd8897ba082386 (patch)
tree9f154b262855ad0e5f5c33719f6e78e8ec391701
parentmore crypto tests (diff)
downloadnet-hawk-6782c342f77cdcc1802bff69fbdd8897ba082386.tar.gz
net-hawk-6782c342f77cdcc1802bff69fbdd8897ba082386.tar.bz2
net-hawk-6782c342f77cdcc1802bff69fbdd8897ba082386.zip
more client tests
-rw-r--r--lib/Net/Hawk/Client.pm2
-rw-r--r--lib/Net/Hawk/Crypto.pm51
-rw-r--r--lib/Net/Hawk/Types.pm14
-rw-r--r--t/tests/Net/Hawk/Client.t48
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();