| package org.bouncycastle.crypto.digests; |
| |
| |
| import org.bouncycastle.util.Memoable; |
| |
| /** |
| * implementation of RIPEMD256. |
| * <p> |
| * <b>note:</b> this algorithm offers the same level of security as RIPEMD128. |
| */ |
| public class RIPEMD256Digest |
| extends GeneralDigest |
| { |
| private static final int DIGEST_LENGTH = 32; |
| |
| private int H0, H1, H2, H3, H4, H5, H6, H7; // IV's |
| |
| private int[] X = new int[16]; |
| private int xOff; |
| |
| /** |
| * Standard constructor |
| */ |
| public RIPEMD256Digest() |
| { |
| reset(); |
| } |
| |
| /** |
| * Copy constructor. This will copy the state of the provided |
| * message digest. |
| */ |
| public RIPEMD256Digest(RIPEMD256Digest t) |
| { |
| super(t); |
| |
| copyIn(t); |
| } |
| |
| private void copyIn(RIPEMD256Digest t) |
| { |
| super.copyIn(t); |
| |
| H0 = t.H0; |
| H1 = t.H1; |
| H2 = t.H2; |
| H3 = t.H3; |
| H4 = t.H4; |
| H5 = t.H5; |
| H6 = t.H6; |
| H7 = t.H7; |
| |
| System.arraycopy(t.X, 0, X, 0, t.X.length); |
| xOff = t.xOff; |
| } |
| |
| public String getAlgorithmName() |
| { |
| return "RIPEMD256"; |
| } |
| |
| public int getDigestSize() |
| { |
| return DIGEST_LENGTH; |
| } |
| |
| protected void processWord( |
| byte[] in, |
| int inOff) |
| { |
| X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8) |
| | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); |
| |
| if (xOff == 16) |
| { |
| processBlock(); |
| } |
| } |
| |
| protected void processLength( |
| long bitLength) |
| { |
| if (xOff > 14) |
| { |
| processBlock(); |
| } |
| |
| X[14] = (int)(bitLength & 0xffffffff); |
| X[15] = (int)(bitLength >>> 32); |
| } |
| |
| private void unpackWord( |
| int word, |
| byte[] out, |
| int outOff) |
| { |
| out[outOff] = (byte)word; |
| out[outOff + 1] = (byte)(word >>> 8); |
| out[outOff + 2] = (byte)(word >>> 16); |
| out[outOff + 3] = (byte)(word >>> 24); |
| } |
| |
| public int doFinal( |
| byte[] out, |
| int outOff) |
| { |
| finish(); |
| |
| unpackWord(H0, out, outOff); |
| unpackWord(H1, out, outOff + 4); |
| unpackWord(H2, out, outOff + 8); |
| unpackWord(H3, out, outOff + 12); |
| unpackWord(H4, out, outOff + 16); |
| unpackWord(H5, out, outOff + 20); |
| unpackWord(H6, out, outOff + 24); |
| unpackWord(H7, out, outOff + 28); |
| |
| reset(); |
| |
| return DIGEST_LENGTH; |
| } |
| |
| /** |
| * reset the chaining variables to the IV values. |
| */ |
| public void reset() |
| { |
| super.reset(); |
| |
| H0 = 0x67452301; |
| H1 = 0xefcdab89; |
| H2 = 0x98badcfe; |
| H3 = 0x10325476; |
| H4 = 0x76543210; |
| H5 = 0xFEDCBA98; |
| H6 = 0x89ABCDEF; |
| H7 = 0x01234567; |
| |
| xOff = 0; |
| |
| for (int i = 0; i != X.length; i++) |
| { |
| X[i] = 0; |
| } |
| } |
| |
| /* |
| * rotate int x left n bits. |
| */ |
| private int RL( |
| int x, |
| int n) |
| { |
| return (x << n) | (x >>> (32 - n)); |
| } |
| |
| /* |
| * f1,f2,f3,f4 are the basic RIPEMD128 functions. |
| */ |
| |
| /* |
| * F |
| */ |
| private int f1( |
| int x, |
| int y, |
| int z) |
| { |
| return x ^ y ^ z; |
| } |
| |
| /* |
| * G |
| */ |
| private int f2( |
| int x, |
| int y, |
| int z) |
| { |
| return (x & y) | (~x & z); |
| } |
| |
| /* |
| * H |
| */ |
| private int f3( |
| int x, |
| int y, |
| int z) |
| { |
| return (x | ~y) ^ z; |
| } |
| |
| /* |
| * I |
| */ |
| private int f4( |
| int x, |
| int y, |
| int z) |
| { |
| return (x & z) | (y & ~z); |
| } |
| |
| private int F1( |
| int a, |
| int b, |
| int c, |
| int d, |
| int x, |
| int s) |
| { |
| return RL(a + f1(b, c, d) + x, s); |
| } |
| |
| private int F2( |
| int a, |
| int b, |
| int c, |
| int d, |
| int x, |
| int s) |
| { |
| return RL(a + f2(b, c, d) + x + 0x5a827999, s); |
| } |
| |
| private int F3( |
| int a, |
| int b, |
| int c, |
| int d, |
| int x, |
| int s) |
| { |
| return RL(a + f3(b, c, d) + x + 0x6ed9eba1, s); |
| } |
| |
| private int F4( |
| int a, |
| int b, |
| int c, |
| int d, |
| int x, |
| int s) |
| { |
| return RL(a + f4(b, c, d) + x + 0x8f1bbcdc, s); |
| } |
| |
| private int FF1( |
| int a, |
| int b, |
| int c, |
| int d, |
| int x, |
| int s) |
| { |
| return RL(a + f1(b, c, d) + x, s); |
| } |
| |
| private int FF2( |
| int a, |
| int b, |
| int c, |
| int d, |
| int x, |
| int s) |
| { |
| return RL(a + f2(b, c, d) + x + 0x6d703ef3, s); |
| } |
| |
| private int FF3( |
| int a, |
| int b, |
| int c, |
| int d, |
| int x, |
| int s) |
| { |
| return RL(a + f3(b, c, d) + x + 0x5c4dd124, s); |
| } |
| |
| private int FF4( |
| int a, |
| int b, |
| int c, |
| int d, |
| int x, |
| int s) |
| { |
| return RL(a + f4(b, c, d) + x + 0x50a28be6, s); |
| } |
| |
| protected void processBlock() |
| { |
| int a, aa; |
| int b, bb; |
| int c, cc; |
| int d, dd; |
| int t; |
| |
| a = H0; |
| b = H1; |
| c = H2; |
| d = H3; |
| aa = H4; |
| bb = H5; |
| cc = H6; |
| dd = H7; |
| |
| // |
| // Round 1 |
| // |
| |
| a = F1(a, b, c, d, X[ 0], 11); |
| d = F1(d, a, b, c, X[ 1], 14); |
| c = F1(c, d, a, b, X[ 2], 15); |
| b = F1(b, c, d, a, X[ 3], 12); |
| a = F1(a, b, c, d, X[ 4], 5); |
| d = F1(d, a, b, c, X[ 5], 8); |
| c = F1(c, d, a, b, X[ 6], 7); |
| b = F1(b, c, d, a, X[ 7], 9); |
| a = F1(a, b, c, d, X[ 8], 11); |
| d = F1(d, a, b, c, X[ 9], 13); |
| c = F1(c, d, a, b, X[10], 14); |
| b = F1(b, c, d, a, X[11], 15); |
| a = F1(a, b, c, d, X[12], 6); |
| d = F1(d, a, b, c, X[13], 7); |
| c = F1(c, d, a, b, X[14], 9); |
| b = F1(b, c, d, a, X[15], 8); |
| |
| aa = FF4(aa, bb, cc, dd, X[ 5], 8); |
| dd = FF4(dd, aa, bb, cc, X[14], 9); |
| cc = FF4(cc, dd, aa, bb, X[ 7], 9); |
| bb = FF4(bb, cc, dd, aa, X[ 0], 11); |
| aa = FF4(aa, bb, cc, dd, X[ 9], 13); |
| dd = FF4(dd, aa, bb, cc, X[ 2], 15); |
| cc = FF4(cc, dd, aa, bb, X[11], 15); |
| bb = FF4(bb, cc, dd, aa, X[ 4], 5); |
| aa = FF4(aa, bb, cc, dd, X[13], 7); |
| dd = FF4(dd, aa, bb, cc, X[ 6], 7); |
| cc = FF4(cc, dd, aa, bb, X[15], 8); |
| bb = FF4(bb, cc, dd, aa, X[ 8], 11); |
| aa = FF4(aa, bb, cc, dd, X[ 1], 14); |
| dd = FF4(dd, aa, bb, cc, X[10], 14); |
| cc = FF4(cc, dd, aa, bb, X[ 3], 12); |
| bb = FF4(bb, cc, dd, aa, X[12], 6); |
| |
| t = a; a = aa; aa = t; |
| |
| // |
| // Round 2 |
| // |
| a = F2(a, b, c, d, X[ 7], 7); |
| d = F2(d, a, b, c, X[ 4], 6); |
| c = F2(c, d, a, b, X[13], 8); |
| b = F2(b, c, d, a, X[ 1], 13); |
| a = F2(a, b, c, d, X[10], 11); |
| d = F2(d, a, b, c, X[ 6], 9); |
| c = F2(c, d, a, b, X[15], 7); |
| b = F2(b, c, d, a, X[ 3], 15); |
| a = F2(a, b, c, d, X[12], 7); |
| d = F2(d, a, b, c, X[ 0], 12); |
| c = F2(c, d, a, b, X[ 9], 15); |
| b = F2(b, c, d, a, X[ 5], 9); |
| a = F2(a, b, c, d, X[ 2], 11); |
| d = F2(d, a, b, c, X[14], 7); |
| c = F2(c, d, a, b, X[11], 13); |
| b = F2(b, c, d, a, X[ 8], 12); |
| |
| aa = FF3(aa, bb, cc, dd, X[ 6], 9); |
| dd = FF3(dd, aa, bb, cc, X[ 11], 13); |
| cc = FF3(cc, dd, aa, bb, X[3], 15); |
| bb = FF3(bb, cc, dd, aa, X[ 7], 7); |
| aa = FF3(aa, bb, cc, dd, X[0], 12); |
| dd = FF3(dd, aa, bb, cc, X[13], 8); |
| cc = FF3(cc, dd, aa, bb, X[5], 9); |
| bb = FF3(bb, cc, dd, aa, X[10], 11); |
| aa = FF3(aa, bb, cc, dd, X[14], 7); |
| dd = FF3(dd, aa, bb, cc, X[15], 7); |
| cc = FF3(cc, dd, aa, bb, X[ 8], 12); |
| bb = FF3(bb, cc, dd, aa, X[12], 7); |
| aa = FF3(aa, bb, cc, dd, X[ 4], 6); |
| dd = FF3(dd, aa, bb, cc, X[ 9], 15); |
| cc = FF3(cc, dd, aa, bb, X[ 1], 13); |
| bb = FF3(bb, cc, dd, aa, X[ 2], 11); |
| |
| t = b; b = bb; bb = t; |
| |
| // |
| // Round 3 |
| // |
| a = F3(a, b, c, d, X[ 3], 11); |
| d = F3(d, a, b, c, X[10], 13); |
| c = F3(c, d, a, b, X[14], 6); |
| b = F3(b, c, d, a, X[ 4], 7); |
| a = F3(a, b, c, d, X[ 9], 14); |
| d = F3(d, a, b, c, X[15], 9); |
| c = F3(c, d, a, b, X[ 8], 13); |
| b = F3(b, c, d, a, X[ 1], 15); |
| a = F3(a, b, c, d, X[ 2], 14); |
| d = F3(d, a, b, c, X[ 7], 8); |
| c = F3(c, d, a, b, X[ 0], 13); |
| b = F3(b, c, d, a, X[ 6], 6); |
| a = F3(a, b, c, d, X[13], 5); |
| d = F3(d, a, b, c, X[11], 12); |
| c = F3(c, d, a, b, X[ 5], 7); |
| b = F3(b, c, d, a, X[12], 5); |
| |
| aa = FF2(aa, bb, cc, dd, X[ 15], 9); |
| dd = FF2(dd, aa, bb, cc, X[5], 7); |
| cc = FF2(cc, dd, aa, bb, X[1], 15); |
| bb = FF2(bb, cc, dd, aa, X[ 3], 11); |
| aa = FF2(aa, bb, cc, dd, X[ 7], 8); |
| dd = FF2(dd, aa, bb, cc, X[14], 6); |
| cc = FF2(cc, dd, aa, bb, X[ 6], 6); |
| bb = FF2(bb, cc, dd, aa, X[ 9], 14); |
| aa = FF2(aa, bb, cc, dd, X[11], 12); |
| dd = FF2(dd, aa, bb, cc, X[ 8], 13); |
| cc = FF2(cc, dd, aa, bb, X[12], 5); |
| bb = FF2(bb, cc, dd, aa, X[ 2], 14); |
| aa = FF2(aa, bb, cc, dd, X[10], 13); |
| dd = FF2(dd, aa, bb, cc, X[ 0], 13); |
| cc = FF2(cc, dd, aa, bb, X[ 4], 7); |
| bb = FF2(bb, cc, dd, aa, X[13], 5); |
| |
| t = c; c = cc; cc = t; |
| |
| // |
| // Round 4 |
| // |
| a = F4(a, b, c, d, X[ 1], 11); |
| d = F4(d, a, b, c, X[ 9], 12); |
| c = F4(c, d, a, b, X[11], 14); |
| b = F4(b, c, d, a, X[10], 15); |
| a = F4(a, b, c, d, X[ 0], 14); |
| d = F4(d, a, b, c, X[ 8], 15); |
| c = F4(c, d, a, b, X[12], 9); |
| b = F4(b, c, d, a, X[ 4], 8); |
| a = F4(a, b, c, d, X[13], 9); |
| d = F4(d, a, b, c, X[ 3], 14); |
| c = F4(c, d, a, b, X[ 7], 5); |
| b = F4(b, c, d, a, X[15], 6); |
| a = F4(a, b, c, d, X[14], 8); |
| d = F4(d, a, b, c, X[ 5], 6); |
| c = F4(c, d, a, b, X[ 6], 5); |
| b = F4(b, c, d, a, X[ 2], 12); |
| |
| aa = FF1(aa, bb, cc, dd, X[ 8], 15); |
| dd = FF1(dd, aa, bb, cc, X[ 6], 5); |
| cc = FF1(cc, dd, aa, bb, X[ 4], 8); |
| bb = FF1(bb, cc, dd, aa, X[ 1], 11); |
| aa = FF1(aa, bb, cc, dd, X[ 3], 14); |
| dd = FF1(dd, aa, bb, cc, X[11], 14); |
| cc = FF1(cc, dd, aa, bb, X[15], 6); |
| bb = FF1(bb, cc, dd, aa, X[ 0], 14); |
| aa = FF1(aa, bb, cc, dd, X[ 5], 6); |
| dd = FF1(dd, aa, bb, cc, X[12], 9); |
| cc = FF1(cc, dd, aa, bb, X[ 2], 12); |
| bb = FF1(bb, cc, dd, aa, X[13], 9); |
| aa = FF1(aa, bb, cc, dd, X[ 9], 12); |
| dd = FF1(dd, aa, bb, cc, X[ 7], 5); |
| cc = FF1(cc, dd, aa, bb, X[10], 15); |
| bb = FF1(bb, cc, dd, aa, X[14], 8); |
| |
| t = d; d = dd; dd = t; |
| |
| H0 += a; |
| H1 += b; |
| H2 += c; |
| H3 += d; |
| H4 += aa; |
| H5 += bb; |
| H6 += cc; |
| H7 += dd; |
| |
| // |
| // reset the offset and clean out the word buffer. |
| // |
| xOff = 0; |
| for (int i = 0; i != X.length; i++) |
| { |
| X[i] = 0; |
| } |
| } |
| |
| public Memoable copy() |
| { |
| return new RIPEMD256Digest(this); |
| } |
| |
| public void reset(Memoable other) |
| { |
| RIPEMD256Digest d = (RIPEMD256Digest)other; |
| |
| copyIn(d); |
| } |
| } |