📄 ripemd128.java
字号:
// $Id: RIPEMD128.java,v 1.1.1.1 2002/08/27 12:32:12 grosbois Exp $//// $Log: RIPEMD128.java,v $// Revision 1.1.1.1 2002/08/27 12:32:12 grosbois// Add cryptix 3.2//// Revision 1.4 1997/12/07 07:25:29 hopwood// + Committed changes below.//// Revision 1.3.1 1997/12/07 hopwood// + Removed '-' from RIPEMD-128 in comments and debug output, since RIPEMD128 is// the standard name.//// Revision 1.3 1997/12/05 19:09:02 raif// + removed '-' from string in Debug.getLevel() invocation.// + cosmetics.//// Revision 1.2 1997/11/20 19:36:30 hopwood// + cryptix.util.* name changes.//// Revision 1.1.1.1 1997/11/03 22:36:56 hopwood// + Imported to CVS (tagged as 'start').//// Revision 0.1.0.3 1997/08/14 David Hopwood// + Added CONTEXT_LENGTH constant.// + Implemented engineGetDigestLength method.// + Required native code version is 2.3.//// Revision 0.1.0.2 1997/07/21 David Hopwood// + Changed name of first parameter to native_hash from ctx to context,// to be consistent with native code.// + Check validity of arguments before calling native_hash.//// Revision 0.1.0.1 1997/07/15 David Hopwood// + Changed 'Object native_lock' to 'boolean native_ok'.// + Removed 'synchronized (native_lock) { ... }' around native_hash call.// It isn't necessary to synchronize calls to native methods in this case,// because unlike the cipher classes, the native code for hash functions// is stateless.//// Revision 0.1.0.0 1997/07/14 R. Naffah// + Original version//// $Endlog$/* * Copyright (c) 1997 Systemics Ltd * on behalf of the Cryptix Development Team. All rights reserved. */package cryptix.provider.md;import cryptix.util.core.Debug;import java.io.PrintWriter;import java.security.MessageDigest;/** * Implements the RIPEMD128 message digest algorithm in Java as per the * reference below. * <p> * <b>References:</b> * <ol> * <li> Hans Dobbertin, Antoon Bosselaers and Bart Preneel, * "RIPEMD-160: A Strengthened Version of RIPEMD," 18 April 1996. * A joint publication by the German Information Security Agency * (POB 20 03 63, D-53133 Bonn, Germany) * and the Katholieke Universiteit Leuven, ESAT-COSIC * (K. Mercierlaan 94, B-3001 Heverlee, Belgium). * </ol> * <p> * <b>Copyright</b> © 1997 * <a href="http://www.systemics.com/">Systemics Ltd</a> on behalf of the * <a href="http://www.systemics.com/docs/cryptix/">Cryptix Development Team</a>. * <br>All rights reserved. * <p> * <b>$Revision: 1.1.1.1 $</b> * @author Raif S. Naffah * @author David Hopwood * @since Cryptix 2.2.2 */public class RIPEMD128extends MessageDigestimplements Cloneable{// Debugging methods and vars.//........................................................................... private static final boolean DEBUG = Debug.GLOBAL_DEBUG; private static final boolean DEBUG_SLOW = Debug.GLOBAL_DEBUG_SLOW; private static int debuglevel = DEBUG ? Debug.getLevel("RIPEMD128") : 0; private static final PrintWriter err = DEBUG ? Debug.getOutput() : null; private static void debug(String s) { err.println("RIPEMD128: " + s); }// Native library linking methods and vars.//........................................................................... private static NativeLink linkStatus = new NativeLink("RIPEMD", 2, 3); public static cryptix.util.core.LinkStatus getLinkStatus() { return linkStatus; } /** * This flag is false if the native code is not being used (e.g. the * library did not load successfully, or the user disabled its use in * the properties file). */ private boolean native_ok; // defaults to false private void link() { synchronized(linkStatus) { try { if (linkStatus.attemptLoad()) linkStatus.checkVersion(getLibMajorVersion(), getLibMinorVersion()); if (linkStatus.useNative()) native_ok = true; } catch (UnsatisfiedLinkError e) { linkStatus.fail(e);if (DEBUG && debuglevel > 2) debug(e.getMessage()); }if (DEBUG && debuglevel > 2) debug("Using native library? " + native_ok); } }// Native implementation of RIPEMD128/160 hash//........................................................................... /** The methods that get the library version. */ private native static int getLibMajorVersion(); private native static int getLibMinorVersion(); /** * Transforms context based on 512 bits from input block starting from * the offset'th byte. * * @param context the current context of this instance. * @param block input array containing data to hash. * @param offset index of where we should start reading from input. * @return an error string if one occurs, or null otherwise. */ private native static String native_hash (int[] context, byte[] block, int offset);// RIPEMD128 specific object variables//........................................................................... private static final int BLOCK_LENGTH = 64; private static final int CONTEXT_LENGTH = 4; /** 128-bit h0, h1, h2, h3 (interim result) */ private int[] context = new int[CONTEXT_LENGTH]; /** Number of bytes processed so far. */ private long count; /** 512 bits input buffer = 16 x 32-bit words = 8 x 64 bytes */ private byte[] buffer = new byte[BLOCK_LENGTH]; /** 512 bits work buffer = 16 x 32-bit words */ private int[] X = new int[16]; /** * Constants for the transform method. They're defined as static because * they're common to all RIPEMD128 instantiated objects; and final since * they're non-modifiable. */ private static final int[] // selection of message word R = { 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}, Rp = { 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}, // amount for rotate left (rol) S = { 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}, Sp = { 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};// Constructors//........................................................................... public RIPEMD128 () { super("RIPEMD128"); engineReset(); link(); } /** This constructor is here to implement cloneability of this class. */ private RIPEMD128 (RIPEMD128 md) { this(); context = (int[]) (md.context.clone()); buffer = (byte[]) (md.buffer.clone()); count = md.count; }// Cloneable method implementation//........................................................................... /** Return a copy of this MD object. */ public Object clone() { return new RIPEMD128(this); }// JCE methods//........................................................................... /** * Resets this object disregarding any temporary data present at the * time of the invocation of this call. */ protected void engineReset () { // magic RIPEMD128 initialisation constants context[0] = 0x67452301; context[1] = 0xEFCDAB89; context[2] = 0x98BADCFE; context[3] = 0x10325476; count = 0L; for (int i = 0; i < BLOCK_LENGTH; i++) buffer[i] = 0; } /** Continue a RIPEMD128 message digest using the input byte. */ protected void engineUpdate (byte input) { // compute number of bytes still unhashed; ie. present in buffer int i = (int)(count % BLOCK_LENGTH); count++; // update number of bytes buffer[i] = input; if (i == BLOCK_LENGTH - 1) transform(buffer, 0); } /** * RIPEMD128 block update operation. * <p> * Continues a RIPEMD128 message digest operation, by filling the buffer, * transform(ing) data in 512-bit message block(s), updating the variables * context and count, and leaving (buffering) the remaining bytes in buffer * for the next update or finish. * * @param input input block * @param offset start of meaningful bytes in input * @param len count of bytes in input block to consider */ public void engineUpdate (byte[] input, int offset, int len) { // make sure we don't exceed input's allocated size/length if (offset < 0 || len < 0 || (long)offset + len > input.length) throw new ArrayIndexOutOfBoundsException(); // compute number of bytes still unhashed; ie. present in buffer int bufferNdx = (int)(count % BLOCK_LENGTH); count += len; // update number of bytes int partLen = BLOCK_LENGTH - bufferNdx; int i = 0; if (len >= partLen) { System.arraycopy(input, offset, buffer, bufferNdx, partLen); transform(buffer, 0); for (i = partLen; i + BLOCK_LENGTH - 1 < len; i+= BLOCK_LENGTH) transform(input, offset + i); bufferNdx = 0; } // buffer remaining input if (i < len) System.arraycopy(input, offset + i, buffer, bufferNdx, len - i); } /** * Complete the hash computation by performing final operations such * as padding. At the return of this engineDigest, the MD engine is * reset. * * @return the array of bytes for the resulting hash value. */ protected byte[] engineDigest () { // pad output (in bytes) to 56 mod 64 int bufferNdx = (int)(count % BLOCK_LENGTH); int padLen = (bufferNdx < 56) ? (56 - bufferNdx) : (120 - bufferNdx); // padding is always binary 1 followed by binary 0s byte[] tail = new byte[padLen + 8]; tail[0] = (byte)0x80; // save number of bits, casting the long to an array of 8 bytes for (int i = 0; i < 8; i++) tail[padLen + i] = (byte)((count * 8) >>> (8 * i)); // append length before final transform engineUpdate(tail, 0, tail.length); byte[] result = new byte[16]; // cast this RIPEMD128's context (array of 4 ints) into an array // of 16 bytes. for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) result[i * 4 + j] = (byte)((context[i] >>> (8 * j)) & 0xFF); engineReset(); return result; } /** <b>SPI</b>: Return the digest length in bytes. */ protected int engineGetDigestLength() { return 16; }// Own methods//........................................................................... /** * RIPEMD128 basic transformation. * <p> * Transforms context based on 512 bits from input block starting from * the offset'th byte. */ private void transform (byte[] block, int offset) { // if allowed to use native library then now's the time if (native_ok) { // should never happen, but this would be a security bug so check it anyway: if (context.length != CONTEXT_LENGTH || offset < 0 || (long)offset + BLOCK_LENGTH > block.length) { throw new InternalError(getAlgorithm() + ": context.length != " + CONTEXT_LENGTH + " || offset < 0 || " + "(long)offset + " + BLOCK_LENGTH + " > block.length"); } linkStatus.check(native_hash(context, block, offset)); return; } int A, B, C, D, Ap, Bp, Cp, Dp, T, s, i; // encode 64 bytes from input block into an array of 16 unsigned // integers. for (i = 0; i < 16; i++) X[i] = (block[offset++] & 0xFF) | (block[offset++] & 0xFF) << 8 | (block[offset++] & 0xFF) << 16 | (block[offset++] & 0xFF) << 24; A = Ap = context[0]; B = Bp = context[1]; C = Cp = context[2]; D = Dp = context[3]; // rounds 0...15 for (i = 0; i < 16; i++) { s = S[i]; T = A + (B ^ C ^ D) + X[i]; A = D; D = C; C = B; B = T << s | T >>> (32 - s); s = Sp[i]; T = Ap + ((Bp & Dp) | (Cp & ~Dp)) + X[Rp[i]] + 0x50A28BE6; Ap = Dp; Dp = Cp; Cp = Bp; Bp = T << s | T >>> (32 - s); } // rounds 16...31 for (i = 16; i < 32; i++) { s = S[i]; T = A + ((B & C) | (~B & D)) + X[R[i]] + 0x5A827999; A = D; D = C; C = B; B = T << s | T >>> (32 - s); s = Sp[i]; T = Ap + ((Bp | ~Cp) ^ Dp) + X[Rp[i]] + 0x5C4DD124; Ap = Dp; Dp = Cp; Cp = Bp; Bp = T << s | T >>> (32 - s); } // rounds 32...47 for (i = 32; i < 48; i++) { s = S[i]; T = A + ((B | ~C) ^ D) + X[R[i]] + 0x6ED9EBA1; A = D; D = C; C = B; B = T << s | T >>> (32 - s); s = Sp[i]; T = Ap + ((Bp & Cp) | (~Bp & Dp)) + X[Rp[i]] + 0x6D703EF3; Ap = Dp; Dp = Cp; Cp = Bp; Bp = T << s | T >>> (32 - s); } // rounds 48...63 for (i = 48; i < 64; i++) { s = S[i]; T = A + ((B & D) | (C & ~D)) + X[R[i]] + 0x8F1BBCDC; A = D; D = C; C = B; B = T << s | T >>> (32 - s); s = Sp[i]; T = Ap + (Bp ^ Cp ^ Dp) + X[Rp[i]]; Ap = Dp; Dp = Cp; Cp = Bp; Bp = T << s | T >>> (32 - s); } T = context[1] + C + Dp; context[1] = context[2] + D + Ap; context[2] = context[3] + A + Bp; context[3] = context[0] + B + Cp; context[0] = T; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -