From a237abd8e01e2783b9bb9d6eb3c3c26ef8832f92 Mon Sep 17 00:00:00 2001 From: dakkar Date: Sat, 20 Dec 2014 14:27:55 +0000 Subject: first tests passing --- lib/Net/Hawk/Crypto.pm | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/Net/Hawk/Utils.pm | 14 ++++++++ 2 files changed, 105 insertions(+) create mode 100644 lib/Net/Hawk/Crypto.pm create mode 100644 lib/Net/Hawk/Utils.pm (limited to 'lib') diff --git a/lib/Net/Hawk/Crypto.pm b/lib/Net/Hawk/Crypto.pm new file mode 100644 index 0000000..a730ca6 --- /dev/null +++ b/lib/Net/Hawk/Crypto.pm @@ -0,0 +1,91 @@ +package Net::Hawk::Crypto; +use strict; +use warnings; +use 5.010; +use Moo; +use Types::Standard 1.000003 qw(Str Int Object Dict Optional Undef Any HasMethods slurpy); +use Types::URI qw(Uri); +use Type::Params qw(compile); +use Try::Tiny; +use Net::Hawk::Utils; +use Digest; + +sub header_version() { 1 } + +sub generate_normalized_string { + state $argcheck = compile(Object,Str,Dict[ + resource => Uri, + ts => Int, + nonce => Str, + method => Optional[Str], + host => Str, + port => Int, + hash => Optional[Str], + ext => Optional[Str], + app => Optional[Str], + dlg => Optional[Str], + slurpy Any, + ]); + my ($self,$type,$options) = $argcheck->(@_); + + my $normalized = sprintf( + "hawk.%d.%s\n%d\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n", + header_version(), $type, + $options->{ts}, + $options->{nonce}, + uc($options->{method} // ''), + $options->{resource}->path_query, + lc($options->{host}), + $options->{port}, + $options->{hash} // '', + ($options->{ext} // '') =~ s{\\}{\\\\}gr =~ s{\n}{\\n}gr, + ); + + if ($options->{app}) { + $normalized .= sprintf( + "%s\n%s\n", + $options->{app}, + $options->{dlg} // '', + ); + } + + return $normalized; +} + +sub calculate_payload_hash { + state $argcheck = compile(Object,Str|Undef,Str,Str); + my ($self,$payload,$algorithm,$content_type) = $argcheck->(@_); + + my $hash = $self->initialize_payload_hash($algorithm,$content_type); + $hash->add($payload//''); + return $self->finalize_payload_hash($hash); +} + +sub initialize_payload_hash { + state $argcheck = compile(Object,Str,Str); + my ($self,$algorithm,$content_type) = $argcheck->(@_); + + my $digest = try { + Digest->new($algorithm); + } + catch { + $algorithm =~ s{(?<=[a-z])(?=[0-9])}{-}; + Digest->new(uc($algorithm)); + }; + + $digest->add(sprintf("hawk.%d.payload\n",header_version())); + $digest->add(Net::Hawk::Utils::parse_content_type($content_type),"\n"); + return $digest; +} + +sub finalize_payload_hash { + state $argcheck = compile(Object,HasMethods[qw(add b64digest)]); + my ($self,$digest) = $argcheck->(@_); + + $digest->add("\n"); + my $ret = $digest->b64digest(); + $ret .= '=' while length($ret) % 4; + return $ret; +} + +1; diff --git a/lib/Net/Hawk/Utils.pm b/lib/Net/Hawk/Utils.pm new file mode 100644 index 0000000..527021d --- /dev/null +++ b/lib/Net/Hawk/Utils.pm @@ -0,0 +1,14 @@ +package Net::Hawk::Utils; +use strict; +use warnings; +use 5.010; + +sub parse_content_type { + my ($header) = @_; + return '' unless defined $header; + + my ($ret) = $header =~ m{^\s*(\S+?)\s*(;|$)}; + return lc($ret); +} + +1; -- cgit v1.2.3