# How does RIPEMD160 pad the message?

For RIPEMD hashing algorithm on hardware I am not exactly getting how padding works

So as per my understanding padding will work like explained below:

For ripemd 160 message should be multiple of 512 bits. So, along with message to make it 512 bits, after message we pad 1 following zeros. Last 64 bits of 512 block are reserved for length of the message.

Suppose message is a which I have to send it for hashing. So first it will go through padding. So for message a asci value 61 will be send for padding which is nothing but 61 hex.

So after value 61 there will be 1 and followed by zeros and last 64 bits will be length of message. So as per little endian conventions, byte wise representation of a after padding will looks like below right?

512'h08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008061


(MSB side last byte 08 is nothing but length of message a LSB side 61 is actual message then followed by 1 and zeros) as ripemd is little endian based.

Please correct me if I am wrong. Is my description correct? If not, how does RIPEMD160 pad the message?

RIPEMD-160 uses precisely the same padding and endianess convention as MD5.

Everything is little-endian, with the exception of the order of bits in bytes, which is kept big-endian. If the message is $n$-bit, it is appended a single bit at 1 and $511-((n+64)\bmod512)$ bit(s) at 0 , then the representation of $n$ on 64 bits. The resulting padded message is an integral number of 512-bit blocks, which are each considered 16 words of 32 bits.

Note: It follows that the padding bit at 1 corresponds to a byte mask with value $2^{7-(n\bmod 8)}$. The $n\bmod 8$ last message bit(s) are in the high-order bit(s) of that byte, which $7-(n\bmod 8)$ low-order bit(s) are 0.

Suppose the message is the one-character string "a", and that is coded in ASCII as the single byte 61h = 01100001b = 97.

That's the bitstring 01100001. $n=8$, thus the padding is 1 followed by 439 0 (with the first eight bits of that padding 10000000 corresponding to byte 80h), followed by the length $n=8$ represented as the bitstring 00001000 00000000 00000000 00000000 0000000 00000000 00000000 0000000 (with the first eight bits 00001000 corresponding to the byte 08h).

Showing this as a string of 64 bytes with bytes and 32-bit boundaries shown (and individual bytes shown in big-endian hexadecimal), the padded block is

61 80 00 00   00 00 00 00   00 00 00 00   00 00 00 00
00 00 00 00   00 00 00 00   00 00 00 00   00 00 00 00
00 00 00 00   00 00 00 00   00 00 00 00   00 00 00 00
00 00 00 00   00 00 00 00   08 00 00 00   00 00 00 00


Packing that into 32-bit words using little-endian convention (and individual 32-bit words shown in big-endian hexadecimal), we get

00008061      00000000      00000000      00000000
00000000      00000000      00000000      00000000
00000000      00000000      00000000      00000000
00000000      00000000      00000008      00000000


or in decimal { 32865, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0 }.

Note: a former version of this answer did not take into account the exception to little-endianness in the conversion of bytes to/from bits, and used uppercase ASCII code in the example. I'm confident about the present revised version.

Simple demonstration and example output for the reference code rmd160

// Demonstration of rmd160 - public domain
// note: on machines with more than 32-bit unsigned long, rmd160.h requires a simple change
#include "rmd160.h" // at http://homes.esat.kuleuven.be/~bosselae/ripemd160/ps/AB-9601/rmd160.h
#define SIZEOFHASH  20      // size of the hash in bytes
#define SIZEOFBLOCK 64      // size of a block in bytes

// including the code simplifies compilation+linking into a tool
#include "rmd160.c" // at http://homes.esat.kuleuven.be/~bosselae/ripemd160/ps/AB-9601/rmd160.c

// hash a byte buffer in memory
void hashmd160(
const byte  *iData,             // input
size_t      iDataLength,        // size of input in bytes
byte        oHash[SIZEOFHASH]   // result (must be allocated by caller)
)
{
dword       vHash32[SIZEOFHASH%4==0 ? SIZEOFHASH/4 : -1 ];      // the hash, as 32-bit words
dword       vBlock32[SIZEOFBLOCK%4==0 ? SIZEOFBLOCK/4 : -1 ];   // a block, as 32-bit words
size_t      vb;
int         vj;
// start hashing
MDinit(vHash32);
// hash full blocks; needed only when iDataLength>=SIZEOFBLOCK
for (vb = iDataLength/SIZEOFBLOCK; vb!=0; --vb)
{ // make a little-endian copy of SIZEOFBLOCK bytes from iData to vBlock32
for (vj = 0; vj<SIZEOFBLOCK/4; ++vj, iData += 4)
vBlock32[vj] = iData[0] | iData[1]<<8 | (dword)(iData[2] | iData[3]<<8)<<16;
compress(vHash32,vBlock32);
}
// hash remaining bytes
MDfinish(vHash32, (byte *)iData, iDataLength, iDataLength>>16>>16);
// make a little-endian copy of SIZEOFHASH bytes from vHash32 to oHash
for (vj = 0; vj<SIZEOFHASH; ++vj)
oHash[vj] = (byte)(vHash32[vj>>2]>>((vj&3)<<3));
}

// hash each argument, print its hash and the (quoted) argument
int main(int argc, char *argv[])
{
byte    vHash[SIZEOFHASH];
int     vj,va;
for(va=1; va<argc; ++va) {
hashmd160((const byte *)(argv[va]),strlen(argv[va]),vHash);
for (vj = 0; vj<SIZEOFHASH; ++vj)
printf("%02x",vHash[vj]);
printf(" \"%s\"\n",argv[va]);
}
return EXIT_SUCCESS;
}

/* Example output
9c1185a5c5e9fc54612808977ee8f548b2258d31 ""
0bdc9d2d256b3ee9daae347be6f4dc835a467ffe "a"
8eb208f7e05d987a9b044a8e98c6b087f15a0bfc "abc"
5d0689ef49d2fae572b881b123a85ffa21595f36 "message digest"
f71c27109c692c1b56bbdceb5b9d2865b3708dbc "abcdefghijklmnopqrstuvwxyz"