填充RIPEMD 160

时间:2014-06-23 14:09:24

标签: java hash cryptography ripemd

RIPEMD 160是否有一个与SHA-2相同的填充方案(我可以共享一个我已经编写过的方法)?文档并没有完全清楚。我已经查看了我发现的所有文档和代码,并且我确信我已经正确设计了压缩功能,但代码并没有返回正确的结果。这是Java代码:

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";
    }
}

就像我说pad方法返回一个与SHA-2一起工作的列表;告诉我你是否也需要看到它。你能看到我在这里做错了吗?

1 个答案:

答案 0 :(得分:2)

如果我看一下reference implementation那么它似乎做了相同的位填充(使用memset使用零值并写入零位),但它结束于:

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

所以我猜你也需要压缩消息长度,这可能是为了避免长度扩展攻击。

编译引用。实现并逐步执行或打印中间值以确定您的中间状态是否正确。