summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2011-03-25 21:43:42 +0000
committerdakkar <dakkar@thenautilus.net>2011-03-25 21:43:42 +0000
commit75aa29074f273164a8029d2fd8c963f8de5aea49 (patch)
tree7dca22b15aa45172a36c3bf83035bb610e9ff109
parentbroken first stab (diff)
downloadDeWeave-75aa29074f273164a8029d2fd8c963f8de5aea49.tar.gz
DeWeave-75aa29074f273164a8029d2fd8c963f8de5aea49.tar.bz2
DeWeave-75aa29074f273164a8029d2fd8c963f8de5aea49.zip
it might even complie
-rw-r--r--bin/client48
-rw-r--r--lib/DeWeave/Crypto.pm126
-rw-r--r--lib/DeWeave/Crypto/KeyBundle.pm15
-rw-r--r--lib/DeWeave/EDO.pm22
-rw-r--r--lib/DeWeave/Storage.pm64
-rw-r--r--lib/DeWeave/WBO.pm3
6 files changed, 277 insertions, 1 deletions
diff --git a/bin/client b/bin/client
new file mode 100644
index 0000000..26eae71
--- /dev/null
+++ b/bin/client
@@ -0,0 +1,48 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use FindBin::libs;
+use DeWeave::Storage;
+use DeWeave::Crypto;
+use DeWeave::EDO;
+use Getopt::Long;
+
+my ($server,$username,$password,$sync_key);
+
+{
+my $p = Getopt::Long::Parser->new(
+ config => [qw(
+ no_auto_abbrev
+ no_getopt_compat
+ no_gnu_compat
+ require_order
+ no_ignore_case
+ )],
+);
+die unless $p->getoptions(
+ 'h|host=s' => \$server,
+ 'u|user=s' => \$username,
+ 'p|pass|password=s' => \$password,
+ 'k|key|sync-key=s' => \$sync_key,
+);
+}
+
+my $storage = DeWeave::Storage->new({
+ ($server ? (server_uri => $server) : () ),
+ username => $username,
+ password => $password,
+});
+
+my $crypto = DeWeave::Crypto->new({
+ storage => $storage,
+ sync_key => $sync_key,
+});
+
+use Data::Dump 'pp';
+
+my $foo = DeWeave::EDO->from_json(
+ $storage->get_item('storage/tabs'),
+ $crypto,
+);
+
+print pp $foo;
diff --git a/lib/DeWeave/Crypto.pm b/lib/DeWeave/Crypto.pm
new file mode 100644
index 0000000..618e095
--- /dev/null
+++ b/lib/DeWeave/Crypto.pm
@@ -0,0 +1,126 @@
+package DeWeave::Crypto;
+use Moose;
+use namespace::autoclean;
+use MooseX::Types::Moose qw(HashRef Str);
+use MooseX::Types::Structured qw(Tuple);
+use JSON::Any;
+use Try::Tiny;
+use Digest::SHA ();
+use MIME::Base32 'RFC';
+use Crypt::CBC;
+
+has storage => (
+ isa => 'DeWeave::Storage',
+ required => 1,
+ is => 'ro',
+);
+
+has sync_key => (
+ isa => Str,
+ required => 1,
+ is => 'ro',
+);
+
+sub _byte_sync_key {
+ my ($self) = @_;
+
+ my $key = $self->sync_key;
+ $key =~ y{89}{lo};
+ return MIME::Base32::decode($key);
+}
+
+has _hmac_input => (
+ isa => Str,
+ default => 'Sync-AES_256_CBC-HMAC256',
+ is => 'ro',
+);
+
+has _encryption_key => (
+ isa => Str,
+ lazy_build => 1,
+ is => 'ro',
+);
+
+sub _build__encryption_key {
+ my ($self) = @_;
+
+ my $secret = $self->_hmac_input
+ . $self->storage->username . "\x01";
+ return Digest::SHA::hmac_sha256($secret, $self->_byte_sync_key);
+}
+
+has _hmac_key => (
+ isa => Str,
+ lazy_build => 1,
+ is => 'ro',
+);
+
+sub _build__hmac_key {
+ my ($self) = @_;
+
+ my $secret = $self->_encryption_key . $self->_hmac_input
+ . $self->storage->username . "\x02";
+ return Digest::SHA::hmac_sha256($secret, $self->_byte_sync_key);
+}
+
+has _keys => (
+ isa => HashRef[Tuple[Str,Str]],
+ init_arg => undef,
+ lazy_build => 1,
+ is => 'ro',
+ traits => ['Hash'],
+ handles => {
+ _has_collection_keys => 'exists',
+ _get_collection_keys => 'get',
+ },
+);
+
+sub _build__keys {
+ my ($self) = @_;
+
+ my $j = JSON::Any->new;
+
+ my $keys_payload = $self->storage->get_item('crypto/keys');
+ my $struct = $j->decode($keys_payload);
+
+ my $keys = {
+ default => $struct->{default},
+ %{$struct->{collections}},
+ };
+
+ return $keys;
+}
+
+sub keys_for_collection {
+ my ($self,$collection) = @_;
+
+ if ($self->_has_collection_keys($collection)) {
+ return $self->_get_collection_keys($collection);
+ }
+ else {
+ return $self->_get_collection_keys('default');
+ }
+}
+
+sub decrypt {
+ my ($self,$args) = @_;
+
+ my $iv = $args->{IV};
+ my $hmac = $args->{hmac};
+ my $ct = $args->{ciphertext};
+
+ my $cipher = Crypt::CBC->new(
+ -key => $self->_encryption_key,
+ -cipher => 'Crypt::OpenSSL::AES',
+ -iv => $iv,
+ -header => 'none',
+ -padding => 'null',
+ -literal_key => 1,
+ );
+
+ my $pt = $cipher->decrypt($ct);
+ # TODO verify
+ return $pt;
+}
+
+1;
diff --git a/lib/DeWeave/Crypto/KeyBundle.pm b/lib/DeWeave/Crypto/KeyBundle.pm
new file mode 100644
index 0000000..aea89ec
--- /dev/null
+++ b/lib/DeWeave/Crypto/KeyBundle.pm
@@ -0,0 +1,15 @@
+package DeWeave::Crypto::KeyBundle;
+use Moose;
+use namespace::autoclean;
+use MooseX::Types::Moose qw(HashRef Str);
+use MooseX::Types::Structured qw(Tuple);
+
+has _keys => (
+ isa => Str,
+ init_arg => undef,
+ lazy_build => 1,
+);
+
+
+
+1;
diff --git a/lib/DeWeave/EDO.pm b/lib/DeWeave/EDO.pm
index 29a9cee..30fdbf2 100644
--- a/lib/DeWeave/EDO.pm
+++ b/lib/DeWeave/EDO.pm
@@ -3,6 +3,7 @@ use Moose;
use namespace::autoclean;
use MooseX::Types::Moose qw(Int Str Num);
use JSON::Any;
+use Try::Tiny;
extends 'DeWeave::WBO';
@@ -24,4 +25,25 @@ has hmac => (
is => 'ro',
);
+around BUILDARGS => sub {
+ my $orig = shift;
+ my $class = shift;
+
+ my $args = $class->$orig(@_);
+ return $args unless defined $args->{__crypt};
+
+ my $decrypted_payload = $args->{__crypt}->decrypt($args);
+
+ if (defined $decrypted_payload) {
+ try {
+ my $j = JSON::Any->new;
+ my $extra_args = $j->decode($decrypted_payload);
+
+ @$args{keys %$extra_args} =
+ values %$extra_args;
+ };
+ }
+ return $args;
+};
+
1;
diff --git a/lib/DeWeave/Storage.pm b/lib/DeWeave/Storage.pm
new file mode 100644
index 0000000..0786b7c
--- /dev/null
+++ b/lib/DeWeave/Storage.pm
@@ -0,0 +1,64 @@
+package DeWeave::Crypto;
+use Moose;
+use namespace::autoclean;
+use MooseX::Types::Moose qw(Str);
+use LWP::UserAgent;
+use MooseX::Types::URI qw(Uri);
+use URI::QueryParam;
+
+has username => (
+ isa => Str,
+ required => 1,
+ is => 'ro',
+);
+
+has password => (
+ isa => Str,
+ required => 1,
+ is => 'ro',
+);
+
+has server_uri => (
+ isa => Uri,
+ coerce => 1,
+ is => 'ro',
+ default => 'https://weave.thenautilus.net/',
+);
+
+has _useragent => (
+ init_arg => undef,
+ is => 'ro',
+ lazy_build => 1,
+);
+
+sub _build__useragent {
+ my ($self) = @_;
+
+ my $ua = LWP::UserAgent->new();
+ $ua->env_proxy;
+ $ua->credentials($self->server_uri->host_port,
+ $self->username,
+ $self->password);
+ $ua->protocols_allowed(['https']);
+
+ return $ua;
+}
+
+sub get_item {
+ my ($self,$path) = @_;
+
+ my $relative = sprintf '1.0/%s/storage/%s',
+ $self->username,$path;
+ my $uri = URI->new_abs($relative,$self->server_uri);
+ $uri->query_param(full => 1);
+ my $response = $self->_useragent->get($uri);
+
+ if ($response->is_success) {
+ return $response->decoded_content;
+ }
+ else {
+ die $response->status_line;
+ }
+}
+
+1;
diff --git a/lib/DeWeave/WBO.pm b/lib/DeWeave/WBO.pm
index db89581..3f551dd 100644
--- a/lib/DeWeave/WBO.pm
+++ b/lib/DeWeave/WBO.pm
@@ -36,7 +36,7 @@ has ttl => (
);
sub from_json {
- my ($class,$json)=@_;
+ my ($class,$json,$crypt)=@_;
my $j = JSON::Any->new;
@@ -47,6 +47,7 @@ sub from_json {
@$args{keys %$extra_args} =
values %$extra_args;
+ $args->{__crypt}=$crypt;
};
}