2

Does RIPEMD 160 have a padding scheme that is identical to SHA-2 (to the point I could share a method I already write that works with it)? The documentation doesn't make it entirely clear. I've gone over all documentation and code I've found and I'm sure I've got the design of the compression function right but the code doesn't return the correct result. Here's the Java code:

public class RIPEMD160 implements HashAlgorithm {

  /**
   * Message word left.
   */
  private static final int[] R_LEFT = {
      0,  1,  2,  3,  4,  5,  6,  7,  8, 9, 10, 11, 12, 13, 14, 15,
      7,  4, 13,  1, 10,  6, 15,  3, 12, 0,  9,  5,  2, 14, 11,  8,
      3, 10, 14,  4,  9, 15,  8,  1,  2, 7,  0,  6, 13, 11,  5, 12,
      1,  9, 11, 10,  0,  8, 12,  4, 13, 3,  7, 15, 14,  5,  6,  2,
      4,  0,  5,  9,  7, 12,  2, 10, 14, 1,  3,  8, 11,  6, 15, 13 };

  /**
   * Message word right.
   */
  private static final int[] R_RIGHT = {
       5, 14,  7, 0, 9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3, 12,
       6, 11,  3, 7, 0, 13,  5, 10, 14, 15,  8, 12,  4,  9,  1,  2,
      15,  5,  1, 3, 7, 14,  6,  9, 11,  8, 12,  2, 10,  0,  4, 13,
       8,  6,  4, 1, 3, 11, 15,  0,  5, 12,  2, 13,  9,  7, 10, 14,
      12, 15, 10, 4, 1,  5,  8,  7,  6,  2, 13, 14,  0,  3,  9, 11 };

  /**
   * Rotate left.
   */
  private static final int[] S_LEFT = {
      11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8,
       7,  6,  8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12,
      11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5,
      11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12,
       9, 15,  5, 11,  6,  8, 13, 12,  5, 12, 13, 14, 11,  8,  5,  6 };

  /**
   * Rotate right.
   */
  private static final int[] S_RIGHT = {
       8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6,
       9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11,
       9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5,
      15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8,
       8,  5, 12,  9, 12,  5, 14,  6,  8, 13,  6,  5, 15, 13, 11, 11 };

    @Override
    public String getHashDigest(String message) {
        List<Integer> padded = HashUtils.pad512(message);

        int blocks = padded.size() / 16;

        //Set hash registers to initial values.
        int h0 = 0x67452301;
        int h1 = 0xefcdab89;
        int h2 = 0x98badcfe;
        int h3 = 0x10325476;
        int h4 = 0xc3d2e1f0;

        int index = 0;
        int[] x = new int[16];

        for (int i = 0; i < blocks; i++) {
            //Push block words into array
            for(int j = 0; j < 16; j++) {
                x[j] = padded.get(index++);
            } //f

            //Left hand side registers.
            int a1 = h0;
            int b1 = h1;
            int c1 = h2;
            int d1 = h3;
            int e1 = h4;

            //Right hand side registers.
            int a2 = h0;
            int b2 = h1;
            int c2 = h2;
            int d2 = h3;
            int e2 = h4;

            //Temp values;
            int t;

            //Compression function. Made up of two lots of 5 sub blocks.
            for(int j = 0; j < 80; j++) {
                t = a1 + nonlinearFunction(j, b1, c1, d1) + x[R_LEFT[j]] + leftK(j);
                a1 = e1;
                e1 = d1;
                d1 = rotateLeft(c1, 10);
                c1 = b1;
                b1 = rotateLeft(t, S_LEFT[j]) + a1;

                t = a2 + nonlinearFunction(79 - j, b2, c2, d2) + x[R_RIGHT[j]] + rightK(j);
                a2 = e2;
                e2 = d2;
                d2 = rotateLeft(c2, 10);
                c2 = b2;
                b2 = rotateLeft(t, S_RIGHT[j]) + a2;
            } //f

            //Mixing at bottom.
            t = h1 + c1 + d2;
            h1 = h2 + d1 + e2;
            h2 = h3 + e1 + a2;
            h3 = h4 + a1 + b2;
            h4 = h0 + b1 + c2;
            h0 = t;
        } //f

        return HashUtils.paddedHexadeciaml(h0)
                + HashUtils.paddedHexadeciaml(h1)
                + HashUtils.paddedHexadeciaml(h2)
                + HashUtils.paddedHexadeciaml(h3)
                + HashUtils.paddedHexadeciaml(h4);
    }

    private int rotateLeft(int x, int r) {
        return (x << r) | (x >>> (32 - r));
    }

    private int nonlinearFunction(int j, int x, int y, int z) {
        if (j <= 15) {
            return x ^ y ^ z;
        } else if (j <= 31) {
            return (x & y) | (~x & z);
        } else if (j <= 47) {
            return (x | ~y) ^ z;
        } else if (j <= 63) {
            return (x & z) | (y & ~z);            
        } else {
            return x ^ (y | ~z);
        } //iel
    }

    private int leftK(int j) {
        if (j <= 15) {
            return 0;
        } else if (j <= 31) {
            return 0x5a827999;
        } else if (j <= 47) {
            return 0x6ed9eba1;
        } else if (j <= 63) {
            return 0x8f1bbcdc;
        } else {
            return 0xa953fd4e;
        } //iel
    }

    private int rightK(int j) {
        if (j <= 15) {
            return 0x50a28be6;
        } else if (j <= 31) {
            return 0x5c4dd124;
        } else if (j <= 47) {
            return 0x6d703ef3;
        } else if (j <= 63) {
            return 0x7a6d76e9;
        } else {
            return 0;
        } //iel
    }

    @Override
    public String getAlgorithmName() {
        return "RIPEMD160";
    }
}

Like I said the pad method returns a list that works with SHA-2; tell me if you need to see it too. Can you see what I'm doing wrong here?

Ghost
  • 103
  • 4

1 Answers1

2

If I take a look at the reference implementation then it seems that it does the same bit padding (using memset with zero values and writing a zero bit), but then it ends with:

/* append length in bits*/
X[14] = lswlen << 3;
X[15] = (lswlen >> 29) | (mswlen << 3);
compress(MDbuf, X);

So I guess you need to compress the message length as well, probably to avoid length extension attacks.

Compile the ref. implementation and step through it or print intermediate values to find out if your intermediate states are correct.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Did this answer your question ghost? Don't forget to accept answers. I can see you've asked 5 questions and did not accept a single one of the - including ones with many upvotes. – Maarten Bodewes Jun 28 '14 at 13:01