Navigation Menu

Skip to content

Commit

Permalink
Make MD4ish roles share Sum::MDPad code
Browse files Browse the repository at this point in the history
  • Loading branch information
skids committed Dec 5, 2012
1 parent 2fc1a68 commit 1189271
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 71 deletions.
69 changes: 8 additions & 61 deletions lib/Sum/MD.pm6
Expand Up @@ -49,7 +49,7 @@ $Sum::MD::Doc::synopsis = $=pod[0].content[3..4]>>.content.Str;
=head1 ROLES
=head2 role Sum::MD4 [ :$mod8 = False ] does Sum
=head2 role Sum::MD4 [ :$mod8 = False ] does Sum::MDPad
The C<Sum::MD4> parametric role is used to create a type of C<Sum>
that calculates an MD4 message digest.
Expand Down Expand Up @@ -77,11 +77,10 @@ $Sum::MD::Doc::synopsis = $=pod[0].content[3..4]>>.content.Str;
=end pod

use Sum;
use Sum::MDPad;

role Sum::MD4_5 [ :$alg where { $_ eqv [|] <MD5 MD4 MD4ext RIPEMD-128 RIPEMD-160 RIPEMD-256 RIPEMD-320 > } = "MD5",
:$mod8 = False ] does Sum {
has $!o is rw = 0;
has Bool $!final is rw;
:$mod8 = False ] does Sum::MDPad[:lengthtype<uint64_le>] {
has @!w is rw; # "Parsed" message gets bound here.
has @!s is rw; # Current hash state. H in specification.

Expand Down Expand Up @@ -113,7 +112,6 @@ role Sum::MD4_5 [ :$alg where { $_ eqv [|] <MD5 MD4 MD4ext RIPEMD-128 RIPEMD-160
(0xf0f0f0f0 +& ($_ +< 4)) +|
(0x0f0f0f0f +& ($_ +> 4)) }));
}
$!final = False;
}

# A moment of silence for the pixies that die every time something
Expand Down Expand Up @@ -472,58 +470,12 @@ role Sum::MD4_5 [ :$alg where { $_ eqv [|] <MD5 MD4 MD4ext RIPEMD-128 RIPEMD-160
@!s = 0xffffffff X+& @!s;
}

# TODO: when role trusts work for private attributes, these first three
# candidates can be made generic across a main role and the above
# conglomeration of functions and constant split up into proper subroles.
multi method do_add (*@addends) {
sink for (@addends) { self.add($_) }
}
multi method do_add ($addend) {
# TODO: Typed failure here?
die("Marshalling error. Addends must be Buf with 0..64 bytes.");
}
multi method do_add (Buf $block where { -1 < .elems < 64 },
Bool $b7?, Bool $b6?, Bool $b5?, Bool $b4?,
Bool $b3?, Bool $b2?, Bool $b1?) {
my int $bits = 0;
my int $byte = 0;

# $block.gist.say;

# Count how many stray bits we have and build them into a byte
( $byte = $byte +| (+$_ +< (7 - (($bits = $bits + 1)-1))) )
if .defined for ($b7,$b6,$b5,$b4,$b3,$b2,$b1);

# Update the count of the total number of bits sent.
$!o += $block.elems * 8 + $bits;
$!o +&= 0xffffffffffffffff;

# Check if buffer, bits, the added 1 bit, and the length fit in block
if $block.elems * 8 + $bits + 1 + 64 < 513 { # Yes

# Note 1 +< (7 - $bits) just happily also DTRT when !$bits
self.add(Buf.new($block[],$byte +| 1 +< (7 - $bits),
0 xx (55 - $block.elems),
(255 X+& ($!o X+> (0,8...56)))));
$!o -= 512; # undo what the other multimethod did.
}
else { # No

# So break it into two blocks.
self.add(Buf.new($block[],$byte +| 1 +< (7 - $bits),
0 xx (63 - $block.elems)));
$!o -= 512; # undo what the other multimethod did.
self.add(Buf.new(0 xx 56,
(255 X+& ($!o X+> (0,8...56)))));
$!o -= 512; # undo what the other multimethod did.
}
$!final = True;
}
multi method do_add (Buf $block where { .elems == 64 }) {

# We now have a complete block to crunch.

# $block.gist.say;
# Update the length count and check for problems via Sum::MDPad
given self.pos_block_inc {
when Failure { return $_ };
}

# Explode the message block into a scratchpad

Expand All @@ -537,12 +489,7 @@ role Sum::MD4_5 [ :$alg where { $_ eqv [|] <MD5 MD4 MD4ext RIPEMD-128 RIPEMD-160
self.md5_comp if $alg eqv "MD5";
self.ripe4_comp if $alg eqv ("RIPEMD-128"|"RIPEMD-256");
self.ripe5_comp if $alg eqv ("RIPEMD-160"|"RIPEMD-320");

# Update the size in bits.
$!o += 512; # spec permits this to wrap for large messages
$!o +&= 0xffffffffffffffff; # Should go away with sized types
};
method add (*@addends) { self.do_add(|@addends) }

method finalize(*@addends) {
given self.push(@addends) {
Expand All @@ -551,7 +498,7 @@ role Sum::MD4_5 [ :$alg where { $_ eqv [|] <MD5 MD4 MD4ext RIPEMD-128 RIPEMD-160

self.add(self.drain) if self.^can("drain");

self.add(Buf.new()) unless $!final;
self.add(Buf.new()) unless $.final;

:256[ 255 X+& (@!s[] X+> (0,8,16,24)) ]
}
Expand Down
41 changes: 31 additions & 10 deletions t/md.t
Expand Up @@ -90,9 +90,13 @@ given (MD5t.new()) {
is MD5t.new().finalize(Buf.new(97 xx 64)),
0x014842d480b571495a4a0363793f7367,
"MD5 is correct (test vector 1).";
is MD5t.new().finalize(Buf.new(97 xx 64), Buf.new(97 xx 64), Buf.new(97 xx 56)),
0x63642b027ee89938c922722650f2eb9b,

given (MD5t.new()) {
.push(Buf.new(97 xx 64));
.push(Buf.new(97 xx 64));
is .finalize(Buf.new(97 xx 56)), 0x63642b027ee89938c922722650f2eb9b,
"MD5 is correct (test vector 2).";
}

class r160t does Sum::RIPEMD160[] does Sum::Marshal::Raw { };
my r160t $r160 .= new();
Expand All @@ -110,9 +114,13 @@ given (r160t.new()) {
is r160t.new().finalize(Buf.new(97 xx 64)),
0x9dfb7d374ad924f3f88de96291c33e9abed53e32,
"RIPEMD-160 is correct (test vector 1).";
is r160t.new().finalize(Buf.new(97 xx 64), Buf.new(97 xx 64), Buf.new(97 xx 56)),
0x52a7ad26b98c60e2f14e0863c1b58de525888b11,

given (r160t.new()) {
.push(Buf.new(97 xx 64));
.push(Buf.new(97 xx 64));
is .finalize(Buf.new(97 xx 56)), 0x52a7ad26b98c60e2f14e0863c1b58de525888b11,
"RIPEMD-160 is correct (test vector 2).";
}

class r128t does Sum::RIPEMD128[] does Sum::Marshal::Raw { };
my r128t $r128 .= new();
Expand All @@ -130,10 +138,13 @@ given (r128t.new()) {
is r128t.new().finalize(Buf.new(97 xx 64)),
0x680716ac638f0d601982c696d37e5e56,
"RIPEMD-128 is correct (test vector 1).";
is r128t.new().finalize(Buf.new(97 xx 64), Buf.new(97 xx 64), Buf.new(97 xx 56)),
0x481285089b4b03da9eeffc2721680354,
"RIPEMD-128 is correct (test vector 2).";

given r128t.new() {
.push(Buf.new(97 xx 64));
.push(Buf.new(97 xx 64));
is .finalize(Buf.new(97 xx 56)), 0x481285089b4b03da9eeffc2721680354,
"RIPEMD-128 is correct (test vector 2).";
}

class r320t does Sum::RIPEMD320[] does Sum::Marshal::Raw { };
my r320t $r320 .= new();
Expand All @@ -146,14 +157,20 @@ given (r320t.new()) {
"RIPEMD-320 of an empty buffer is correct.";
is .Buf.values.fmt("%x"), "22 d6 5d 56 61 53 6c dc 75 c1 fd f5 c6 de 7b 41 b9 f2 73 25 eb c6 1e 85 57 17 7d 70 5a e c8 80 15 1c 3a 32 a0 8 99 b8", "RIPEMD-320 Buf method works";
}

# Since it uses the same buffering code as MD4 we don't need to test
# different lengths thoroughly, but a few more test vectors would be good.
is r320t.new().finalize(Buf.new(97 xx 64)),
0x6e815badcf69d2978caf8b8bbaba941239f9847d1ff140062484cb57a0745bccf21c427705fdd30d,
"RIPEMD-320 is correct (test vector 1).";
is r320t.new().finalize(Buf.new(97 xx 64), Buf.new(97 xx 64), Buf.new(97 xx 56)),

given r320t.new() {
.push(Buf.new(97 xx 64));
.push(Buf.new(97 xx 64));
is .finalize(Buf.new(97 xx 56)),
0x82c5b5ffb960376afb6e21b33bd2367197080dd9724f7e2947e1075347462e603649bca32ad1b824,
"RIPEMD-320 is correct (test vector 2).";
}

class r256t does Sum::RIPEMD256[] does Sum::Marshal::Raw { };
my r256t $r256 .= new();
Expand All @@ -171,10 +188,14 @@ given (r256t.new()) {
is r256t.new().finalize(Buf.new(97 xx 64)),
0x8147678472c129cabb59f57f637c622ccd5707af80a583303e6dde7d0800ced6,
"RIPEMD-256 is correct (test vector 1).";
is r256t.new().finalize(Buf.new(97 xx 64), Buf.new(97 xx 64), Buf.new(97 xx 56)),

given r256t.new() {
.push(Buf.new(97 xx 64));
.push(Buf.new(97 xx 64));
is .finalize(Buf.new(97 xx 56)),
0x8e7bc719ca3cdbb9411e43f18955a1f305e7643a0ae20a7a01823e80090fcf37,
"RIPEMD-256 is correct (test vector 2).";

}

class MD2t does Sum::MD2 does Sum::Marshal::Raw { };
my MD2t $s2 .= new();
Expand Down

0 comments on commit 1189271

Please sign in to comment.