| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 | /******************************************************************************* copyright: Copyright (c) 2009 Tango. All rights reserved license: BSD style: see doc/license.txt for details version: Initial release: Sep 2009 author: Kai Nacke This module implements the Ripemd160 algorithm by Hans Dobbertin, Antoon Bosselaers and Bart Preneel. See http://homes.esat.kuleuven.be/~bosselae/ripemd160.html for more information. The implementation is based on: RIPEMD-160 software written by Antoon Bosselaers, available at http://www.esat.kuleuven.ac.be/~cosicart/ps/AB-9601/ *******************************************************************************/ module tango.util.digest.Ripemd320; private import tango.util.digest.MerkleDamgard; public import tango.util.digest.Digest; /******************************************************************************* *******************************************************************************/ final class Ripemd320 : MerkleDamgard { private uint[10] context; private enum uint padChar = 0x80; /*********************************************************************** ***********************************************************************/ private enum uint[10] initial = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0, 0x76543210, 0xfedcba98, 0x89abcdef, 0x01234567, 0x3c2d1e0f ]; /*********************************************************************** Construct a Ripemd320 ***********************************************************************/ this() { } /*********************************************************************** The size of a Ripemd320 digest is 40 bytes ***********************************************************************/ override uint digestSize() {return 40;} /*********************************************************************** Initialize the cipher Remarks: Returns the cipher state to it's initial value ***********************************************************************/ override void reset() { super.reset(); context[] = initial[]; } /*********************************************************************** Obtain the digest Returns: the digest Remarks: Returns a digest of the current cipher state, this may be the final digest, or a digest of the state between calls to update() ***********************************************************************/ override void createDigest(ubyte[] buf) { version (BigEndian) ByteSwap.swap32 (context.ptr, context.length * uint.sizeof); buf[] = cast(ubyte[]) context; } /*********************************************************************** block size Returns: the block size Remarks: Specifies the size (in bytes) of the block of data to pass to each call to transform(). For Ripemd320 the blockSize is 64. ***********************************************************************/ protected override uint blockSize() { return 64; } /*********************************************************************** Length padding size Returns: the length padding size Remarks: Specifies the size (in bytes) of the padding which uses the length of the data which has been ciphered, this padding is carried out by the padLength method. For Ripemd320 the addSize is 8. ***********************************************************************/ protected override uint addSize() { return 8; } /*********************************************************************** Pads the cipher data Params: data = a slice of the cipher buffer to fill with padding Remarks: Fills the passed buffer slice with the appropriate padding for the final call to transform(). This padding will fill the cipher buffer up to blockSize()-addSize(). ***********************************************************************/ protected override void padMessage(ubyte[] at) { at[0] = padChar; at[1..at.length] = 0; } /*********************************************************************** Performs the length padding Params: data = the slice of the cipher buffer to fill with padding length = the length of the data which has been ciphered Remarks: Fills the passed buffer slice with addSize() bytes of padding based on the length in bytes of the input data which has been ciphered. ***********************************************************************/ protected override void padLength(ubyte[] at, ulong length) { length <<= 3; littleEndian64((cast(ubyte*)&length)[0..8],cast(ulong[]) at); } /*********************************************************************** Performs the cipher on a block of data Params: data = the block of data to cipher Remarks: The actual cipher algorithm is carried out by this method on the passed block of data. This method is called for every blockSize() bytes of input data and once more with the remaining data padded to blockSize(). ***********************************************************************/ protected override void transform(const(ubyte[]) input) { uint al, bl, cl, dl, el; uint ar, br, cr, dr, er; uint[16] x; uint t; littleEndian32(input,x); al = context[0]; bl = context[1]; cl = context[2]; dl = context[3]; el = context[4]; ar = context[5]; br = context[6]; cr = context[7]; dr = context[8]; er = context[9]; // Round 1 and parallel round 1 al = rotateLeft(al + (bl ^ cl ^ dl) + x[0], 11) + el; ar = rotateLeft(ar + (br ^ (cr | ~(dr))) + x[5] + 0x50a28be6, 8) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + (al ^ bl ^ cl) + x[1], 14) + dl; er = rotateLeft(er + (ar ^ (br | ~(cr))) + x[14] + 0x50a28be6, 9) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + (el ^ al ^ bl) + x[2], 15) + cl; dr = rotateLeft(dr + (er ^ (ar | ~(br))) + x[7] + 0x50a28be6, 9) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + (dl ^ el ^ al) + x[3], 12) + bl; cr = rotateLeft(cr + (dr ^ (er | ~(ar))) + x[0] + 0x50a28be6, 11) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + (cl ^ dl ^ el) + x[4], 5) + al; br = rotateLeft(br + (cr ^ (dr | ~(er))) + x[9] + 0x50a28be6, 13) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + (bl ^ cl ^ dl) + x[5], 8) + el; ar = rotateLeft(ar + (br ^ (cr | ~(dr))) + x[2] + 0x50a28be6, 15) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + (al ^ bl ^ cl) + x[6], 7) + dl; er = rotateLeft(er + (ar ^ (br | ~(cr))) + x[11] + 0x50a28be6, 15) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + (el ^ al ^ bl) + x[7], 9) + cl; dr = rotateLeft(dr + (er ^ (ar | ~(br))) + x[4] + 0x50a28be6, 5) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + (dl ^ el ^ al) + x[8], 11) + bl; cr = rotateLeft(cr + (dr ^ (er | ~(ar))) + x[13] + 0x50a28be6, 7) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + (cl ^ dl ^ el) + x[9], 13) + al; br = rotateLeft(br + (cr ^ (dr | ~(er))) + x[6] + 0x50a28be6, 7) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + (bl ^ cl ^ dl) + x[10], 14) + el; ar = rotateLeft(ar + (br ^ (cr | ~(dr))) + x[15] + 0x50a28be6, 8) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + (al ^ bl ^ cl) + x[11], 15) + dl; er = rotateLeft(er + (ar ^ (br | ~(cr))) + x[8] + 0x50a28be6, 11) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + (el ^ al ^ bl) + x[12], 6) + cl; dr = rotateLeft(dr + (er ^ (ar | ~(br))) + x[1] + 0x50a28be6, 14) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + (dl ^ el ^ al) + x[13], 7) + bl; cr = rotateLeft(cr + (dr ^ (er | ~(ar))) + x[10] + 0x50a28be6, 14) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + (cl ^ dl ^ el) + x[14], 9) + al; br = rotateLeft(br + (cr ^ (dr | ~(er))) + x[3] + 0x50a28be6, 12) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + (bl ^ cl ^ dl) + x[15], 8) + el; ar = rotateLeft(ar + (br ^ (cr | ~(dr))) + x[12] + 0x50a28be6, 6) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); t = al; al = ar; ar = t; // Round 2 and parallel round 2 el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[7] + 0x5a827999, 7) + dl; er = rotateLeft(er + ((ar & cr) | (br & ~(cr))) + x[6] + 0x5c4dd124, 9) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[4] + 0x5a827999, 6) + cl; dr = rotateLeft(dr + ((er & br) | (ar & ~(br))) + x[11] + 0x5c4dd124, 13) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[13] + 0x5a827999, 8) + bl; cr = rotateLeft(cr + ((dr & ar) | (er & ~(ar))) + x[3] + 0x5c4dd124, 15) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[1] + 0x5a827999, 13) + al; br = rotateLeft(br + ((cr & er) | (dr & ~(er))) + x[7] + 0x5c4dd124, 7) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[10] + 0x5a827999, 11) + el; ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[0] + 0x5c4dd124, 12) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[6] + 0x5a827999, 9) + dl; er = rotateLeft(er + ((ar & cr) | (br & ~(cr))) + x[13] + 0x5c4dd124, 8) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[15] + 0x5a827999, 7) + cl; dr = rotateLeft(dr + ((er & br) | (ar & ~(br))) + x[5] + 0x5c4dd124, 9) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[3] + 0x5a827999, 15) + bl; cr = rotateLeft(cr + ((dr & ar) | (er & ~(ar))) + x[10] + 0x5c4dd124, 11) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[12] + 0x5a827999, 7) + al; br = rotateLeft(br + ((cr & er) | (dr & ~(er))) + x[14] + 0x5c4dd124, 7) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[0] + 0x5a827999, 12) + el; ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[15] + 0x5c4dd124, 7) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[9] + 0x5a827999, 15) + dl; er = rotateLeft(er + ((ar & cr) | (br & ~(cr))) + x[8] + 0x5c4dd124, 12) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[5] + 0x5a827999, 9) + cl; dr = rotateLeft(dr + ((er & br) | (ar & ~(br))) + x[12] + 0x5c4dd124, 7) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[2] + 0x5a827999, 11) + bl; cr = rotateLeft(cr + ((dr & ar) | (er & ~(ar))) + x[4] + 0x5c4dd124, 6) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[14] + 0x5a827999, 7) + al; br = rotateLeft(br + ((cr & er) | (dr & ~(er))) + x[9] + 0x5c4dd124, 15) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[11] + 0x5a827999, 13) + el; ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[1] + 0x5c4dd124, 13) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[8] + 0x5a827999, 12) + dl; er = rotateLeft(er + ((ar & cr) | (br & ~(cr))) + x[2] + 0x5c4dd124, 11) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); t = bl; bl = br; br = t; // Round 3 and parallel round 3 dl = rotateLeft(dl + ((el | ~(al)) ^ bl) + x[3] + 0x6ed9eba1, 11) + cl; dr = rotateLeft(dr + ((er | ~(ar)) ^ br) + x[15] + 0x6d703ef3, 9) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + ((dl | ~(el)) ^ al) + x[10] + 0x6ed9eba1, 13) + bl; cr = rotateLeft(cr + ((dr | ~(er)) ^ ar) + x[5] + 0x6d703ef3, 7) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + ((cl | ~(dl)) ^ el) + x[14] + 0x6ed9eba1, 6) + al; br = rotateLeft(br + ((cr | ~(dr)) ^ er) + x[1] + 0x6d703ef3, 15) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[4] + 0x6ed9eba1, 7) + el; ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[3] + 0x6d703ef3, 11) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + ((al | ~(bl)) ^ cl) + x[9] + 0x6ed9eba1, 14) + dl; er = rotateLeft(er + ((ar | ~(br)) ^ cr) + x[7] + 0x6d703ef3, 8) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + ((el | ~(al)) ^ bl) + x[15] + 0x6ed9eba1, 9) + cl; dr = rotateLeft(dr + ((er | ~(ar)) ^ br) + x[14] + 0x6d703ef3, 6) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + ((dl | ~(el)) ^ al) + x[8] + 0x6ed9eba1, 13) + bl; cr = rotateLeft(cr + ((dr | ~(er)) ^ ar) + x[6] + 0x6d703ef3, 6) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + ((cl | ~(dl)) ^ el) + x[1] + 0x6ed9eba1, 15) + al; br = rotateLeft(br + ((cr | ~(dr)) ^ er) + x[9] + 0x6d703ef3, 14) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[2] + 0x6ed9eba1, 14) + el; ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[11] + 0x6d703ef3, 12) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + ((al | ~(bl)) ^ cl) + x[7] + 0x6ed9eba1, 8) + dl; er = rotateLeft(er + ((ar | ~(br)) ^ cr) + x[8] + 0x6d703ef3, 13) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + ((el | ~(al)) ^ bl) + x[0] + 0x6ed9eba1, 13) + cl; dr = rotateLeft(dr + ((er | ~(ar)) ^ br) + x[12] + 0x6d703ef3, 5) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + ((dl | ~(el)) ^ al) + x[6] + 0x6ed9eba1, 6) + bl; cr = rotateLeft(cr + ((dr | ~(er)) ^ ar) + x[2] + 0x6d703ef3, 14) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + ((cl | ~(dl)) ^ el) + x[13] + 0x6ed9eba1, 5) + al; br = rotateLeft(br + ((cr | ~(dr)) ^ er) + x[10] + 0x6d703ef3, 13) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[11] + 0x6ed9eba1, 12) + el; ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[0] + 0x6d703ef3, 13) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + ((al | ~(bl)) ^ cl) + x[5] + 0x6ed9eba1, 7) + dl; er = rotateLeft(er + ((ar | ~(br)) ^ cr) + x[4] + 0x6d703ef3, 7) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + ((el | ~(al)) ^ bl) + x[12] + 0x6ed9eba1, 5) + cl; dr = rotateLeft(dr + ((er | ~(ar)) ^ br) + x[13] + 0x6d703ef3, 5) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); t = cl; cl = cr; cr = t; // Round 4 and parallel round 4 cl = rotateLeft(cl + ((dl & al) | (el & ~(al))) + x[1] + 0x8f1bbcdc, 11) + bl; cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[8] + 0x7a6d76e9, 15) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + ((cl & el) | (dl & ~(el))) + x[9] + 0x8f1bbcdc, 12) + al; br = rotateLeft(br + (((dr ^ er) & cr) ^ er) + x[6] + 0x7a6d76e9, 5) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[11] + 0x8f1bbcdc, 14) + el; ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[4] + 0x7a6d76e9, 8) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + ((al & cl) | (bl & ~(cl))) + x[10] + 0x8f1bbcdc, 15) + dl; er = rotateLeft(er + (((br ^ cr) & ar) ^ cr) + x[1] + 0x7a6d76e9, 11) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + ((el & bl) | (al & ~(bl))) + x[0] + 0x8f1bbcdc, 14) + cl; dr = rotateLeft(dr + (((ar ^ br) & er) ^ br) + x[3] + 0x7a6d76e9, 14) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + ((dl & al) | (el & ~(al))) + x[8] + 0x8f1bbcdc, 15) + bl; cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[11] + 0x7a6d76e9, 14) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + ((cl & el) | (dl & ~(el))) + x[12] + 0x8f1bbcdc, 9) + al; br = rotateLeft(br + (((dr ^ er) & cr) ^ er) + x[15] + 0x7a6d76e9, 6) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[4] + 0x8f1bbcdc, 8) + el; ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[0] + 0x7a6d76e9, 14) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + ((al & cl) | (bl & ~(cl))) + x[13] + 0x8f1bbcdc, 9) + dl; er = rotateLeft(er + (((br ^ cr) & ar) ^ cr) + x[5] + 0x7a6d76e9, 6) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + ((el & bl) | (al & ~(bl))) + x[3] + 0x8f1bbcdc, 14) + cl; dr = rotateLeft(dr + (((ar ^ br) & er) ^ br) + x[12] + 0x7a6d76e9, 9) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + ((dl & al) | (el & ~(al))) + x[7] + 0x8f1bbcdc, 5) + bl; cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[2] + 0x7a6d76e9, 12) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + ((cl & el) | (dl & ~(el))) + x[15] + 0x8f1bbcdc, 6) + al; br = rotateLeft(br + (((dr ^ er) & cr) ^ er) + x[13] + 0x7a6d76e9, 9) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[14] + 0x8f1bbcdc, 8) + el; ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[9] + 0x7a6d76e9, 12) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + ((al & cl) | (bl & ~(cl))) + x[5] + 0x8f1bbcdc, 6) + dl; er = rotateLeft(er + (((br ^ cr) & ar) ^ cr) + x[7] + 0x7a6d76e9, 5) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + ((el & bl) | (al & ~(bl))) + x[6] + 0x8f1bbcdc, 5) + cl; dr = rotateLeft(dr + (((ar ^ br) & er) ^ br) + x[10] + 0x7a6d76e9, 15) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + ((dl & al) | (el & ~(al))) + x[2] + 0x8f1bbcdc, 12) + bl; cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[14] + 0x7a6d76e9, 8) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); t = dl; dl = dr; dr = t; // Round 5 and parallel round 5 bl = rotateLeft(bl + (cl ^ (dl | ~(el))) + x[4] + 0xa953fd4e, 9) + al; br = rotateLeft(br + (cr ^ dr ^ er) + x[12], 8) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + (bl ^ (cl | ~(dl))) + x[0] + 0xa953fd4e, 15) + el; ar = rotateLeft(ar + (br ^ cr ^ dr) + x[15], 5) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + (al ^ (bl | ~(cl))) + x[5] + 0xa953fd4e, 5) + dl; er = rotateLeft(er + (ar ^ br ^ cr) + x[10], 12) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + (el ^ (al | ~(bl))) + x[9] + 0xa953fd4e, 11) + cl; dr = rotateLeft(dr + (er ^ ar ^ br) + x[4], 9) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + (dl ^ (el | ~(al))) + x[7] + 0xa953fd4e, 6) + bl; cr = rotateLeft(cr + (dr ^ er ^ ar) + x[1], 12) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + (cl ^ (dl | ~(el))) + x[12] + 0xa953fd4e, 8) + al; br = rotateLeft(br + (cr ^ dr ^ er) + x[5], 5) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + (bl ^ (cl | ~(dl))) + x[2] + 0xa953fd4e, 13) + el; ar = rotateLeft(ar + (br ^ cr ^ dr) + x[8], 14) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + (al ^ (bl | ~(cl))) + x[10] + 0xa953fd4e, 12) + dl; er = rotateLeft(er + (ar ^ br ^ cr) + x[7], 6) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + (el ^ (al | ~(bl))) + x[14] + 0xa953fd4e, 5) + cl; dr = rotateLeft(dr + (er ^ ar ^ br) + x[6], 8) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + (dl ^ (el | ~(al))) + x[1] + 0xa953fd4e, 12) + bl; cr = rotateLeft(cr + (dr ^ er ^ ar) + x[2], 13) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + (cl ^ (dl | ~(el))) + x[3] + 0xa953fd4e, 13) + al; br = rotateLeft(br + (cr ^ dr ^ er) + x[13], 6) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); al = rotateLeft(al + (bl ^ (cl | ~(dl))) + x[8] + 0xa953fd4e, 14) + el; ar = rotateLeft(ar + (br ^ cr ^ dr) + x[14], 5) + er; cl = rotateLeft(cl, 10); cr = rotateLeft(cr, 10); el = rotateLeft(el + (al ^ (bl | ~(cl))) + x[11] + 0xa953fd4e, 11) + dl; er = rotateLeft(er + (ar ^ br ^ cr) + x[0], 15) + dr; bl = rotateLeft(bl, 10); br = rotateLeft(br, 10); dl = rotateLeft(dl + (el ^ (al | ~(bl))) + x[6] + 0xa953fd4e, 8) + cl; dr = rotateLeft(dr + (er ^ ar ^ br) + x[3], 13) + cr; al = rotateLeft(al, 10); ar = rotateLeft(ar, 10); cl = rotateLeft(cl + (dl ^ (el | ~(al))) + x[15] + 0xa953fd4e, 5) + bl; cr = rotateLeft(cr + (dr ^ er ^ ar) + x[9], 11) + br; el = rotateLeft(el, 10); er = rotateLeft(er, 10); bl = rotateLeft(bl + (cl ^ (dl | ~(el))) + x[13] + 0xa953fd4e, 6) + al; br = rotateLeft(br + (cr ^ dr ^ er) + x[11], 11) + ar; dl = rotateLeft(dl, 10); dr = rotateLeft(dr, 10); // Do not swap el and er; simply add the right value to context context[0] += al; context[1] += bl; context[2] += cl; context[3] += dl; context[4] += er; context[5] += ar; context[6] += br; context[7] += cr; context[8] += dr; context[9] += el; x[] = 0; } } /******************************************************************************* *******************************************************************************/ debug(UnitTest) { unittest { enum immutable(char)[][] strings = [ "", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "12345678901234567890123456789012345678901234567890123456789012345678901234567890" ]; enum immutable(char)[][] results = [ "22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8", "ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d", "de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d", "3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197", "cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009", "d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac", "ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4", "557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42" ]; Ripemd320 h = new Ripemd320(); foreach (int i, immutable(char)[] s; strings) { h.update(cast(ubyte[]) s); char[] d = h.hexDigest(); assert(d == results[i],":("~s~")("~d~")!=("~results[i]~")"); } char[] s = new char[1000000]; for (auto i = 0; i < s.length; i++) s[i] = 'a'; immutable(char)[] result = "bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66"; h.update(cast(ubyte[]) s); char[] d = h.hexDigest(); assert(d == result,":(1 million times \"a\")("~d~")!=("~result~")"); } } |