Skip to content

Instantly share code, notes, and snippets.

@vti
Created July 27, 2010 16:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vti/436c4e80ceaba0f3a85e to your computer and use it in GitHub Desktop.
Save vti/436c4e80ceaba0f3a85e to your computer and use it in GitHub Desktop.
diff --git a/lib/Mojo/ByteStream.pm b/lib/Mojo/ByteStream.pm
index d424c08..a7d9a10 100644
--- a/lib/Mojo/ByteStream.pm
+++ b/lib/Mojo/ByteStream.pm
@@ -15,6 +15,8 @@ require Encode;
require MIME::Base64;
require MIME::QuotedPrint;
+use constant DIGEST_SHA1 => eval 'use Digest::SHA1; 1';
+
# Punycode bootstring parameters
use constant PUNYCODE_BASE => 36;
use constant PUNYCODE_TMIN => 1;
@@ -467,13 +469,32 @@ sub hmac_md5_sum {
#Secret
$secret ||= 'Very unsecure!';
- $secret = _md5_sum($secret) if length $secret > 64;
+ $secret = _md5_bytes($secret) if length $secret > 64;
# HMAC
my $ipad = $secret ^ (chr(0x36) x 64);
my $opad = $secret ^ (chr(0x5c) x 64);
- $self->{bytestream} =
- _md5_sum($opad . _md5_sum($ipad . $self->{bytestream}));
+ $self->{bytestream} = unpack 'H*' =>
+ _md5_bytes($opad . _md5_bytes($ipad . $self->{bytestream}));
+
+ return $self;
+}
+
+sub hmac_sha1_sum {
+ my ($self, $secret) = @_;
+
+ Carp::croak qq/Digest::SHA1 is required for using hmac_sha1_sum/
+ unless DIGEST_SHA1;
+
+ #Secret
+ $secret ||= 'Very unsecure!';
+ $secret = _sha1_bytes($secret) if length $secret > 64;
+
+ # HMAC
+ my $ipad = $secret ^ (chr(0x36) x 64);
+ my $opad = $secret ^ (chr(0x5c) x 64);
+ $self->{bytestream} = unpack 'H*' =>
+ _sha1_bytes($opad . _sha1_bytes($ipad . $self->{bytestream}));
return $self;
}
@@ -527,6 +548,22 @@ sub md5_sum {
return $self;
}
+sub sha1_bytes {
+ my $self = shift;
+ utf8::encode $self->{bytestream} if utf8::is_utf8 $self->{bytestream};
+ $self->{bytestream} = Digest::SHA1::sha1($self->{bytestream});
+ return $self;
+}
+
+sub sha1_sum {
+ my $self = shift;
+ Carp::croak qq/Digest::SHA1 is required for using sha1_sum/
+ unless DIGEST_SHA1;
+ utf8::encode $self->{bytestream} if utf8::is_utf8 $self->{bytestream};
+ $self->{bytestream} = Digest::SHA1::sha1_hex($self->{bytestream});
+ return $self;
+}
+
sub punycode_decode {
my $self = shift;
@@ -803,7 +840,10 @@ sub _adapt {
}
# Helper for hmac_md5_sum
-sub _md5_sum { Mojo::ByteStream->new(shift)->md5_sum->to_string }
+sub _md5_bytes { Mojo::ByteStream->new(shift)->md5_bytes->to_string }
+
+# Helper for hmac_sha1_sum
+sub _sha1_bytes { Mojo::ByteStream->new(shift)->sha1_bytes->to_string }
# Helper for url_sanitize
sub _sanitize {
diff --git a/t/mojo/bytestream.t b/t/mojo/bytestream.t
index 2738714..7647794 100644
--- a/t/mojo/bytestream.t
+++ b/t/mojo/bytestream.t
@@ -10,7 +10,7 @@ use utf8;
# Homer, we're going to ask you a few simple yes or no questions.
# Do you understand?
# Yes. *lie dectector blows up*
-use Test::More tests => 60;
+use Test::More tests => 72;
use_ok('Mojo::ByteStream', 'b');
@@ -138,6 +138,11 @@ $stream = b('foo bar baz');
is($stream->md5_sum, 'ab07acbb1e496801937adfa772424bf7',
'right md5 checksum');
+# sha1_sum
+$stream = b('foo bar baz');
+is($stream->sha1_sum, 'c7567e8b39e2428e38bf9c9226ac68de4c67dc39',
+ 'right sha1 checksum');
+
# length
$stream = b('foo bar baz');
is($stream->size, 11, 'size is 11');
@@ -147,19 +152,23 @@ $stream = b('0');
is($stream->size, 1, 'size is 1');
is($stream->to_string, '0', 'right buffer content');
-# hmac_md5_sum
-is( b('some secret message')->hmac_md5_sum('secret'),
- '5a7dcc4c407032ad10758abdda017f7b',
- 'right hmac md5 checksum'
-);
-is( b('some other message')->hmac_md5_sum('secret'),
- '9ab78f427440259a33abb088d4400526',
- 'right hmac md5 checksum'
-);
-is( b('some secret message')->hmac_md5_sum('secret'),
- '5a7dcc4c407032ad10758abdda017f7b',
- 'right hmac md5 checksum'
-);
+# hmac_md5_sum (test cases from RFC2202)
+is(b("Hi There")->hmac_md5_sum(chr(0x0b) x 16), '9294727a3638bb1c13f48ef8158bfc9d');
+is(b("what do ya want for nothing?")->hmac_md5_sum("Jefe"), '750c783e6ab0b503eaa86e310a5db738');
+is(b(chr(0xdd) x 50)->hmac_md5_sum(chr(0xaa) x 16), '56be34521d144c88dbb8c733f0e8b3f6');
+is(b(chr(0xcd) x 50)->hmac_md5_sum(pack 'H*' => '0102030405060708090a0b0c0d0e0f10111213141516171819'), '697eaf0aca3a3aea3a75164746ffaa79');
+is(b("Test With Truncation")->hmac_md5_sum(chr(0x0c) x 16), '56461ef2342edc00f9bab995690efd4c');
+is(b("Test Using Larger Than Block-Size Key - Hash Key First")->hmac_md5_sum(chr(0xaa) x 80), '6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd');
+is(b("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data")->hmac_md5_sum(chr(0xaa) x 80), '6f630fad67cda0ee1fb1f562db3aa53e');
+
+# hmac_sha1_sum (test cases from RFC2202)
+is(b("Hi There")->hmac_sha1_sum(chr(0x0b) x 20), 'b617318655057264e28bc0b6fb378c8ef146be00');
+is(b("what do ya want for nothing?")->hmac_sha1_sum("Jefe"), 'effcdf6ae5eb2fa2d27416d5f184df9c259a7c79');
+is(b(chr(0xdd) x 50)->hmac_sha1_sum(chr(0xaa) x 20), '125d7342b9ac11cd91a39af48aa17b4f63f175d3');
+is(b(chr(0xcd) x 50)->hmac_sha1_sum(pack 'H*' => '0102030405060708090a0b0c0d0e0f10111213141516171819'), '4c9007f4026250c6bc8414f9bf50c86c2d7235da');
+is(b("Test With Truncation")->hmac_sha1_sum(chr(0x0c) x 20), '4c1a03424b55e07fe7f27be1d58bb9324a9a5a04');
+is(b("Test Using Larger Than Block-Size Key - Hash Key First")->hmac_sha1_sum(chr(0xaa) x 80), 'aa4ae5e15272d00e95705637ce8a3b55ed402112');
+is(b("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data")->hmac_sha1_sum(chr(0xaa) x 80), 'e8e99d0f45237d786d6bbaa7965c7808bbff1a91');
# html_escape
$stream = b('foobar<baz>');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment