All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.milton.zsync.MD4 Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/* vim:set softtabstop=3 shiftwidth=3 tabstop=3 expandtab tw=72:
   $Id: MD4.java,v 1.9 2003/03/30 15:18:46 rsdio Exp $
  
   This version is derived from the version in GNU Crypto.
  
   MD4: The MD4 message digest algorithm.
   Copyright (C) 2002 The Free Software Foundation, Inc.
   Copyright (C) 2003  Casey Marshall 
  
   This file is a part of Jarsync.
  
   Jarsync is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2 of the License, or (at
   your option) any later version.
  
   Jarsync is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.
  
   You should have received a copy of the GNU General Public License
   along with Jarsync; if not, write to the
  
      Free Software Foundation, Inc.,
      59 Temple Place, Suite 330,
      Boston, MA  02111-1307
      USA
  
   Linking Jarsync statically or dynamically with other modules is
   making a combined work based on Jarsync.  Thus, the terms and
   conditions of the GNU General Public License cover the whole
   combination.  */

package io.milton.zsync;

import java.security.DigestException;
import java.security.MessageDigestSpi;

/**
 * 

An implementation of Ron Rivest's MD4 message digest algorithm. * MD4 was the precursor to the stronger MD5 * algorithm, and while not considered cryptograpically secure itself, * MD4 is in use in various applications. It is slightly faster than * MD5.

* *

This implementation is derived from the version of MD4 in GNU Crypto.

* *

References:

* *
    *
  1. The MD4 Message- * Digest Algorithm.
    * R. Rivest.
  2. *
* * @version $Revision: 1.9 $ */ public class MD4 extends MessageDigestSpi implements Cloneable { // Constants and variables. // ----------------------------------------------------------------- /** * An MD4 message digest is always 128-bits long, or 16 bytes. */ public static final int DIGEST_LENGTH = 16; /** * The MD4 algorithm operates on 512-bit blocks, or 64 bytes. */ public static final int BLOCK_LENGTH = 64; protected static final int A = 0x67452301; protected static final int B = 0xefcdab89; protected static final int C = 0x98badcfe; protected static final int D = 0x10325476; /* The four chaining variables. */ protected int a, b, c, d; protected long count; protected final byte[] buffer; /** * Word buffer for transforming. */ private final int[] X = new int[16]; // Constructors. // ----------------------------------------------------------------- /** * Trivial zero-argument constructor. */ public MD4() { buffer = new byte[BLOCK_LENGTH]; engineReset(); } /** * Private constructor for cloning. */ private MD4(MD4 that) { this(); this.a = that.a; this.b = that.b; this.c = that.c; this.d = that.d; this.count = that.count; System.arraycopy(that.buffer, 0, this.buffer, 0, BLOCK_LENGTH); } // java.lang.Cloneable interface implementation -------------------- public Object clone() { return new MD4(this); } // SPI instance methods. // ----------------------------------------------------------------- protected int engineGetDigestLength() { return DIGEST_LENGTH; } public void engineUpdate(byte b) { // compute number of bytes still unhashed; ie. present in buffer int i = (int) (count % BLOCK_LENGTH); count++; buffer[i] = b; if (i == (BLOCK_LENGTH - 1)) { transform(buffer, 0); } } protected void engineUpdate(byte[] b, int offset, int len) { int n = (int) (count % BLOCK_LENGTH); count += len; int partLen = BLOCK_LENGTH - n; int i = 0; if (len >= partLen) { System.arraycopy(b, offset, buffer, n, partLen); transform(buffer, 0); for (i = partLen; i + BLOCK_LENGTH - 1 < len; i += BLOCK_LENGTH) { transform(b, offset + i); } n = 0; } if (i < len) { System.arraycopy(b, offset + i, buffer, n, len - i); } } /** * Pack the four chaining variables into a byte array. */ protected byte[] engineDigest() { byte[] tail = padBuffer(); engineUpdate(tail, 0, tail.length); byte[] digest = { (byte) a, (byte) (a >>> 8), (byte) (a >>> 16), (byte) (a >>> 24), (byte) b, (byte) (b >>> 8), (byte) (b >>> 16), (byte) (b >>> 24), (byte) c, (byte) (c >>> 8), (byte) (c >>> 16), (byte) (c >>> 24), (byte) d, (byte) (d >>> 8), (byte) (d >>> 16), (byte) (d >>> 24) }; engineReset(); return digest; } protected int engineDigest(byte[] out, int off, int len) throws DigestException { if (off < 0 || off + len >= out.length) { throw new DigestException(); } System.arraycopy(engineDigest(), 0, out, off, Math.min(len, DIGEST_LENGTH)); return Math.min(len, DIGEST_LENGTH); } /** * Reset the four chaining variables. */ protected void engineReset() { a = A; b = B; c = C; d = D; count = 0; } /** * Pad the buffer by appending the byte 0x80, then as many zero bytes * to fill the buffer 8 bytes shy of being a multiple of 64 bytes, then * append the length of the buffer, in bits, before padding. */ protected byte[] padBuffer() { int n = (int) (count % BLOCK_LENGTH); int padding = (n < 56) ? (56 - n) : (120 - n); byte[] pad = new byte[padding + 8]; pad[0] = (byte) 0x80; long bits = count << 3; pad[padding++] = (byte) bits; pad[padding++] = (byte) (bits >>> 8); pad[padding++] = (byte) (bits >>> 16); pad[padding++] = (byte) (bits >>> 24); pad[padding++] = (byte) (bits >>> 32); pad[padding++] = (byte) (bits >>> 40); pad[padding++] = (byte) (bits >>> 48); pad[padding] = (byte) (bits >>> 56); return pad; } /** * Transform a 64-byte block. */ protected void transform(byte[] in, int offset) { int aa, bb, cc, dd; for (int i = 0, n = 0; i < 16; i++) { X[i] = (in[offset++] & 0xff) | (in[offset++] & 0xff) << 8 | (in[offset++] & 0xff) << 16 | (in[offset++] & 0xff) << 24; } aa = a; bb = b; cc = c; dd = d; // Round 1 a += ((b & c) | ((~b) & d)) + X[0]; a = a << 3 | a >>> (32 - 3); d += ((a & b) | ((~a) & c)) + X[1]; d = d << 7 | d >>> (32 - 7); c += ((d & a) | ((~d) & b)) + X[2]; c = c << 11 | c >>> (32 - 11); b += ((c & d) | ((~c) & a)) + X[3]; b = b << 19 | b >>> (32 - 19); a += ((b & c) | ((~b) & d)) + X[4]; a = a << 3 | a >>> (32 - 3); d += ((a & b) | ((~a) & c)) + X[5]; d = d << 7 | d >>> (32 - 7); c += ((d & a) | ((~d) & b)) + X[6]; c = c << 11 | c >>> (32 - 11); b += ((c & d) | ((~c) & a)) + X[7]; b = b << 19 | b >>> (32 - 19); a += ((b & c) | ((~b) & d)) + X[8]; a = a << 3 | a >>> (32 - 3); d += ((a & b) | ((~a) & c)) + X[9]; d = d << 7 | d >>> (32 - 7); c += ((d & a) | ((~d) & b)) + X[10]; c = c << 11 | c >>> (32 - 11); b += ((c & d) | ((~c) & a)) + X[11]; b = b << 19 | b >>> (32 - 19); a += ((b & c) | ((~b) & d)) + X[12]; a = a << 3 | a >>> (32 - 3); d += ((a & b) | ((~a) & c)) + X[13]; d = d << 7 | d >>> (32 - 7); c += ((d & a) | ((~d) & b)) + X[14]; c = c << 11 | c >>> (32 - 11); b += ((c & d) | ((~c) & a)) + X[15]; b = b << 19 | b >>> (32 - 19); // Round 2. a += ((b & (c | d)) | (c & d)) + X[0] + 0x5a827999; a = a << 3 | a >>> (32 - 3); d += ((a & (b | c)) | (b & c)) + X[4] + 0x5a827999; d = d << 5 | d >>> (32 - 5); c += ((d & (a | b)) | (a & b)) + X[8] + 0x5a827999; c = c << 9 | c >>> (32 - 9); b += ((c & (d | a)) | (d & a)) + X[12] + 0x5a827999; b = b << 13 | b >>> (32 - 13); a += ((b & (c | d)) | (c & d)) + X[1] + 0x5a827999; a = a << 3 | a >>> (32 - 3); d += ((a & (b | c)) | (b & c)) + X[5] + 0x5a827999; d = d << 5 | d >>> (32 - 5); c += ((d & (a | b)) | (a & b)) + X[9] + 0x5a827999; c = c << 9 | c >>> (32 - 9); b += ((c & (d | a)) | (d & a)) + X[13] + 0x5a827999; b = b << 13 | b >>> (32 - 13); a += ((b & (c | d)) | (c & d)) + X[2] + 0x5a827999; a = a << 3 | a >>> (32 - 3); d += ((a & (b | c)) | (b & c)) + X[6] + 0x5a827999; d = d << 5 | d >>> (32 - 5); c += ((d & (a | b)) | (a & b)) + X[10] + 0x5a827999; c = c << 9 | c >>> (32 - 9); b += ((c & (d | a)) | (d & a)) + X[14] + 0x5a827999; b = b << 13 | b >>> (32 - 13); a += ((b & (c | d)) | (c & d)) + X[3] + 0x5a827999; a = a << 3 | a >>> (32 - 3); d += ((a & (b | c)) | (b & c)) + X[7] + 0x5a827999; d = d << 5 | d >>> (32 - 5); c += ((d & (a | b)) | (a & b)) + X[11] + 0x5a827999; c = c << 9 | c >>> (32 - 9); b += ((c & (d | a)) | (d & a)) + X[15] + 0x5a827999; b = b << 13 | b >>> (32 - 13); // Round 3. a += (b ^ c ^ d) + X[0] + 0x6ed9eba1; a = a << 3 | a >>> (32 - 3); d += (a ^ b ^ c) + X[8] + 0x6ed9eba1; d = d << 9 | d >>> (32 - 9); c += (d ^ a ^ b) + X[4] + 0x6ed9eba1; c = c << 11 | c >>> (32 - 11); b += (c ^ d ^ a) + X[12] + 0x6ed9eba1; b = b << 15 | b >>> (32 - 15); a += (b ^ c ^ d) + X[2] + 0x6ed9eba1; a = a << 3 | a >>> (32 - 3); d += (a ^ b ^ c) + X[10] + 0x6ed9eba1; d = d << 9 | d >>> (32 - 9); c += (d ^ a ^ b) + X[6] + 0x6ed9eba1; c = c << 11 | c >>> (32 - 11); b += (c ^ d ^ a) + X[14] + 0x6ed9eba1; b = b << 15 | b >>> (32 - 15); a += (b ^ c ^ d) + X[1] + 0x6ed9eba1; a = a << 3 | a >>> (32 - 3); d += (a ^ b ^ c) + X[9] + 0x6ed9eba1; d = d << 9 | d >>> (32 - 9); c += (d ^ a ^ b) + X[5] + 0x6ed9eba1; c = c << 11 | c >>> (32 - 11); b += (c ^ d ^ a) + X[13] + 0x6ed9eba1; b = b << 15 | b >>> (32 - 15); a += (b ^ c ^ d) + X[3] + 0x6ed9eba1; a = a << 3 | a >>> (32 - 3); d += (a ^ b ^ c) + X[11] + 0x6ed9eba1; d = d << 9 | d >>> (32 - 9); c += (d ^ a ^ b) + X[7] + 0x6ed9eba1; c = c << 11 | c >>> (32 - 11); b += (c ^ d ^ a) + X[15] + 0x6ed9eba1; b = b << 15 | b >>> (32 - 15); a += aa; b += bb; c += cc; d += dd; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy