aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2014-12-20 14:27:55 +0000
committerdakkar <dakkar@thenautilus.net>2014-12-20 14:27:55 +0000
commita237abd8e01e2783b9bb9d6eb3c3c26ef8832f92 (patch)
treeed88c9fed05152c9ce2ee77e3bf42dc600a1d24b /lib
downloadnet-hawk-a237abd8e01e2783b9bb9d6eb3c3c26ef8832f92.tar.gz
net-hawk-a237abd8e01e2783b9bb9d6eb3c3c26ef8832f92.tar.bz2
net-hawk-a237abd8e01e2783b9bb9d6eb3c3c26ef8832f92.zip
first tests passing
Diffstat (limited to 'lib')
-rw-r--r--lib/Net/Hawk/Crypto.pm91
-rw-r--r--lib/Net/Hawk/Utils.pm14
2 files changed, 105 insertions, 0 deletions
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;