Nuiton-utils-commits
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
April 2009
- 2 participants
- 40 discussions
[Lutinutil-commits] r1456 - lutinutil/trunk/src/main/java/org/codelutin/util
by chatellier@users.labs.libre-entreprise.org 30 Apr '09
by chatellier@users.labs.libre-entreprise.org 30 Apr '09
30 Apr '09
Author: chatellier
Date: 2009-04-30 12:26:16 +0000 (Thu, 30 Apr 2009)
New Revision: 1456
Modified:
lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
Log:
Add doc on md5 parameter.
Add new zip method with null default filter value.
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-30 12:16:04 UTC (rev 1455)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-30 12:26:16 UTC (rev 1456)
@@ -143,10 +143,10 @@
* @param includes the files to include in zip
* @throws java.io.IOException if any problem while compressing
*/
- static public void compressFiles(File zipFile, File root, Collection<File> includes) throws IOException {
+ public static void compressFiles(File zipFile, File root, Collection<File> includes) throws IOException {
compressFiles(zipFile, root, includes, false);
}
-
+
/**
* Compress 'includes' files in zipFile. If file in includes is directory
* only the directory is put in zipFile, not the file contained in directory
@@ -202,7 +202,7 @@
}
/**
- * if fileOrDirectory is directory Compress recursively all file in this
+ * If fileOrDirectory is directory Compress recursively all file in this
* directory, else if is just file compress one file.
* <p/>
* Entry result name in zip start at fileOrDirectory.
@@ -210,15 +210,30 @@
*
* @param zipFile the source zip file
* @param fileOrDirectory the file or directory to compress
+ * @throws IOException if any problem while compressing
+ */
+ public static void compress(File zipFile, File fileOrDirectory) throws IOException {
+ compress(zipFile, fileOrDirectory, null, false);
+ }
+
+ /**
+ * If fileOrDirectory is directory Compress recursively all file in this
+ * directory, else if is just file compress one file.
+ * <p/>
+ * Entry result name in zip start at fileOrDirectory.
+ * example: if we compress /etc/apache, entry will be apache/http.conf, ...
+ *
+ * @param zipFile the source zip file
+ * @param fileOrDirectory the file or directory to compress
* @param filter used to accept file, if null, all file is accepted
* @throws IOException if any problem while compressing
*/
- static public void compress(File zipFile, File fileOrDirectory, FileFilter filter) throws IOException {
+ public static void compress(File zipFile, File fileOrDirectory, FileFilter filter) throws IOException {
compress(zipFile, fileOrDirectory, filter, false);
}
/**
- * if fileOrDirectory is directory Compress recursively all file in this
+ * If fileOrDirectory is directory Compress recursively all file in this
* directory, else if is just file compress one file.
* <p/>
* Entry result name in zip start at fileOrDirectory.
@@ -227,9 +242,10 @@
* @param zipFile the source zip file
* @param fileOrDirectory the file or directory to compress
* @param filter used to accept file, if null, all file is accepted
+ * @param createMD5 also create a MD5 file (zip name + .md5). MD5 file is created after zip.
* @throws IOException if any problem while compressing
*/
- static public void compress(File zipFile, File fileOrDirectory, FileFilter filter, boolean createMD5) throws IOException {
+ public static void compress(File zipFile, File fileOrDirectory, FileFilter filter, boolean createMD5) throws IOException {
if (filter == null) {
filter = ALL_FILE_FILTER;
}
1
0
[Lutinutil-commits] r1455 - lutinutil/trunk/src/main/java/org/codelutin/util
by chatellier@users.labs.libre-entreprise.org 30 Apr '09
by chatellier@users.labs.libre-entreprise.org 30 Apr '09
30 Apr '09
Author: chatellier
Date: 2009-04-30 12:16:04 +0000 (Thu, 30 Apr 2009)
New Revision: 1455
Modified:
lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
Log:
Add md5create parameter on all zip methods
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-29 12:50:30 UTC (rev 1454)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-30 12:16:04 UTC (rev 1455)
@@ -214,6 +214,22 @@
* @throws IOException if any problem while compressing
*/
static public void compress(File zipFile, File fileOrDirectory, FileFilter filter) throws IOException {
+ compress(zipFile, fileOrDirectory, filter, false);
+ }
+
+ /**
+ * if fileOrDirectory is directory Compress recursively all file in this
+ * directory, else if is just file compress one file.
+ * <p/>
+ * Entry result name in zip start at fileOrDirectory.
+ * example: if we compress /etc/apache, entry will be apache/http.conf, ...
+ *
+ * @param zipFile the source zip file
+ * @param fileOrDirectory the file or directory to compress
+ * @param filter used to accept file, if null, all file is accepted
+ * @throws IOException if any problem while compressing
+ */
+ static public void compress(File zipFile, File fileOrDirectory, FileFilter filter, boolean createMD5) throws IOException {
if (filter == null) {
filter = ALL_FILE_FILTER;
}
@@ -224,7 +240,7 @@
files.add(fileOrDirectory);
}
- compressFiles(zipFile, fileOrDirectory.getParentFile(), files);
+ compressFiles(zipFile, fileOrDirectory.getParentFile(), files, createMD5);
}
/**
1
0
[Lutinutil-commits] r1454 - lutinutil/trunk/src/main/java/org/codelutin/util
by chatellier@users.labs.libre-entreprise.org 29 Apr '09
by chatellier@users.labs.libre-entreprise.org 29 Apr '09
29 Apr '09
Author: chatellier
Date: 2009-04-29 12:50:30 +0000 (Wed, 29 Apr 2009)
New Revision: 1454
Modified:
lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
Log:
Change byte[]?\194?\160to String cast
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-29 12:35:14 UTC (rev 1453)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-29 12:50:30 UTC (rev 1454)
@@ -192,7 +192,7 @@
// if md5 creation flag
if (createMD5) {
- String md5hash = new String(((MD5OutputStream)oStream).hash());
+ String md5hash = MD5.asHex(((MD5OutputStream)oStream).hash());
File md5File = new File(zipFile.getAbsoluteFile() + ".md5");
FileUtil.writeString(md5File, md5hash);
}
1
0
[Lutinutil-commits] r1453 - lutinutil/trunk/src/main/java/org/codelutin/util
by chatellier@users.labs.libre-entreprise.org 29 Apr '09
by chatellier@users.labs.libre-entreprise.org 29 Apr '09
29 Apr '09
Author: chatellier
Date: 2009-04-29 12:35:14 +0000 (Wed, 29 Apr 2009)
New Revision: 1453
Modified:
lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
Log:
Change byte[]?\194?\160to String cast
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-29 12:30:26 UTC (rev 1452)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-29 12:35:14 UTC (rev 1453)
@@ -192,7 +192,7 @@
// if md5 creation flag
if (createMD5) {
- String md5hash = String.valueOf(((MD5OutputStream)oStream).hash());
+ String md5hash = new String(((MD5OutputStream)oStream).hash());
File md5File = new File(zipFile.getAbsoluteFile() + ".md5");
FileUtil.writeString(md5File, md5hash);
}
1
0
[Lutinutil-commits] r1452 - lutinutil/trunk/src/main/java/org/codelutin/util
by chatellier@users.labs.libre-entreprise.org 29 Apr '09
by chatellier@users.labs.libre-entreprise.org 29 Apr '09
29 Apr '09
Author: chatellier
Date: 2009-04-29 12:30:26 +0000 (Wed, 29 Apr 2009)
New Revision: 1452
Modified:
lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
Log:
Readd previous fast-MD5 implementation
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-29 12:30:18 UTC (rev 1451)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-29 12:30:26 UTC (rev 1452)
@@ -192,7 +192,7 @@
// if md5 creation flag
if (createMD5) {
- String md5hash = ((MD5OutputStream)oStream).getHashString();
+ String md5hash = String.valueOf(((MD5OutputStream)oStream).hash());
File md5File = new File(zipFile.getAbsoluteFile() + ".md5");
FileUtil.writeString(md5File, md5hash);
}
1
0
[Lutinutil-commits] r1451 - lutinutil/trunk/src/main/java/org/codelutin/util
by chatellier@users.labs.libre-entreprise.org 29 Apr '09
by chatellier@users.labs.libre-entreprise.org 29 Apr '09
29 Apr '09
Author: chatellier
Date: 2009-04-29 12:30:18 +0000 (Wed, 29 Apr 2009)
New Revision: 1451
Added:
lutinutil/trunk/src/main/java/org/codelutin/util/MD5State.java
Modified:
lutinutil/trunk/src/main/java/org/codelutin/util/MD5.java
lutinutil/trunk/src/main/java/org/codelutin/util/MD5InputStream.java
lutinutil/trunk/src/main/java/org/codelutin/util/MD5OutputStream.java
Log:
Readd previous fast-MD5 implementation
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/MD5.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/MD5.java 2009-04-28 17:28:47 UTC (rev 1450)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/MD5.java 2009-04-29 12:30:18 UTC (rev 1451)
@@ -1,735 +1,826 @@
package org.codelutin.util;
-/*
- * written Santeri Paavolainen, Helsinki Finland 1996
- * (c) Santeri Paavolainen, Helsinki Finland 1996
- * modifications Copyright (C) 2002-2007 Stephen Ostermiller
- * http://ostermiller.org/contact.pl?regarding=Java+Utilities
- * Copyright (C) 2007 Stu Thompson stu.comp -at- mailworks.org
- *
- * This program 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.
- *
- * This program 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.
- *
- * See COPYING.TXT for details.
- *
- * The original work by Santeri Paavolainen can be found at
- * http://www.helsinki.fi/~sjpaavol/programs/md5/
- *
- * This Java class has been derived from the RSA Data Security, Inc. MD5
- * Message-Digest Algorithm and its reference implementation.
- */
-
import java.io.*;
/**
- * MD5 hash generator.
- * More information about this class is available from <a target="_top" href=
- * "http://ostermiller.org/utils/MD5.html">ostermiller.org</a>.
+ * Fast implementation of RSA's MD5 hash generator in Java JDK Beta-2 or higher.
* <p>
- * This class takes as input a message of arbitrary length and produces
- * as output a 128-bit "fingerprint" or "message digest" of the input.
- * It is conjectured that it is computationally infeasible to produce
- * two messages having the same message digest, or to produce any
- * message having a given pre-specified target message digest. The MD5
- * algorithm is intended for digital signature applications, where a
- * large file must be "compressed" in a secure manner before being
- * encrypted with a private (secret) key under a public-key cryptosystem
- * such as RSA.
+ * Originally written by Santeri Paavolainen, Helsinki Finland 1996.<br>
+ * (c) Santeri Paavolainen, Helsinki Finland 1996<br>
+ * Many changes Copyright (c) 2002 - 2008 Timothy W Macinta<br>
* <p>
- * For more information see RFC1321.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * <p>
+ * This library 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
+ * Library General Public License for more details.
+ * <p>
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * <p>
+ * See http://www.twmacinta.com/myjava/fast_md5.php for more information
+ * on this file and the related files.
+ * <p>
+ * This was originally a rather straight re-implementation of the
+ * reference implementation given in RFC1321 by RSA. It passes the MD5
+ * test suite as defined in RFC1321.
+ * <p>
+ * Many optimizations made by Timothy W Macinta. Reduced time to checksum a
+ * test file in Java alone to roughly half the time taken compared with
+ * java.security.MessageDigest (within an intepretter). Also added an
+ * optional native method to reduce the time even further.
+ * See http://www.twmacinta.com/myjava/fast_md5.php for further information
+ * on the time improvements achieved.
+ * <p>
+ * Some bug fixes also made by Timothy W Macinta.
+ * <p>
+ * Please note: I (Timothy Macinta) have put this code in the
+ * com.twmacinta.util package only because it came without a package. I
+ * was not the the original author of the code, although I did
+ * optimize it (substantially) and fix some bugs.
+ * <p>
+ * This Java class has been derived from the RSA Data Security, Inc. MD5
+ * Message-Digest Algorithm and its reference implementation.
+ * <p>
+ * This class will attempt to use a native method to quickly compute
+ * checksums when the appropriate native library is available. On Linux,
+ * this library should be named "MD5.so" and on Windows it should be
+ * named "MD5.dll". The code will attempt to locate the library in the
+ * following locations in the order given:
*
- * @see MD5OutputStream
- * @see MD5InputStream
+ * <ol>
+ * <li>The path specified by the system property
+ * "com.twmacinta.util.MD5.NATIVE_LIB_FILE"
+ * (be sure to include "MD5.so" or "MD5.dll"
+ * as appropriate at the end of the path).
+ * <li>A platform specific directory beneath the "lib/arch/" directory.
+ * On Linux for x86, this is "lib/arch/linux_x86/". On Windows for
+ * x86, this is "lib/arch/win32_x86/".
+ * <li>Within the "lib/" directory.
+ * <li>Within the current directory.
+ * </ol>
*
- * @author Santeri Paavolainen http://www.helsinki.fi/~sjpaavol/programs/md5/
- * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
- * @since ostermillerutils 1.00.00
+ * <p>
+ * If the library is not found, the code will fall back to the default
+ * (slower) Java code.
+ * <p>
+ * As a side effect of having the code search for the native library,
+ * SecurityExceptions might be thrown on JVMs that have a restrictive
+ * SecurityManager. The initialization code attempts to silently discard
+ * these exceptions and continue, but many SecurityManagers will
+ * attempt to notify the user directly of all SecurityExceptions thrown.
+ * Consequently, the code has provisions for skipping the search for
+ * the native library. Any of these provisions may be used to skip the
+ * search as long as they are performed <i>before</i> the first
+ * instance of a com.twmacinta.util.MD5 object is constructed (note that
+ * the convenience stream objects will implicitly create an MD5 object).
+ * <p>
+ * The first option is to set the system property
+ * "com.twmacinta.util.MD5.NO_NATIVE_LIB" to "true" or "1".
+ * Unfortunately, SecurityManagers may also choose to disallow system
+ * property setting, so this won't be of use in all cases.
+ * <p>
+ * The second option is to call
+ * com.twmacinta.util.MD5.initNativeLibrary(true) before any MD5 objects
+ * are constructed.
+ *
+ * @author Santeri Paavolainen <sjpaavol(a)cc.helsinki.fi>
+ * @author Timothy W Macinta (twm(a)alum.mit.edu) (optimizations and bug fixes)
*/
+
public class MD5 {
-
+
/**
- * Class constructor
- *
- * @since ostermillerutils 1.00.00
- */
- public MD5 () {
- reset();
- }
-
+ * MD5 state
+ **/
+ MD5State state;
+
/**
- * Command line program that will take files as arguments
- * and output the MD5 sum for each file.
- *
- * @param args command line arguments
- *
- * @since ostermillerutils 1.00.00
- */
- public static void main (String[] args){
- if (args.length == 0){
- System.err.println("Please specify a file.");
- } else {
- for (String element: args) {
- try {
- System.out.println(MD5.getHashString(new File(element)) + " " + element);
- } catch (IOException x){
- System.err.println(x.getMessage());
- }
- }
- }
- }
-
+ * If Final() has been called, finals is set to the current finals
+ * state. Any Update() causes this to be set to null.
+ **/
+ MD5State finals;
+
+ /**
+ * Padding for Final()
+ **/
+ static byte padding[] = {
+ (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ private static boolean native_lib_loaded = false;
+ private static boolean native_lib_init_pending = true;
+
/**
- * Gets this hash sum as an array of 16 bytes.
- *
- * @return Array of 16 bytes, the hash of all updated bytes.
- *
- * @since ostermillerutils 1.00.00
- */
- public byte[] getHash() {
- if (!finalState.valid) {
- finalState.copy(workingState);
- long bitCount = finalState.bitCount;
- // Compute the number of left over bits
- int leftOver = (int) (((bitCount >>> 3)) & 0x3f);
- // Compute the amount of padding to add based on number of left over bits.
- int padlen = (leftOver < 56) ? (56 - leftOver) : (120 - leftOver);
- // add the padding
- update(finalState, padding, 0, padlen);
- // add the length (computed before padding was added)
- update(finalState, encode(bitCount), 0, 8);
- finalState.valid = true;
- }
- // make a copy of the hash before returning it.
- return encode(finalState.state, 16);
+ * Initialize MD5 internal state (object can be reused just by
+ * calling Init() after every Final()
+ **/
+ public synchronized void Init () {
+ state = new MD5State();
+ finals = null;
}
-
+
/**
- * Returns 32-character hex representation of this hash.
- *
- * @return String representation of this object's hash.
- *
- * @since ostermillerutils 1.00.00
- */
- public String getHashString(){
- return toHex(this.getHash());
+ * Class constructor
+ **/
+ public MD5 () {
+ if (native_lib_init_pending) _initNativeLibrary();
+ this.Init();
}
-
+
/**
- * Gets the MD5 hash of the given byte array.
+ * Initialize class, and update hash with ob.toString()
*
- * @param b byte array for which an MD5 hash is desired.
- * @return Array of 16 bytes, the hash of all updated bytes.
- *
- * @since ostermillerutils 1.00.00
- */
- public static byte[] getHash(byte[] b){
- MD5 md5 = new MD5();
- md5.update(b);
- return md5.getHash();
+ * @param ob Object, ob.toString() is used to update hash
+ * after initialization
+ **/
+ public MD5 (Object ob) {
+ this();
+ Update(ob.toString());
}
-
- /**
- * Gets the MD5 hash of the given byte array.
- *
- * @param b byte array for which an MD5 hash is desired.
- * @return 32-character hex representation the data's MD5 hash.
- *
- * @since ostermillerutils 1.00.00
- */
- public static String getHashString(byte[] b){
- MD5 md5 = new MD5();
- md5.update(b);
- return md5.getHashString();
+
+ private void Decode (byte buffer[], int shift, int[] out) {
+ /*len += shift;
+ for (int i = 0; shift < len; i++, shift += 4) {
+ out[i] = ((int) (buffer[shift] & 0xff)) |
+ (((int) (buffer[shift + 1] & 0xff)) << 8) |
+ (((int) (buffer[shift + 2] & 0xff)) << 16) |
+ (((int) buffer[shift + 3]) << 24);
+ }*/
+
+ // unrolled loop (original loop shown above)
+
+ out[0] = ((int) (buffer[shift] & 0xff)) |
+ (((int) (buffer[shift + 1] & 0xff)) << 8) |
+ (((int) (buffer[shift + 2] & 0xff)) << 16) |
+ (((int) buffer[shift + 3]) << 24);
+ out[1] = ((int) (buffer[shift + 4] & 0xff)) |
+ (((int) (buffer[shift + 5] & 0xff)) << 8) |
+ (((int) (buffer[shift + 6] & 0xff)) << 16) |
+ (((int) buffer[shift + 7]) << 24);
+ out[2] = ((int) (buffer[shift + 8] & 0xff)) |
+ (((int) (buffer[shift + 9] & 0xff)) << 8) |
+ (((int) (buffer[shift + 10] & 0xff)) << 16) |
+ (((int) buffer[shift + 11]) << 24);
+ out[3] = ((int) (buffer[shift + 12] & 0xff)) |
+ (((int) (buffer[shift + 13] & 0xff)) << 8) |
+ (((int) (buffer[shift + 14] & 0xff)) << 16) |
+ (((int) buffer[shift + 15]) << 24);
+ out[4] = ((int) (buffer[shift + 16] & 0xff)) |
+ (((int) (buffer[shift + 17] & 0xff)) << 8) |
+ (((int) (buffer[shift + 18] & 0xff)) << 16) |
+ (((int) buffer[shift + 19]) << 24);
+ out[5] = ((int) (buffer[shift + 20] & 0xff)) |
+ (((int) (buffer[shift + 21] & 0xff)) << 8) |
+ (((int) (buffer[shift + 22] & 0xff)) << 16) |
+ (((int) buffer[shift + 23]) << 24);
+ out[6] = ((int) (buffer[shift + 24] & 0xff)) |
+ (((int) (buffer[shift + 25] & 0xff)) << 8) |
+ (((int) (buffer[shift + 26] & 0xff)) << 16) |
+ (((int) buffer[shift + 27]) << 24);
+ out[7] = ((int) (buffer[shift + 28] & 0xff)) |
+ (((int) (buffer[shift + 29] & 0xff)) << 8) |
+ (((int) (buffer[shift + 30] & 0xff)) << 16) |
+ (((int) buffer[shift + 31]) << 24);
+ out[8] = ((int) (buffer[shift + 32] & 0xff)) |
+ (((int) (buffer[shift + 33] & 0xff)) << 8) |
+ (((int) (buffer[shift + 34] & 0xff)) << 16) |
+ (((int) buffer[shift + 35]) << 24);
+ out[9] = ((int) (buffer[shift + 36] & 0xff)) |
+ (((int) (buffer[shift + 37] & 0xff)) << 8) |
+ (((int) (buffer[shift + 38] & 0xff)) << 16) |
+ (((int) buffer[shift + 39]) << 24);
+ out[10] = ((int) (buffer[shift + 40] & 0xff)) |
+ (((int) (buffer[shift + 41] & 0xff)) << 8) |
+ (((int) (buffer[shift + 42] & 0xff)) << 16) |
+ (((int) buffer[shift + 43]) << 24);
+ out[11] = ((int) (buffer[shift + 44] & 0xff)) |
+ (((int) (buffer[shift + 45] & 0xff)) << 8) |
+ (((int) (buffer[shift + 46] & 0xff)) << 16) |
+ (((int) buffer[shift + 47]) << 24);
+ out[12] = ((int) (buffer[shift + 48] & 0xff)) |
+ (((int) (buffer[shift + 49] & 0xff)) << 8) |
+ (((int) (buffer[shift + 50] & 0xff)) << 16) |
+ (((int) buffer[shift + 51]) << 24);
+ out[13] = ((int) (buffer[shift + 52] & 0xff)) |
+ (((int) (buffer[shift + 53] & 0xff)) << 8) |
+ (((int) (buffer[shift + 54] & 0xff)) << 16) |
+ (((int) buffer[shift + 55]) << 24);
+ out[14] = ((int) (buffer[shift + 56] & 0xff)) |
+ (((int) (buffer[shift + 57] & 0xff)) << 8) |
+ (((int) (buffer[shift + 58] & 0xff)) << 16) |
+ (((int) buffer[shift + 59]) << 24);
+ out[15] = ((int) (buffer[shift + 60] & 0xff)) |
+ (((int) (buffer[shift + 61] & 0xff)) << 8) |
+ (((int) (buffer[shift + 62] & 0xff)) << 16) |
+ (((int) buffer[shift + 63]) << 24);
}
-
- /**
- * Gets the MD5 hash the data on the given InputStream.
- *
- * @param in byte array for which an MD5 hash is desired.
- * @return Array of 16 bytes, the hash of all updated bytes.
- * @throws IOException if an I/O error occurs.
- *
- * @since ostermillerutils 1.00.00
- */
- public static byte[] getHash(InputStream in) throws IOException {
- MD5 md5 = new MD5();
- byte[] buffer = new byte[1024];
- int read;
- while ((read = in.read(buffer)) != -1){
- md5.update(buffer, read);
- }
- return md5.getHash();
+
+ private native void Transform_native (int[] state, byte buffer[], int shift, int length);
+
+ private void Transform (MD5State state, byte buffer[], int shift, int[] decode_buf) {
+ int
+ a = state.state[0],
+ b = state.state[1],
+ c = state.state[2],
+ d = state.state[3],
+ x[] = decode_buf;
+
+ Decode(buffer, shift, decode_buf);
+
+ /* Round 1 */
+ a += ((b & c) | (~b & d)) + x[ 0] + 0xd76aa478; /* 1 */
+ a = ((a << 7) | (a >>> 25)) + b;
+ d += ((a & b) | (~a & c)) + x[ 1] + 0xe8c7b756; /* 2 */
+ d = ((d << 12) | (d >>> 20)) + a;
+ c += ((d & a) | (~d & b)) + x[ 2] + 0x242070db; /* 3 */
+ c = ((c << 17) | (c >>> 15)) + d;
+ b += ((c & d) | (~c & a)) + x[ 3] + 0xc1bdceee; /* 4 */
+ b = ((b << 22) | (b >>> 10)) + c;
+
+ a += ((b & c) | (~b & d)) + x[ 4] + 0xf57c0faf; /* 5 */
+ a = ((a << 7) | (a >>> 25)) + b;
+ d += ((a & b) | (~a & c)) + x[ 5] + 0x4787c62a; /* 6 */
+ d = ((d << 12) | (d >>> 20)) + a;
+ c += ((d & a) | (~d & b)) + x[ 6] + 0xa8304613; /* 7 */
+ c = ((c << 17) | (c >>> 15)) + d;
+ b += ((c & d) | (~c & a)) + x[ 7] + 0xfd469501; /* 8 */
+ b = ((b << 22) | (b >>> 10)) + c;
+
+ a += ((b & c) | (~b & d)) + x[ 8] + 0x698098d8; /* 9 */
+ a = ((a << 7) | (a >>> 25)) + b;
+ d += ((a & b) | (~a & c)) + x[ 9] + 0x8b44f7af; /* 10 */
+ d = ((d << 12) | (d >>> 20)) + a;
+ c += ((d & a) | (~d & b)) + x[10] + 0xffff5bb1; /* 11 */
+ c = ((c << 17) | (c >>> 15)) + d;
+ b += ((c & d) | (~c & a)) + x[11] + 0x895cd7be; /* 12 */
+ b = ((b << 22) | (b >>> 10)) + c;
+
+ a += ((b & c) | (~b & d)) + x[12] + 0x6b901122; /* 13 */
+ a = ((a << 7) | (a >>> 25)) + b;
+ d += ((a & b) | (~a & c)) + x[13] + 0xfd987193; /* 14 */
+ d = ((d << 12) | (d >>> 20)) + a;
+ c += ((d & a) | (~d & b)) + x[14] + 0xa679438e; /* 15 */
+ c = ((c << 17) | (c >>> 15)) + d;
+ b += ((c & d) | (~c & a)) + x[15] + 0x49b40821; /* 16 */
+ b = ((b << 22) | (b >>> 10)) + c;
+
+
+ /* Round 2 */
+ a += ((b & d) | (c & ~d)) + x[ 1] + 0xf61e2562; /* 17 */
+ a = ((a << 5) | (a >>> 27)) + b;
+ d += ((a & c) | (b & ~c)) + x[ 6] + 0xc040b340; /* 18 */
+ d = ((d << 9) | (d >>> 23)) + a;
+ c += ((d & b) | (a & ~b)) + x[11] + 0x265e5a51; /* 19 */
+ c = ((c << 14) | (c >>> 18)) + d;
+ b += ((c & a) | (d & ~a)) + x[ 0] + 0xe9b6c7aa; /* 20 */
+ b = ((b << 20) | (b >>> 12)) + c;
+
+ a += ((b & d) | (c & ~d)) + x[ 5] + 0xd62f105d; /* 21 */
+ a = ((a << 5) | (a >>> 27)) + b;
+ d += ((a & c) | (b & ~c)) + x[10] + 0x02441453; /* 22 */
+ d = ((d << 9) | (d >>> 23)) + a;
+ c += ((d & b) | (a & ~b)) + x[15] + 0xd8a1e681; /* 23 */
+ c = ((c << 14) | (c >>> 18)) + d;
+ b += ((c & a) | (d & ~a)) + x[ 4] + 0xe7d3fbc8; /* 24 */
+ b = ((b << 20) | (b >>> 12)) + c;
+
+ a += ((b & d) | (c & ~d)) + x[ 9] + 0x21e1cde6; /* 25 */
+ a = ((a << 5) | (a >>> 27)) + b;
+ d += ((a & c) | (b & ~c)) + x[14] + 0xc33707d6; /* 26 */
+ d = ((d << 9) | (d >>> 23)) + a;
+ c += ((d & b) | (a & ~b)) + x[ 3] + 0xf4d50d87; /* 27 */
+ c = ((c << 14) | (c >>> 18)) + d;
+ b += ((c & a) | (d & ~a)) + x[ 8] + 0x455a14ed; /* 28 */
+ b = ((b << 20) | (b >>> 12)) + c;
+
+ a += ((b & d) | (c & ~d)) + x[13] + 0xa9e3e905; /* 29 */
+ a = ((a << 5) | (a >>> 27)) + b;
+ d += ((a & c) | (b & ~c)) + x[ 2] + 0xfcefa3f8; /* 30 */
+ d = ((d << 9) | (d >>> 23)) + a;
+ c += ((d & b) | (a & ~b)) + x[ 7] + 0x676f02d9; /* 31 */
+ c = ((c << 14) | (c >>> 18)) + d;
+ b += ((c & a) | (d & ~a)) + x[12] + 0x8d2a4c8a; /* 32 */
+ b = ((b << 20) | (b >>> 12)) + c;
+
+
+ /* Round 3 */
+ a += (b ^ c ^ d) + x[ 5] + 0xfffa3942; /* 33 */
+ a = ((a << 4) | (a >>> 28)) + b;
+ d += (a ^ b ^ c) + x[ 8] + 0x8771f681; /* 34 */
+ d = ((d << 11) | (d >>> 21)) + a;
+ c += (d ^ a ^ b) + x[11] + 0x6d9d6122; /* 35 */
+ c = ((c << 16) | (c >>> 16)) + d;
+ b += (c ^ d ^ a) + x[14] + 0xfde5380c; /* 36 */
+ b = ((b << 23) | (b >>> 9)) + c;
+
+ a += (b ^ c ^ d) + x[ 1] + 0xa4beea44; /* 37 */
+ a = ((a << 4) | (a >>> 28)) + b;
+ d += (a ^ b ^ c) + x[ 4] + 0x4bdecfa9; /* 38 */
+ d = ((d << 11) | (d >>> 21)) + a;
+ c += (d ^ a ^ b) + x[ 7] + 0xf6bb4b60; /* 39 */
+ c = ((c << 16) | (c >>> 16)) + d;
+ b += (c ^ d ^ a) + x[10] + 0xbebfbc70; /* 40 */
+ b = ((b << 23) | (b >>> 9)) + c;
+
+ a += (b ^ c ^ d) + x[13] + 0x289b7ec6; /* 41 */
+ a = ((a << 4) | (a >>> 28)) + b;
+ d += (a ^ b ^ c) + x[ 0] + 0xeaa127fa; /* 42 */
+ d = ((d << 11) | (d >>> 21)) + a;
+ c += (d ^ a ^ b) + x[ 3] + 0xd4ef3085; /* 43 */
+ c = ((c << 16) | (c >>> 16)) + d;
+ b += (c ^ d ^ a) + x[ 6] + 0x04881d05; /* 44 */
+ b = ((b << 23) | (b >>> 9)) + c;
+
+ a += (b ^ c ^ d) + x[ 9] + 0xd9d4d039; /* 33 */
+ a = ((a << 4) | (a >>> 28)) + b;
+ d += (a ^ b ^ c) + x[12] + 0xe6db99e5; /* 34 */
+ d = ((d << 11) | (d >>> 21)) + a;
+ c += (d ^ a ^ b) + x[15] + 0x1fa27cf8; /* 35 */
+ c = ((c << 16) | (c >>> 16)) + d;
+ b += (c ^ d ^ a) + x[ 2] + 0xc4ac5665; /* 36 */
+ b = ((b << 23) | (b >>> 9)) + c;
+
+
+ /* Round 4 */
+ a += (c ^ (b | ~d)) + x[ 0] + 0xf4292244; /* 49 */
+ a = ((a << 6) | (a >>> 26)) + b;
+ d += (b ^ (a | ~c)) + x[ 7] + 0x432aff97; /* 50 */
+ d = ((d << 10) | (d >>> 22)) + a;
+ c += (a ^ (d | ~b)) + x[14] + 0xab9423a7; /* 51 */
+ c = ((c << 15) | (c >>> 17)) + d;
+ b += (d ^ (c | ~a)) + x[ 5] + 0xfc93a039; /* 52 */
+ b = ((b << 21) | (b >>> 11)) + c;
+
+ a += (c ^ (b | ~d)) + x[12] + 0x655b59c3; /* 53 */
+ a = ((a << 6) | (a >>> 26)) + b;
+ d += (b ^ (a | ~c)) + x[ 3] + 0x8f0ccc92; /* 54 */
+ d = ((d << 10) | (d >>> 22)) + a;
+ c += (a ^ (d | ~b)) + x[10] + 0xffeff47d; /* 55 */
+ c = ((c << 15) | (c >>> 17)) + d;
+ b += (d ^ (c | ~a)) + x[ 1] + 0x85845dd1; /* 56 */
+ b = ((b << 21) | (b >>> 11)) + c;
+
+ a += (c ^ (b | ~d)) + x[ 8] + 0x6fa87e4f; /* 57 */
+ a = ((a << 6) | (a >>> 26)) + b;
+ d += (b ^ (a | ~c)) + x[15] + 0xfe2ce6e0; /* 58 */
+ d = ((d << 10) | (d >>> 22)) + a;
+ c += (a ^ (d | ~b)) + x[ 6] + 0xa3014314; /* 59 */
+ c = ((c << 15) | (c >>> 17)) + d;
+ b += (d ^ (c | ~a)) + x[13] + 0x4e0811a1; /* 60 */
+ b = ((b << 21) | (b >>> 11)) + c;
+
+ a += (c ^ (b | ~d)) + x[ 4] + 0xf7537e82; /* 61 */
+ a = ((a << 6) | (a >>> 26)) + b;
+ d += (b ^ (a | ~c)) + x[11] + 0xbd3af235; /* 62 */
+ d = ((d << 10) | (d >>> 22)) + a;
+ c += (a ^ (d | ~b)) + x[ 2] + 0x2ad7d2bb; /* 63 */
+ c = ((c << 15) | (c >>> 17)) + d;
+ b += (d ^ (c | ~a)) + x[ 9] + 0xeb86d391; /* 64 */
+ b = ((b << 21) | (b >>> 11)) + c;
+
+ state.state[0] += a;
+ state.state[1] += b;
+ state.state[2] += c;
+ state.state[3] += d;
}
-
+
/**
- * Gets the MD5 hash the data on the given InputStream.
+ * Updates hash with the bytebuffer given (using at maximum length bytes from
+ * that buffer)
*
- * @param in byte array for which an MD5 hash is desired.
- * @return 32-character hex representation the data's MD5 hash.
- * @throws IOException if an I/O error occurs.
- *
- * @since ostermillerutils 1.00.00
+ * @param stat Which state is updated
+ * @param buffer Array of bytes to be hashed
+ * @param offset Offset to buffer array
+ * @param length Use at maximum `length' bytes (absolute
+ * maximum is buffer.length)
*/
- public static String getHashString(InputStream in) throws IOException {
- MD5 md5 = new MD5();
- byte[] buffer = new byte[1024];
- int read;
- while ((read = in.read(buffer)) != -1){
- md5.update(buffer, read);
- }
- return md5.getHashString();
- }
-
- /**
- * Gets the MD5 hash of the given file.
- *
- * @param f file for which an MD5 hash is desired.
- * @return Array of 16 bytes, the hash of all updated bytes.
- * @throws IOException if an I/O error occurs.
- *
- * @since ostermillerutils 1.00.00
- */
- public static byte[] getHash(File f) throws IOException {
- InputStream is = new FileInputStream(f);
- byte[] hash = getHash(is);
- is.close();
- return hash;
- }
-
- /**
- * Gets the MD5 hash of the given file.
- *
- * @param f file array for which an MD5 hash is desired.
- * @return 32-character hex representation the data's MD5 hash.
- * @throws IOException if an I/O error occurs.
- *
- * @since ostermillerutils 1.00.00
- */
- public static String getHashString(File f) throws IOException {
- InputStream is = new FileInputStream(f);
- String hash = getHashString(is);
- is.close();
- return hash;
- }
-
- /**
- * Gets the MD5 hash of the given String.
- * The string is converted to bytes using the current
- * platform's default character encoding.
- *
- * @param s String for which an MD5 hash is desired.
- * @return Array of 16 bytes, the hash of all updated bytes.
- *
- * @since ostermillerutils 1.00.00
- */
- public static byte[] getHash(String s){
- MD5 md5 = new MD5();
- md5.update(s);
- return md5.getHash();
- }
-
- /**
- * Gets the MD5 hash of the given String.
- * The string is converted to bytes using the current
- * platform's default character encoding.
- *
- * @param s String for which an MD5 hash is desired.
- * @return 32-character hex representation the data's MD5 hash.
- *
- * @since ostermillerutils 1.00.00
- */
- public static String getHashString(String s){
- MD5 md5 = new MD5();
- md5.update(s);
- return md5.getHashString();
- }
-
-
- /**
- * Gets the MD5 hash of the given String.
- *
- * @param s String for which an MD5 hash is desired.
- * @param enc The name of a supported character encoding.
- * @return Array of 16 bytes, the hash of all updated bytes.
- * @throws UnsupportedEncodingException If the named encoding is not supported.
- *
- * @since ostermillerutils 1.00.00
- */
- public static byte[] getHash(String s, String enc) throws UnsupportedEncodingException {
- MD5 md5 = new MD5();
- md5.update(s, enc);
- return md5.getHash();
- }
-
- /**
- * Gets the MD5 hash of the given String.
- *
- * @param s String for which an MD5 hash is desired.
- * @param enc The name of a supported character encoding.
- * @return 32-character hex representation the data's MD5 hash.
- * @throws UnsupportedEncodingException If the named encoding is not supported.
- *
- * @since ostermillerutils 1.00.00
- */
- public static String getHashString(String s, String enc) throws UnsupportedEncodingException {
- MD5 md5 = new MD5();
- md5.update(s, enc);
- return md5.getHashString();
- }
-
-
- /**
- * Reset the MD5 sum to its initial state.
- *
- * @since ostermillerutils 1.00.00
- */
- public void reset() {
- workingState.reset();
- finalState.valid = false;
- }
-
- /**
- * Returns 32-character hex representation of this hash.
- *
- * @return String representation of this object's hash.
- *
- * @since ostermillerutils 1.00.00
- */
- @Override public String toString(){
- return getHashString();
- }
-
- /**
- * Update this hash with the given data.
- * <p>
- * A state may be passed into this method so that we can add padding
- * and finalize a md5 hash without limiting our ability to update
- * more data later.
- * <p>
- * If length bytes are not available to be hashed, as many bytes as
- * possible will be hashed.
- *
- * @param state Which state is updated.
- * @param buffer Array of bytes to be hashed.
- * @param offset Offset to buffer array.
- * @param length number of bytes to hash.
- *
- * @since ostermillerutils 1.00.00
- */
- private void update (MD5State state, byte buffer[], int offset, int length) {
-
- finalState.valid = false;
-
- // if length goes beyond the end of the buffer, cut it short.
- if ((length + offset) > buffer.length){
+ public void Update (MD5State stat, byte buffer[], int offset, int length) {
+ int index, partlen, i, start;
+ finals = null;
+
+ /* Length can be told to be shorter, but not inter */
+ if ((length - offset)> buffer.length)
length = buffer.length - offset;
- }
-
- // compute number of bytes mod 64
- // this is what we have sitting in a buffer
- // that have not been hashed yet
- int index = (int) (state.bitCount >>> 3) & 0x3f;
-
- // add the length to the count (translate bytes to bits)
- state.bitCount += length << 3;
-
- int partlen = 64 - index;
-
- int i = 0;
+
+ /* compute number of bytes mod 64 */
+
+ index = (int) (stat.count & 0x3f);
+ stat.count += length;
+
+ partlen = 64 - index;
+
if (length >= partlen) {
- System.arraycopy(buffer, offset, state.buffer, index, partlen);
- transform(state, decode(state.buffer, 64, 0));
- for (i = partlen; (i + 63) < length; i+= 64){
- transform(state, decode(buffer, 64, i));
+
+ // update state (using native method) to reflect input
+
+ if (native_lib_loaded) {
+ if (partlen == 64) {
+ partlen = 0;
+ } else {
+ for (i = 0; i < partlen; i++)
+ stat.buffer[i + index] = buffer[i + offset];
+ Transform_native(stat.state, stat.buffer, 0, 64);
+ }
+ i = partlen + ((length - partlen) / 64) * 64;
+
+ // break into chunks to guard against stack overflow in JNI
+
+ int transformLength = length - partlen;
+ int transformOffset = partlen + offset;
+ final int MAX_LENGTH = 65536; // prevent stack overflow in JNI
+ while (true) {
+ if (transformLength > MAX_LENGTH) {
+ Transform_native(stat.state, buffer, transformOffset, MAX_LENGTH);
+ transformLength -= MAX_LENGTH;
+ transformOffset += MAX_LENGTH;
+ } else {
+ Transform_native(stat.state, buffer, transformOffset, transformLength);
+ break;
+ }
+ }
}
+
+ // update state (using only Java) to reflect input
+
+ else {
+ int[] decode_buf = new int[16];
+ if (partlen == 64) {
+ partlen = 0;
+ } else {
+ for (i = 0; i < partlen; i++)
+ stat.buffer[i + index] = buffer[i + offset];
+ Transform(stat, stat.buffer, 0, decode_buf);
+ }
+ for (i = partlen; (i + 63) < length; i+= 64) {
+ Transform(stat, buffer, i + offset, decode_buf);
+ }
+ }
index = 0;
+ } else {
+ i = 0;
}
-
- // buffer remaining input
+
+ /* buffer remaining input */
if (i < length) {
- for (int start = i; i < length; i++) {
- state.buffer[index + i - start] = buffer[i + offset];
+ start = i;
+ for (; i < length; i++) {
+ stat.buffer[index + i - start] = buffer[i + offset];
}
}
}
-
- /**
- * Update this hash with the given data.
- * <p>
- * If length bytes are not available to be hashed, as many bytes as
- * possible will be hashed.
- *
- * @param buffer Array of bytes to be hashed.
- * @param offset Offset to buffer array.
- * @param length number of bytes to hash.
- *
- * @since ostermillerutils 1.00.00
+
+ /*
+ * Update()s for other datatypes than byte[] also. Update(byte[], int)
+ * is only the main driver.
*/
- public void update (byte buffer[], int offset, int length) {
- update(workingState, buffer, offset, length);
- }
-
+
/**
- * Update this hash with the given data.
- * <p>
- * If length bytes are not available to be hashed, as many bytes as
- * possible will be hashed.
- *
- * @param buffer Array of bytes to be hashed.
- * @param length number of bytes to hash.
- *
- * @since ostermillerutils 1.00.00
- */
- public void update (byte buffer[], int length) {
- update(buffer, 0, length);
+ * Plain update, updates this object
+ **/
+ public void Update (byte buffer[], int offset, int length) {
+ Update(this.state, buffer, offset, length);
}
-
+
+ public void Update (byte buffer[], int length) {
+ Update(this.state, buffer, 0, length);
+ }
+
/**
- * Update this hash with the given data.
+ * Updates hash with given array of bytes
*
- * @param buffer Array of bytes to be hashed.
- *
- * @since ostermillerutils 1.00.00
- */
- public void update (byte buffer[]) {
- update(buffer, 0, buffer.length);
+ * @param buffer Array of bytes to use for updating the hash
+ **/
+ public void Update (byte buffer[]) {
+ Update(buffer, 0, buffer.length);
}
-
+
/**
- * Updates this hash with a single byte.
+ * Updates hash with a single byte
*
- * @param b byte to be hashed.
- *
- * @since ostermillerutils 1.00.00
- */
- public void update (byte b) {
+ * @param b Single byte to update the hash
+ **/
+ public void Update (byte b) {
byte buffer[] = new byte[1];
buffer[0] = b;
- update(buffer, 1);
+
+ Update(buffer, 1);
}
-
+
/**
- * Update this hash with a String.
- * The string is converted to bytes using the current
- * platform's default character encoding.
+ * Update buffer with given string. Note that because the version of
+ * the s.getBytes() method without parameters is used to convert the
+ * string to a byte array, the results of this method may be different
+ * on different platforms. The s.getBytes() method converts the string
+ * into a byte array using the current platform's default character set
+ * and may therefore have different results on platforms with different
+ * default character sets. If a version that works consistently
+ * across platforms with different default character sets is desired,
+ * use the overloaded version of the Update() method which takes a
+ * string and a character encoding.
*
- * @param s String to be hashed.
- *
- * @since ostermillerutils 1.00.00
- */
- public void update (String s) {
- update(s.getBytes());
+ * @param s String to be update to hash (is used as s.getBytes())
+ **/
+ public void Update (String s) {
+ byte chars[] = s.getBytes();
+ Update(chars, chars.length);
}
-
+
/**
- * Update this hash with a String.
+ * Update buffer with given string using the given encoding. If the
+ * given encoding is null, the encoding "ISO8859_1" is used.
*
- * @param s String to be hashed.
- * @param enc The name of a supported character encoding.
- * @throws UnsupportedEncodingException If the named encoding is not supported.
- *
- * @since ostermillerutils 1.00.00
- */
- public void update (String s, String enc) throws UnsupportedEncodingException {
- update(s.getBytes(enc));
+ * @param s String to be update to hash (is used as
+ * s.getBytes(charset_name))
+ * @param charset_name The character set to use to convert s to a
+ * byte array, or null if the "ISO8859_1"
+ * character set is desired.
+ * @exception java.io.UnsupportedEncodingException If the named
+ * charset is not supported.
+ **/
+ public void Update (String s, String charset_name) throws java.io.UnsupportedEncodingException {
+ if (charset_name == null) charset_name = "ISO8859_1";
+ byte chars[] = s.getBytes(charset_name);
+ Update(chars, chars.length);
}
-
+
/**
- * The current state from which the hash sum
- * can be computed or updated.
+ * Update buffer with a single integer (only & 0xff part is used,
+ * as a byte)
*
- * @since ostermillerutils 1.00.00
- */
- private MD5State workingState = new MD5State();
-
+ * @param i Integer value, which is then converted to byte as i & 0xff
+ **/
+ public void Update (int i) {
+ Update((byte) (i & 0xff));
+ }
+
+ private byte[] Encode (int input[], int len) {
+ int i, j;
+ byte out[];
+
+ out = new byte[len];
+
+ for (i = j = 0; j < len; i++, j += 4) {
+ out[j] = (byte) (input[i] & 0xff);
+ out[j + 1] = (byte) ((input[i] >>> 8) & 0xff);
+ out[j + 2] = (byte) ((input[i] >>> 16) & 0xff);
+ out[j + 3] = (byte) ((input[i] >>> 24) & 0xff);
+ }
+
+ return out;
+ }
+
/**
- * Cached copy of the final MD5 hash sum. This is created when
- * the hash is requested and it is invalidated when the hash
- * is updated.
+ * Returns array of bytes (16 bytes) representing hash as of the
+ * current state of this object. Note: getting a hash does not
+ * invalidate the hash object, it only creates a copy of the real
+ * state which is finalized.
*
- * @since ostermillerutils 1.00.00
- */
- private MD5State finalState = new MD5State();
-
+ * @return Array of 16 bytes, the hash of all updated bytes
+ **/
+ public synchronized byte[] Final () {
+ byte bits[];
+ int index, padlen;
+ MD5State fin;
+
+ if (finals == null) {
+ fin = new MD5State(state);
+
+ int[] count_ints = {(int) (fin.count << 3), (int) (fin.count >> 29)};
+ bits = Encode(count_ints, 8);
+
+ index = (int) (fin.count & 0x3f);
+ padlen = (index < 56) ? (56 - index) : (120 - index);
+
+ Update(fin, padding, 0, padlen);
+ Update(fin, bits, 0, 8);
+
+ /* Update() sets finals to null */
+ finals = fin;
+ }
+
+ return Encode(finals.state, 16);
+ }
+
+ private static final char[] HEX_CHARS = {'0', '1', '2', '3',
+ '4', '5', '6', '7',
+ '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f',};
+
/**
- * Temporary buffer cached here for performance reasons.
- *
- * @since ostermillerutils 1.00.00
+ * Turns array of bytes into string representing each byte as
+ * unsigned hex number.
+ *
+ * @param hash Array of bytes to convert to hex-string
+ * @return Generated hex string
*/
- private int[] decodeBuffer = new int[16];
-
- /**
- * 64 bytes of padding that can be added if the length
- * is not divisible by 64.
- *
- * @since ostermillerutils 1.00.00
- */
- private static final byte padding[] = {
- (byte) 0x80, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- };
-
- /**
- * Contains internal state of the MD5 class.
- * Passes MD5 test suite as defined in RFC1321.
- *
- * @since ostermillerutils 1.00.00
- */
- private class MD5State {
-
- /**
- * True if this state is valid.
- *
- * @since ostermillerutils 1.00.00
- */
- private boolean valid = true;
-
- /**
- * Reset to initial state.
- *
- * @since ostermillerutils 1.00.00
- */
- private void reset(){
- state[0] = 0x67452301;
- state[1] = 0xefcdab89;
- state[2] = 0x98badcfe;
- state[3] = 0x10325476;
-
- bitCount = 0;
+ public static String asHex (byte hash[]) {
+ char buf[] = new char[hash.length * 2];
+ for (int i = 0, x = 0; i < hash.length; i++) {
+ buf[x++] = HEX_CHARS[(hash[i] >>> 4) & 0xf];
+ buf[x++] = HEX_CHARS[hash[i] & 0xf];
}
-
- /**
- * 128-byte state
- *
- * @since ostermillerutils 1.00.00
- */
- private int state[] = new int[4];
-
- /**
- * 64-bit count of the number of bits that have been hashed.
- *
- * @since ostermillerutils 1.00.00
- */
- private long bitCount;
-
- /**
- * 64-byte buffer (512 bits) for storing to-be-hashed characters
- *
- * @since ostermillerutils 1.00.00
- */
- private byte buffer[] = new byte[64];
-
- private MD5State() {
- reset();
- }
-
- /**
- * Set this state to be exactly the same as some other.
- *
- * @param from state to copy from.
- *
- * @since ostermillerutils 1.00.00
- */
- private void copy(MD5State from) {
- System.arraycopy(from.buffer, 0, this.buffer, 0, this.buffer.length);
- System.arraycopy(from.state, 0, this.state, 0, this.state.length);
- this.valid = from.valid;
- this.bitCount = from.bitCount;
- }
+ return new String(buf);
}
-
-
+
/**
- * Turns array of bytes into string representing each byte as
- * a two digit unsigned hex number.
+ * Returns 32-character hex representation of this objects hash
*
- * @param hash Array of bytes to convert to hex-string
- * @return Generated hex string
- *
- * @since ostermillerutils 1.00.00
+ * @return String of this object's hash
*/
- private static String toHex(byte hash[]){
- StringBuffer buf = new StringBuffer(hash.length * 2);
- for (byte element: hash) {
- int intVal = element & 0xff;
- if (intVal < 0x10){
- // append a zero before a one digit hex
- // number to make it two digits.
- buf.append("0");
- }
- buf.append(Integer.toHexString(intVal));
+ public String asHex () {
+ return asHex(this.Final());
+ }
+
+ public static synchronized final void initNativeLibrary (boolean disallow_lib_loading) {
+ if (disallow_lib_loading) {
+ native_lib_init_pending = false;
+ } else {
+ _initNativeLibrary();
}
- return buf.toString();
}
-
- private static int FF (int a, int b, int c, int d, int x, int s, int ac) {
- a += ((b & c) | (~b & d));
- a += x;
- a += ac;
- //return rotateLeft(a, s) + b;
- a = (a << s) | (a >>> (32 - s));
- return a + b;
+
+ private static synchronized final void _initNativeLibrary () {
+ if (!native_lib_init_pending) return;
+ native_lib_loaded = _loadNativeLibrary();
+ native_lib_init_pending = false;
}
-
- private static int GG (int a, int b, int c, int d, int x, int s, int ac) {
- a += ((b & d) | (c & ~d));
- a += x;
- a += ac;
- //return rotateLeft(a, s) + b;
- a = (a << s) | (a >>> (32 - s));
- return a + b;
+
+ private static synchronized final boolean _loadNativeLibrary () {
+ try {
+
+ // don't try to load if the right property is set
+
+ String prop = System.getProperty("com.twmacinta.util.MD5.NO_NATIVE_LIB");
+ if (prop != null) {
+ prop = prop.trim();
+ if (prop.equalsIgnoreCase("true") || prop.equals("1")) return false;
+ }
+
+ // the library to load can be specified as a property
+
+ File f;
+ prop = System.getProperty("com.twmacinta.util.MD5.NATIVE_LIB_FILE");
+ if (prop != null) {
+ f = new File(prop);
+ if (f.canRead()) {
+ System.load(f.getAbsolutePath());
+ return true;
+ }
+ }
+
+ // determine the operating system and architecture
+
+ String os_name = System.getProperty("os.name");
+ String os_arch = System.getProperty("os.arch");
+ if (os_name == null || os_arch == null) return false;
+ os_name = os_name.toLowerCase();
+ os_arch = os_arch.toLowerCase();
+
+ // define settings which are OS arch architecture independent
+
+ File arch_lib_path = null;
+ String arch_libfile_suffix = null;
+
+ // fill in settings for Linux on x86
+
+ if (os_name.equals("linux") &&
+ (os_arch.equals("x86") ||
+ os_arch.equals("i386") ||
+ os_arch.equals("i486") ||
+ os_arch.equals("i586") ||
+ os_arch.equals("i686"))) {
+ arch_lib_path = new File(new File(new File("lib"), "arch"), "linux_x86");
+ arch_libfile_suffix = ".so";
+ }
+
+ // fill in settings for Windows on x86
+
+ else if (os_name.startsWith("windows ") &&
+ (os_arch.equals("x86") ||
+ os_arch.equals("i386") ||
+ os_arch.equals("i486") ||
+ os_arch.equals("i586") ||
+ os_arch.equals("i686"))) {
+ arch_lib_path = new File(new File(new File("lib"), "arch"), "win32_x86");
+ arch_libfile_suffix = ".dll";
+ }
+
+ // fill in settings for Mac OS X on PPC
+
+ else if (os_name.startsWith("mac os x") &&
+ (os_arch.equals("ppc"))) {
+ arch_lib_path = new File(new File(new File("lib"), "arch"), "darwin_ppc");
+ arch_libfile_suffix = ".jnilib";
+ }
+
+ // fill in settings for Mac OS X on x86
+
+ else if (os_name.startsWith("mac os x") &&
+ (os_arch.equals("x86") ||
+ os_arch.equals("i386") ||
+ os_arch.equals("i486") ||
+ os_arch.equals("i586") ||
+ os_arch.equals("i686"))) {
+ arch_lib_path = new File(new File(new File("lib"), "arch"), "darwin_x86");
+ arch_libfile_suffix = ".jnilib";
+ }
+
+ // default to .so files with no architecture specific subdirectory
+
+ else {
+ arch_libfile_suffix = ".so";
+ }
+
+ // build the required filename
+
+ String fname = "MD5" + arch_libfile_suffix;
+
+ // try the architecture specific directory
+
+ if (arch_lib_path != null) {
+ f = new File(arch_lib_path, fname);
+ if (f.canRead()) {
+ System.load(f.getAbsolutePath());
+ return true;
+ }
+ }
+
+ // try the "lib" subdirectory
+
+ f = new File(new File("lib"), fname);
+ if (f.canRead()) {
+ System.load(f.getAbsolutePath());
+ return true;
+ }
+
+ // try the working directory
+
+ f = new File(fname);
+ if (f.canRead()) {
+ System.load(f.getAbsolutePath());
+ return true;
+ }
+ }
+
+ // discard SecurityExceptions
+
+ catch (SecurityException e) {}
+
+ // unable to load
+
+ return false;
}
-
- private static int HH (int a, int b, int c, int d, int x, int s, int ac) {
- a += (b ^ c ^ d);
- a += x;
- a += ac;
- //return rotateLeft(a, s) + b;
- a = (a << s) | (a >>> (32 - s));
- return a + b;
- }
-
- private static int II (int a, int b, int c, int d, int x, int s, int ac) {
- a += (c ^ (b | ~d));
- a += x;
- a += ac;
- //return rotateLeft(a, s) + b;
- a = (a << s) | (a >>> (32 - s));
- return a + b;
- }
-
- private static byte[] encode(long l){
- byte[] out = new byte[8];
- out[0] = (byte) (l & 0xff);
- out[1] = (byte) ((l >>> 8) & 0xff);
- out[2] = (byte) ((l >>> 16) & 0xff);
- out[3] = (byte) ((l >>> 24) & 0xff);
- out[4] = (byte) ((l >>> 32) & 0xff);
- out[5] = (byte) ((l >>> 40) & 0xff);
- out[6] = (byte) ((l >>> 48) & 0xff);
- out[7] = (byte) ((l >>> 56) & 0xff);
- return out;
- }
-
- private static byte[] encode(int input[], int len){
- byte[] out = new byte[len];
- int i, j;
- for (i = j = 0; j < len; i++, j += 4) {
- out[j] = (byte) (input[i] & 0xff);
- out[j + 1] = (byte) ((input[i] >>> 8) & 0xff);
- out[j + 2] = (byte) ((input[i] >>> 16) & 0xff);
- out[j + 3] = (byte) ((input[i] >>> 24) & 0xff);
+
+ /**
+ * Calculates and returns the hash of the contents of the given file.
+ **/
+ public static byte[] getHash (File f) throws IOException {
+ if (!f.exists()) throw new FileNotFoundException(f.toString());
+ InputStream close_me = null;
+ try {
+ long buf_size = f.length();
+ if (buf_size < 512) buf_size = 512;
+ if (buf_size > 65536) buf_size = 65536;
+ byte[] buf = new byte[(int) buf_size];
+ MD5InputStream in = new MD5InputStream(new FileInputStream(f));
+ close_me = in;
+ while (in.read(buf) != -1);
+ in.close();
+ return in.hash();
+ } catch (IOException e) {
+ if (close_me != null) try { close_me.close(); } catch (Exception e2) {}
+ throw e;
}
- return out;
}
-
- private int[] decode(byte buffer[], int len, int offset){
- int i, j;
- for (i = j = 0; j < len; i++, j += 4) {
- decodeBuffer[i] = (
- (buffer[j + offset] & 0xff)) |
- (((buffer[j + 1 + offset] & 0xff)) << 8) |
- (((buffer[j + 2 + offset] & 0xff)) << 16) |
- (((buffer[j + 3 + offset] & 0xff)) << 24
- );
+
+ /**
+ * @return true iff the first 16 bytes of both hash1 and hash2 are
+ * equal; both hash1 and hash2 are null; or either hash
+ * array is less than 16 bytes in length and their lengths and
+ * all of their bytes are equal.
+ **/
+ public static boolean hashesEqual (byte[] hash1, byte[] hash2) {
+ if (hash1 == null) return hash2 == null;
+ if (hash2 == null) return false;
+ int targ = 16;
+ if (hash1.length < 16) {
+ if (hash2.length != hash1.length) return false;
+ targ = hash1.length;
+ } else if (hash2.length < 16) {
+ return false;
}
- return decodeBuffer;
+ for (int i = 0; i < targ; i++) {
+ if (hash1[i] != hash2[i]) return false;
+ }
+ return true;
}
-
- private static void transform(MD5State state, int[] x){
- int a = state.state[0];
- int b = state.state[1];
- int c = state.state[2];
- int d = state.state[3];
-
- /* Round 1 */
- a = FF (a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */
- d = FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
- c = FF (c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
- b = FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
- a = FF (a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
- d = FF (d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
- c = FF (c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
- b = FF (b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
- a = FF (a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
- d = FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
- c = FF (c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
- b = FF (b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
- a = FF (a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
- d = FF (d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
- c = FF (c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
- b = FF (b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
-
- /* Round 2 */
- a = GG (a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */
- d = GG (d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
- c = GG (c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
- b = GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
- a = GG (a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
- d = GG (d, a, b, c, x[10], 9, 0x02441453); /* 22 */
- c = GG (c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
- b = GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
- a = GG (a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
- d = GG (d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
- c = GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
- b = GG (b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
- a = GG (a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
- d = GG (d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
- c = GG (c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
- b = GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
-
- /* Round 3 */
- a = HH (a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */
- d = HH (d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
- c = HH (c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
- b = HH (b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
- a = HH (a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
- d = HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
- c = HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
- b = HH (b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
- a = HH (a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
- d = HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
- c = HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
- b = HH (b, c, d, a, x[ 6], 23, 0x04881d05); /* 44 */
- a = HH (a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
- d = HH (d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
- c = HH (c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
- b = HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
-
- /* Round 4 */
- a = II (a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */
- d = II (d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
- c = II (c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
- b = II (b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
- a = II (a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
- d = II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
- c = II (c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
- b = II (b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
- a = II (a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
- d = II (d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
- c = II (c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
- b = II (b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
- a = II (a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
- d = II (d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
- c = II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
- b = II (b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
-
- state.state[0] += a;
- state.state[1] += b;
- state.state[2] += c;
- state.state[3] += d;
- }
+
}
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/MD5InputStream.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/MD5InputStream.java 2009-04-28 17:28:47 UTC (rev 1450)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/MD5InputStream.java 2009-04-29 12:30:18 UTC (rev 1451)
@@ -1,131 +1,169 @@
-/*
- * Implements MD5 functionality on a stream.
- *
- * written Santeri Paavolainen, Helsinki Finland 1996
- * (c) Santeri Paavolainen, Helsinki Finland 1996
- * modifications Copyright (C) 2002 Stephen Ostermiller
- * http://ostermiller.org/contact.pl?regarding=Java+Utilities
- *
- * This program 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.
- *
- * This program 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.
- *
- * See COPYING.TXT for details.
- *
- * The original work by Santeri Paavolainen can be found a
- * http://www.helsinki.fi/~sjpaavol/programs/md5/
- */
package org.codelutin.util;
import java.io.*;
-/**
- * Implements MD5 functionality on a stream.
- * More information about this class is available from <a target="_top" href=
- * "http://ostermiller.org/utils/MD5.html">ostermiller.org</a>.
+/**
+ * MD5InputStream, a subclass of FilterInputStream implementing MD5
+ * functionality on a stream.
* <p>
- * This class produces a 128-bit "fingerprint" or "message digest" for
- * all data read from this stream.
- * It is conjectured that it is computationally infeasible to produce
- * two messages having the same message digest, or to produce any
- * message having a given pre-specified target message digest. The MD5
- * algorithm is intended for digital signature applications, where a
- * large file must be "compressed" in a secure manner before being
- * encrypted with a private (secret) key under a public-key cryptosystem
- * such as RSA.
+ * Originally written by Santeri Paavolainen, Helsinki Finland 1996 <br>
+ * (c) Santeri Paavolainen, Helsinki Finland 1996 <br>
+ * Some changes Copyright (c) 2002 Timothy W Macinta <br>
* <p>
- * For more information see RFC1321.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * <p>
+ * This library 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
+ * Library General Public License for more details.
+ * <p>
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * <p>
+ * See http://www.twmacinta.com/myjava/fast_md5.php for more information
+ * on this file.
+ * <p>
+ * Please note: I (Timothy Macinta) have put this code in the
+ * com.twmacinta.util package only because it came without a package. I
+ * was not the the original author of the code, although I did
+ * optimize it (substantially) and fix some bugs.
*
- * @see MD5
- * @see MD5OutputStream
- *
- * @author Santeri Paavolainen http://www.helsinki.fi/~sjpaavol/programs/md5/
- * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
- * @since ostermillerutils 1.00.00
- */
+ * @author Santeri Paavolainen <santtu(a)cs.hut.fi>
+ * @author Timothy W Macinta (twm(a)alum.mit.edu) (added main() method)
+ **/
+
+
public class MD5InputStream extends FilterInputStream {
- /**
- * MD5 context
- */
- private MD5 md5;
+ /**
+ * MD5 context
+ */
+ private MD5 md5;
+
+ /**
+ * Creates a MD5InputStream
+ * @param in The input stream
+ */
+ public MD5InputStream (InputStream in) {
+ super(in);
- /**
- * Creates a MD5InputStream
- * @param in the underlying input stream
- */
- public MD5InputStream (InputStream in) {
- super(in);
- md5 = new MD5();
- }
+ md5 = new MD5();
+ }
- /**
- * Reads the next byte of data from this input stream. The value byte
- * is returned as an int in the range 0 to 255. If no byte is available
- * because the end of the stream has been reached, the value -1 is returned.
- * This method blocks until input data is available, the end of the stream is
- * detected, or an exception is thrown.
- * <p>
- * This method simply performs in.read() and returns the result.
- *
- * @return the next byte of data, or -1 if the end of the stream is reached.
- * @throws IOException if an I/O error occurs.
- *
- * @since ostermillerutils 1.00.00
- */
- @Override public int read() throws IOException {
- int c = in.read();
- if (c == -1) {
- return -1;
- }
- md5.update((byte)(c & 0xff));
- return c;
-}
+ /**
+ * Read a byte of data.
+ * @see java.io.FilterInputStream
+ */
+ public int read() throws IOException {
+ int c = in.read();
- /**
- * Reads up to length bytes of data from this input stream into an
- * array of bytes. This method blocks until some input is available.
- *
- * @param bytes the buffer into which the data is read.
- * @param offset the start offset of the data.
- * @param length the maximum number of bytes read.
- * @throws IOException if an I/O error occurs.
- *
- * @since ostermillerutils 1.00.00
- */
- @Override public int read(byte[] bytes, int offset, int length) throws IOException {
- int r;
- if ((r = in.read(bytes, offset, length)) == -1) {
- return r;
- }
- md5.update(bytes, offset, r);
- return r;
+ if (c == -1)
+ return -1;
+
+ if ((c & ~0xff) != 0) {
+ System.out.println("MD5InputStream.read() got character with (c & ~0xff) != 0)!");
+ } else {
+ md5.Update(c);
}
- /**
- * Returns array of bytes representing hash of the stream so far.
- *
- * @return Array of 16 bytes, the hash of all read bytes.
- *
- * @since ostermillerutils 1.00.00
- */
- public byte[] getHash(){
- return md5.getHash();
+ return c;
+ }
+
+ /**
+ * Reads into an array of bytes.
+ *
+ * @see java.io.FilterInputStream
+ */
+ public int read (byte bytes[], int offset, int length) throws IOException {
+ int r;
+
+ if ((r = in.read(bytes, offset, length)) == -1)
+ return r;
+
+ md5.Update(bytes, offset, r);
+
+ return r;
+ }
+
+ /**
+ * Returns array of bytes representing hash of the stream as
+ * finalized for the current state.
+ * @see MD5#Final
+ */
+ public byte[] hash () {
+ return md5.Final();
+ }
+
+ public MD5 getMD5() {
+ return md5;
+ }
+
+ /**
+ * This method is here for testing purposes only - do not rely
+ * on it being here.
+ **/
+ public static void main(String[] arg) {
+ try {
+
+ ////////////////////////////////////////////////////////////////
+ //
+ // usage: java com.twmacinta.util.MD5InputStream [--use-default-md5] [--no-native-lib] filename
+ //
+ /////////
+
+ // determine the filename to use and the MD5 impelementation to use
+
+ String filename = arg[arg.length-1];
+ boolean use_default_md5 = false;
+ boolean use_native_lib = true;
+ for (int i = 0; i < arg.length-1; i++) {
+ if (arg[i].equals("--use-default-md5")) {
+ use_default_md5 = true;
+ } else if (arg[i].equals("--no-native-lib")) {
+ use_native_lib = false;
+ }
+ }
+
+ // initialize common variables
+
+ byte[] buf = new byte[65536];
+ int num_read;
+
+ // Use the default MD5 implementation that comes with Java
+
+ if (use_default_md5) {
+ InputStream in = new BufferedInputStream(new FileInputStream(filename));
+ java.security.MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
+ while ((num_read = in.read(buf)) != -1) {
+ digest.update(buf, 0, num_read);
+ }
+ System.out.println(MD5.asHex(digest.digest())+" "+filename);
+ in.close();
+
+ // Use the optimized MD5 implementation
+
+ } else {
+
+ // disable the native library search, if requested
+
+ if (!use_native_lib) {
+ MD5.initNativeLibrary(true);
+ }
+
+ // calculate the checksum
+
+ MD5InputStream in = new MD5InputStream(new BufferedInputStream(new FileInputStream(filename)));
+ while ((num_read = in.read(buf)) != -1);
+ System.out.println(MD5.asHex(in.hash())+" "+filename);
+ in.close();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
}
+ }
- /**
- * Get a 32-character hex representation representing hash of the stream so far.
- *
- * @return A string containing the hash of all written bytes.
- *
- * @since ostermillerutils 1.00.00
- */
- public String getHashString(){
- return md5.getHashString();
- }
}
+
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/MD5OutputStream.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/MD5OutputStream.java 2009-04-28 17:28:47 UTC (rev 1450)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/MD5OutputStream.java 2009-04-29 12:30:18 UTC (rev 1451)
@@ -1,120 +1,117 @@
-/*
- * Implements MD5 functionality on a stream.
- *
- * written Santeri Paavolainen, Helsinki Finland 1996
- * (c) Santeri Paavolainen, Helsinki Finland 1996
- * modifications Copyright (C) 2002 Stephen Ostermiller
- * http://ostermiller.org/contact.pl?regarding=Java+Utilities
- *
- * This program 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.
- *
- * This program 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.
- *
- * See COPYING.TXT for details.
- *
- * The original work by Santeri Paavolainen can be found a
- * http://www.helsinki.fi/~sjpaavol/programs/md5/
- */
package org.codelutin.util;
import java.io.*;
-/**
- * Implements MD5 functionality on a stream.
- * More information about this class is available from <a target="_top" href=
- * "http://ostermiller.org/utils/MD5.html">ostermiller.org</a>.
+/**
+ * MD5OutputStream is a subclass of FilterOutputStream adding MD5
+ * hashing of the output.
* <p>
- * This class produces a 128-bit "fingerprint" or "message digest" for
- * all data written to this stream.
- * It is conjectured that it is computationally infeasible to produce
- * two messages having the same message digest, or to produce any
- * message having a given pre-specified target message digest. The MD5
- * algorithm is intended for digital signature applications, where a
- * large file must be "compressed" in a secure manner before being
- * encrypted with a private (secret) key under a public-key cryptosystem
- * such as RSA.
+ * Originally written by Santeri Paavolainen, Helsinki Finland 1996 <br>
+ * (c) Santeri Paavolainen, Helsinki Finland 1996 <br>
+ * Some changes Copyright (c) 2002 Timothy W Macinta <br>
* <p>
- * For more information see RFC1321.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * <p>
+ * This library 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
+ * Library General Public License for more details.
+ * <p>
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * <p>
+ * See http://www.twmacinta.com/myjava/fast_md5.php for more information
+ * on this file.
+ * <p>
+ * Please note: I (Timothy Macinta) have put this code in the
+ * com.twmacinta.util package only because it came without a package. I
+ * was not the the original author of the code, although I did
+ * optimize it (substantially) and fix some bugs.
*
- * @see MD5
- * @see MD5InputStream
- *
- * @author Santeri Paavolainen http://www.helsinki.fi/~sjpaavol/programs/md5/
- * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
- * @since ostermillerutils 1.00.00
- */
-public class MD5OutputStream extends FilterOutputStream {
+ * @author Santeri Paavolainen <santtu(a)cs.hut.fi>
+ * @author Timothy W Macinta (twm(a)alum.mit.edu) (added main() method)
+ **/
+public class MD5OutputStream extends FilterOutputStream {
/**
* MD5 context
*/
- private MD5 md5;
+ private MD5 md5;
/**
* Creates MD5OutputStream
- * @param out The output stream
- *
- * @since ostermillerutils 1.00.00
+ * @param out The output stream
*/
- public MD5OutputStream(OutputStream out) {
- super(out);
- md5 = new MD5();
+
+ public MD5OutputStream (OutputStream out) {
+ super(out);
+
+ md5 = new MD5();
}
/**
- * Writes the specified byte to this output stream.
+ * Writes a byte.
*
- * @param b the byte.
- * @throws IOException if an I/O error occurs.
- *
- * @since ostermillerutils 1.00.00
+ * @see java.io.FilterOutputStream
*/
- @Override public void write(int b) throws IOException {
- out.write(b);
- md5.update((byte)(b & 0xff));
+
+ public void write (int b) throws IOException {
+ out.write(b);
+ md5.Update((byte) b);
}
/**
- * Writes length bytes from the specified byte array starting a
- * offset off to this output stream.
+ * Writes a sub array of bytes.
*
- * @param b the data.
- * @param off the start offset in the data.
- * @param len the number of bytes to write.
- * @throws IOException if an I/O error occurs.
- *
- * @since ostermillerutils 1.00.00
+ * @see java.io.FilterOutputStream
*/
- @Override public void write(byte b[], int off, int len) throws IOException {
- out.write(b, off, len);
- md5.update(b, off, len);
+
+ public void write (byte b[], int off, int len) throws IOException {
+ out.write(b, off, len);
+ md5.Update(b, off, len);
}
/**
- * Returns array of bytes representing hash of the stream so far.
- *
- * @return Array of 16 bytes, the hash of all written bytes.
- *
- * @since ostermillerutils 1.00.00
+ * Returns array of bytes representing hash of the stream as finalized
+ * for the current state.
+ * @see MD5#Final
*/
- public byte[] getHash(){
- return md5.getHash();
+
+ public byte[] hash () {
+ return md5.Final();
}
- /**
- * Get a 32-character hex representation representing hash of the stream so far.
- *
- * @return A string containing the hash of all written bytes.
- *
- * @since ostermillerutils 1.00.00
- */
- public String getHashString(){
- return md5.getHashString();
+ public MD5 getMD5() {
+ return md5;
+ }
+
+ /*
+ * This method is here for testing purposes only - do not rely
+ * on it being here.
+ *
+ public static void main(String[] arg) {
+ try {
+ MD5OutputStream out = new MD5OutputStream(new com.twmacinta.io.NullOutputStream());
+ InputStream in = new BufferedInputStream(new FileInputStream(arg[0]));
+ byte[] buf = new byte[65536];
+ int num_read;
+ long total_read = 0;
+ while ((num_read = in.read(buf)) != -1) {
+ total_read += num_read;
+ out.write(buf, 0, num_read);
+ }
+ System.out.println(MD5.asHex(out.hash())+" "+arg[0]);
+ in.close();
+ out.close();
+ } catch (Exception e) {
+ e.printStackTrace();
}
-}
\ No newline at end of file
+ }*/
+
+
+}
+
Added: lutinutil/trunk/src/main/java/org/codelutin/util/MD5State.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/MD5State.java (rev 0)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/MD5State.java 2009-04-29 12:30:18 UTC (rev 1451)
@@ -0,0 +1,79 @@
+package org.codelutin.util;
+
+/**
+ * Fast implementation of RSA's MD5 hash generator in Java JDK Beta-2 or higher<br>
+ * Originally written by Santeri Paavolainen, Helsinki Finland 1996 <br>
+ * (c) Santeri Paavolainen, Helsinki Finland 1996 <br>
+ * Some changes Copyright (c) 2002 Timothy W Macinta <br>
+ * <p>
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * <p>
+ * This library 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
+ * Library General Public License for more details.
+ * <p>
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * <p>
+ * See http://www.twmacinta.com/myjava/fast_md5.php for more information
+ * on this file.
+ * <p>
+ * Contains internal state of the MD5 class
+ * <p>
+ * Please note: I (Timothy Macinta) have put this code in the
+ * com.twmacinta.util package only because it came without a package. I
+ * was not the the original author of the code, although I did
+ * optimize it (substantially) and fix some bugs.
+ *
+ * @author Santeri Paavolainen <sjpaavol(a)cc.helsinki.fi>
+ * @author Timothy W Macinta (twm(a)alum.mit.edu) (optimizations and bug fixes)
+ **/
+
+class MD5State {
+ /**
+ * 128-bit state
+ */
+ int state[];
+
+ /**
+ * 64-bit character count
+ */
+ long count;
+
+ /**
+ * 64-byte buffer (512 bits) for storing to-be-hashed characters
+ */
+ byte buffer[];
+
+ public MD5State() {
+ buffer = new byte[64];
+ count = 0;
+ state = new int[4];
+
+ state[0] = 0x67452301;
+ state[1] = 0xefcdab89;
+ state[2] = 0x98badcfe;
+ state[3] = 0x10325476;
+
+ }
+
+ /** Create this State as a copy of another state */
+ public MD5State (MD5State from) {
+ this();
+
+ int i;
+
+ for (i = 0; i < buffer.length; i++)
+ this.buffer[i] = from.buffer[i];
+
+ for (i = 0; i < state.length; i++)
+ this.state[i] = from.state[i];
+
+ this.count = from.count;
+ }
+};
1
0
[Lutinutil-commits] r1450 - lutinutil/trunk/src/main/java/org/codelutin/util
by chatellier@users.labs.libre-entreprise.org 28 Apr '09
by chatellier@users.labs.libre-entreprise.org 28 Apr '09
28 Apr '09
Author: chatellier
Date: 2009-04-28 17:28:47 +0000 (Tue, 28 Apr 2009)
New Revision: 1450
Modified:
lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
Log:
Add comment
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-28 17:13:08 UTC (rev 1449)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-28 17:28:47 UTC (rev 1450)
@@ -155,7 +155,7 @@
* @param root for all file in includes that is in this directory, then we
* remove this directory in zip entry name (aka -C for tar), can be null;
* @param includes the files to include in zip
- * @param createMD5 also create a MD5 file (zip name + .md5)
+ * @param createMD5 also create a MD5 file (zip name + .md5). MD5 file is created after zip.
* @throws IOException if any problem while compressing
*/
public static void compressFiles(File zipFile, File root, Collection<File> includes, boolean createMD5) throws IOException {
1
0
[Lutinutil-commits] r1449 - in lutinutil/trunk: . src/main/java/org/codelutin/util src/test/java/org/codelutin/util
by chatellier@users.labs.libre-entreprise.org 28 Apr '09
by chatellier@users.labs.libre-entreprise.org 28 Apr '09
28 Apr '09
Author: chatellier
Date: 2009-04-28 17:13:08 +0000 (Tue, 28 Apr 2009)
New Revision: 1449
Removed:
lutinutil/trunk/src/main/java/org/codelutin/util/MD5State.java
Modified:
lutinutil/trunk/changelog.txt
lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
lutinutil/trunk/src/test/java/org/codelutin/util/ZipUtilTest.java
Log:
Create a md5 file "on-the-fly" when crating an archive
Modified: lutinutil/trunk/changelog.txt
===================================================================
--- lutinutil/trunk/changelog.txt 2009-04-28 16:59:51 UTC (rev 1448)
+++ lutinutil/trunk/changelog.txt 2009-04-28 17:13:08 UTC (rev 1449)
@@ -1,5 +1,9 @@
+ver 1.0.5 chatellier xxxxxx
+ * Change MD5 implementation to http://ostermiller.org/utils/MD5.html one.
+
ver 1.0.4 chemit 20090311
* 20090305 [chemit] - improve FileUtil methods : now can specify the component's invoker (fix some focus bugs in fullscreen mode)
+
ver 1.0.3 chemit 20090218
* 20090218 [chemit] - use lutinproject 3.4
* 20090209 [chemit] - add inputStreamToFile method in FileUtil + javadoc on this class
Deleted: lutinutil/trunk/src/main/java/org/codelutin/util/MD5State.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/MD5State.java 2009-04-28 16:59:51 UTC (rev 1448)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/MD5State.java 2009-04-28 17:13:08 UTC (rev 1449)
@@ -1,97 +0,0 @@
-/**
- * *##% Lutin utilities library
- * Copyright (C) 2004 - 2008 CodeLutin
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program 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 Lesser Public License for more details.
- *
- * You should have received a copy of the GNU General Lesser Public
- * License along with this program. If not, see
- * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*
- */
-package org.codelutin.util;
-
-/**
- * Fast implementation of RSA's MD5 hash generator in Java JDK Beta-2 or higher<br>
- * Originally written by Santeri Paavolainen, Helsinki Finland 1996 <br>
- * (c) Santeri Paavolainen, Helsinki Finland 1996 <br>
- * Some changes Copyright (c) 2002 Timothy W Macinta <br>
- * <p>
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; either version 2.1 of the License, or (at your option)
- * any later version.
- * <p>
- * This library 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 Library General Public License for more
- * details.
- * <p>
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- * <p>
- * See http://www.twmacinta.com/myjava/fast_md5.php for more information on this
- * file.
- * <p>
- * Contains internal state of the MD5 class
- * <p>
- * Please note: I (Timothy Macinta) have put this code in the com.twmacinta.util
- * package only because it came without a package. I was not the the original
- * author of the code, although I did optimize it (substantially) and fix some
- * bugs.
- *
- * @author Santeri Paavolainen <sjpaavol(a)cc.helsinki.fi>
- * @author Timothy W Macinta (twm(a)alum.mit.edu) (optimizations and bug fixes)
- */
-
-class MD5State {
- /**
- * 128-bit state
- */
- int state[];
-
- /**
- * 64-bit character count
- */
- long count;
-
- /**
- * 64-byte buffer (512 bits) for storing to-be-hashed characters
- */
- byte buffer[];
-
- public MD5State() {
- buffer = new byte[64];
- count = 0;
- state = new int[4];
-
- state[0] = 0x67452301;
- state[1] = 0xefcdab89;
- state[2] = 0x98badcfe;
- state[3] = 0x10325476;
-
- }
-
- /** Create this State as a copy of another state */
- public MD5State(MD5State from) {
- this();
-
- int i;
-
- for (i = 0; i < buffer.length; i++)
- this.buffer[i] = from.buffer[i];
-
- for (i = 0; i < state.length; i++)
- this.state[i] = from.state[i];
-
- this.count = from.count;
- }
-};
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-28 16:59:51 UTC (rev 1448)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/ZipUtil.java 2009-04-28 17:13:08 UTC (rev 1449)
@@ -1,5 +1,5 @@
/* *##% Lutin utilities library
- * Copyright (C) 2004 - 2008 CodeLutin
+ * Copyright (C) 2004 - 2009 CodeLutin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
@@ -15,18 +15,6 @@
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%* */
-/* *
- * ZipUtil.java
- *
- * Created: 24 août 2006 10:13:35
- *
- * @author poussin
- * @version $Revision$
- *
- * Last update: $Date$
- * by : $Author$
- */
-
package org.codelutin.util;
import org.apache.commons.logging.LogFactory;
@@ -48,37 +36,45 @@
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
-
-/** @author poussin */
-
+/**
+ * ZipUtil.java
+ *
+ * Created: 24 août 2006 10:13:35
+ *
+ * @author poussin
+ * @version $Revision$
+ *
+ * Last update: $Date$
+ * by : $Author$
+ */
public class ZipUtil {
- /** to use log facility, just put in your code: log.info(\"...\"); */
- static private org.apache.commons.logging.Log log = LogFactory.getLog(ZipUtil.class);
+ /** Class logger. */
+ private static org.apache.commons.logging.Log log = LogFactory.getLog(ZipUtil.class);
- /** Taille du buffer pour les lectures/écritures */
+ /** Taille du buffer pour les lectures/écritures. */
private static final int BUFFER_SIZE = 8 * 1024;
- /** le séparateur de fichier en local */
+ /** Le séparateur de fichier en local. */
private static final String LOCAL_SEP = File.separator;
private static final String LOCAL_SEP_PATTERN = "\\".equals(LOCAL_SEP) ?
LOCAL_SEP + LOCAL_SEP : LOCAL_SEP;
- /** le séparateur zip */
+ /** Le séparateur zip. */
private static final String ZIP_SEP = "/";
private static final String ZIP_SEP_PATTERN = "/";
- static private FileFilter ALL_FILE_FILTER = new FileFilter() {
+ /** Accept all file pattern. */
+ protected static FileFilter ALL_FILE_FILTER = new FileFilter() {
public boolean accept(File pathname) {
return true;
}
-
};
/**
- * uncompress zipped file in targetDir
+ * Uncompress zipped file in targetDir.
*
* @param file the zip source file
* @param targetDir the destination direcotory
@@ -92,7 +88,7 @@
}
/**
- * uncompress zipped file in targetDir, and rename uncompressed file if
+ * Uncompress zipped file in targetDir, and rename uncompressed file if
* necessary. If renameFrom or renameTo is null no renaming is done
* <p/>
* file in zip use / to separate directory and not begin with /
@@ -148,7 +144,27 @@
* @throws java.io.IOException if any problem while compressing
*/
static public void compressFiles(File zipFile, File root, Collection<File> includes) throws IOException {
- FileOutputStream oStream = new FileOutputStream(zipFile);
+ compressFiles(zipFile, root, includes, false);
+ }
+
+ /**
+ * Compress 'includes' files in zipFile. If file in includes is directory
+ * only the directory is put in zipFile, not the file contained in directory
+ *
+ * @param zipFile the destination zip file
+ * @param root for all file in includes that is in this directory, then we
+ * remove this directory in zip entry name (aka -C for tar), can be null;
+ * @param includes the files to include in zip
+ * @param createMD5 also create a MD5 file (zip name + .md5)
+ * @throws IOException if any problem while compressing
+ */
+ public static void compressFiles(File zipFile, File root, Collection<File> includes, boolean createMD5) throws IOException {
+ OutputStream oStream = new FileOutputStream(zipFile);
+
+ // if md5 creation flag
+ if (createMD5) {
+ oStream = new MD5OutputStream(oStream);
+ }
try {
ZipOutputStream zipOStream = new ZipOutputStream(oStream);
@@ -173,6 +189,13 @@
zipOStream.closeEntry();
}
zipOStream.close();
+
+ // if md5 creation flag
+ if (createMD5) {
+ String md5hash = ((MD5OutputStream)oStream).getHashString();
+ File md5File = new File(zipFile.getAbsoluteFile() + ".md5");
+ FileUtil.writeString(md5File, md5hash);
+ }
} finally {
oStream.close();
}
Modified: lutinutil/trunk/src/test/java/org/codelutin/util/ZipUtilTest.java
===================================================================
--- lutinutil/trunk/src/test/java/org/codelutin/util/ZipUtilTest.java 2009-04-28 16:59:51 UTC (rev 1448)
+++ lutinutil/trunk/src/test/java/org/codelutin/util/ZipUtilTest.java 2009-04-28 17:13:08 UTC (rev 1449)
@@ -20,6 +20,8 @@
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.LogFactory;
@@ -40,9 +42,11 @@
public class ZipUtilTest {
/** to use log facility, just put in your code: log.info(\"...\"); */
- private static org.apache.commons.logging.Log log = LogFactory.getLog(ZipUtilTest.class);
+ private static org.apache.commons.logging.Log log = LogFactory
+ .getLog(ZipUtilTest.class);
- protected static final File DIR = new File(System.getProperty("java.home"), "bin");
+ protected static final File DIR = new File(System.getProperty("java.home"),
+ "bin");
@Test
public void testUncompress() throws IOException {
@@ -62,7 +66,7 @@
List<File> dest = FileUtil.getFilteredElements(ucz, null, true);
Assert.assertEquals(src.size() + 1, dest.size()); // +1 car il y a le rep lui meme dans dest
-
+
// remove created temp dirs :
FileUtil.deleteRecursively(ucz);
Assert.assertFalse(ucz.isDirectory());
@@ -108,7 +112,8 @@
@Test
public void testCompressFile() throws IOException {
- File dir = new File(System.getProperty("java.home"), "bin" + File.separator + "java");
+ File dir = new File(System.getProperty("java.home"), "bin"
+ + File.separator + "java");
File zipFile = File.createTempFile("testCompressZip", ".zip");
zipFile.deleteOnExit();
log.info("Compress " + dir + " in zip file = " + zipFile);
@@ -119,4 +124,23 @@
Assert.assertTrue(0 != zipFile.length());
}
+ @Test
+ public void testCompressFileMD5() throws IOException {
+ File dir = new File(System.getProperty("java.home"), "bin"
+ + File.separator + "java");
+ File zipFile = File.createTempFile("testCompressZip", ".zip");
+ zipFile.deleteOnExit();
+ log.info("Compress " + dir + " in zip file = " + zipFile);
+
+ Collection<File> files = Collections.singleton(dir);
+ ZipUtil.compressFiles(zipFile, dir, files, true);
+
+ Assert.assertTrue(zipFile.exists());
+ Assert.assertTrue(zipFile.length() > 0);
+ File md5File = new File(zipFile.getAbsoluteFile() + ".md5");
+ md5File.deleteOnExit();
+ Assert.assertTrue(md5File.exists());
+ Assert.assertTrue(md5File.length() > 0);
+ }
+
}
1
0
[Lutinutil-commits] r1448 - lutinutil/trunk/src/main/java/org/codelutin/util
by chatellier@users.labs.libre-entreprise.org 28 Apr '09
by chatellier@users.labs.libre-entreprise.org 28 Apr '09
28 Apr '09
Author: chatellier
Date: 2009-04-28 16:59:51 +0000 (Tue, 28 Apr 2009)
New Revision: 1448
Added:
lutinutil/trunk/src/main/java/org/codelutin/util/MD5OutputStream.java
Modified:
lutinutil/trunk/src/main/java/org/codelutin/util/MD5.java
lutinutil/trunk/src/main/java/org/codelutin/util/MD5InputStream.java
Log:
Chnage MD5 implementation to Ostermiller.
Add MD5OutputStream.
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/MD5.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/MD5.java 2009-04-24 16:18:13 UTC (rev 1447)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/MD5.java 2009-04-28 16:59:51 UTC (rev 1448)
@@ -1,835 +1,735 @@
-/**
- * *##% Lutin utilities library
- * Copyright (C) 2004 - 2008 CodeLutin
+package org.codelutin.util;
+
+/*
+ * written Santeri Paavolainen, Helsinki Finland 1996
+ * (c) Santeri Paavolainen, Helsinki Finland 1996
+ * modifications Copyright (C) 2002-2007 Stephen Ostermiller
+ * http://ostermiller.org/contact.pl?regarding=Java+Utilities
+ * Copyright (C) 2007 Stu Thompson stu.comp -at- mailworks.org
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
+ * This program 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.
*
* This program 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 Lesser Public License for more details.
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Lesser Public
- * License along with this program. If not, see
- * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*
+ * See COPYING.TXT for details.
+ *
+ * The original work by Santeri Paavolainen can be found at
+ * http://www.helsinki.fi/~sjpaavol/programs/md5/
+ *
+ * This Java class has been derived from the RSA Data Security, Inc. MD5
+ * Message-Digest Algorithm and its reference implementation.
*/
-package org.codelutin.util;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
/**
- * Fast implementation of RSA's MD5 hash generator in Java JDK Beta-2 or higher.
+ * MD5 hash generator.
+ * More information about this class is available from <a target="_top" href=
+ * "http://ostermiller.org/utils/MD5.html">ostermiller.org</a>.
* <p>
- * Originally written by Santeri Paavolainen, Helsinki Finland 1996.<br>
- * (c) Santeri Paavolainen, Helsinki Finland 1996<br>
- * Many changes Copyright (c) 2002 - 2005 Timothy W Macinta<br>
+ * This class takes as input a message of arbitrary length and produces
+ * as output a 128-bit "fingerprint" or "message digest" of the input.
+ * It is conjectured that it is computationally infeasible to produce
+ * two messages having the same message digest, or to produce any
+ * message having a given pre-specified target message digest. The MD5
+ * algorithm is intended for digital signature applications, where a
+ * large file must be "compressed" in a secure manner before being
+ * encrypted with a private (secret) key under a public-key cryptosystem
+ * such as RSA.
* <p>
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; either version 2.1 of the License, or (at your option)
- * any later version.
- * <p>
- * This library 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 Library General Public License for more
- * details.
- * <p>
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- * <p>
- * See http://www.twmacinta.com/myjava/fast_md5.php for more information on this
- * file and the related files.
- * <p>
- * This was originally a rather straight re-implementation of the reference
- * implementation given in RFC1321 by RSA. It passes the MD5 test suite as
- * defined in RFC1321.
- * <p>
- * Many optimizations made by Timothy W Macinta. Reduced time to checksum a test
- * file in Java alone to roughly half the time taken compared with
- * java.security.MessageDigest (within an intepretter). Also added an optional
- * native method to reduce the time even further. See
- * http://www.twmacinta.com/myjava/fast_md5.php for further information on the
- * time improvements achieved.
- * <p>
- * Some bug fixes also made by Timothy W Macinta.
- * <p>
- * Please note: I (Timothy Macinta) have put this code in the com.twmacinta.util
- * package only because it came without a package. I was not the the original
- * author of the code, although I did optimize it (substantially) and fix some
- * bugs.
- * <p>
- * This Java class has been derived from the RSA Data Security, Inc. MD5
- * Message-Digest Algorithm and its reference implementation.
- * <p>
- * This class will attempt to use a native method to quickly compute checksums
- * when the appropriate native library is available. On Linux, this library
- * should be named "MD5.so" and on Windows it should be named "MD5.dll". The
- * code will attempt to locate the library in the following locations in the
- * order given:
- *
- * <ol>
- * <li>The path specified by the system property
- * "com.twmacinta.util.MD5.NATIVE_LIB_FILE" (be sure to include "MD5.so" or
- * "MD5.dll" as appropriate at the end of the path).
- * <li>A platform specific directory beneath the "lib/arch/" directory. On
- * Linux for x86, this is "lib/arch/linux_x86/". On Windows for x86, this is
- * "lib/arch/win32_x86/".
- * <li>Within the "lib/" directory.
- * <li>Within the current directory.
- * </ol>
- *
- * <p>
- * If the library is not found, the code will fall back to the default (slower)
- * Java code.
- * <p>
- * As a side effect of having the code search for the native library,
- * SecurityExceptions might be thrown on JVMs that have a restrictive
- * SecurityManager. The initialization code attempts to silently discard these
- * exceptions and continue, but many SecurityManagers will attempt to notify the
- * user directly of all SecurityExceptions thrown. Consequently, the code has
- * provisions for skipping the search for the native library. Any of these
- * provisions may be used to skip the search as long as they are performed
- * <i>before</i> the first instance of a com.twmacinta.util.MD5 object is
- * constructed (note that the convenience stream objects will implicitly create
- * an MD5 object).
- * <p>
- * The first option is to set the system property
- * "com.twmacinta.util.MD5.NO_NATIVE_LIB" to "true" or "1". Unfortunately,
- * SecurityManagers may also choose to disallow system property setting, so this
- * won't be of use in all cases.
- * <p>
- * The second option is to call com.twmacinta.util.MD5.initNativeLibrary(true)
- * before any MD5 objects are constructed.
- *
- * @author Santeri Paavolainen <sjpaavol(a)cc.helsinki.fi>
- * @author Timothy W Macinta (twm(a)alum.mit.edu) (optimizations and bug fixes)
+ * For more information see RFC1321.
+ *
+ * @see MD5OutputStream
+ * @see MD5InputStream
+ *
+ * @author Santeri Paavolainen http://www.helsinki.fi/~sjpaavol/programs/md5/
+ * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
+ * @since ostermillerutils 1.00.00
*/
-
public class MD5 {
+
/**
- * MD5 state
+ * Class constructor
+ *
+ * @since ostermillerutils 1.00.00
*/
- MD5State state;
+ public MD5 () {
+ reset();
+ }
/**
- * If Final() has been called, finals is set to the current finals state.
- * Any Update() causes this to be set to null.
+ * Command line program that will take files as arguments
+ * and output the MD5 sum for each file.
+ *
+ * @param args command line arguments
+ *
+ * @since ostermillerutils 1.00.00
*/
- MD5State finals;
+ public static void main (String[] args){
+ if (args.length == 0){
+ System.err.println("Please specify a file.");
+ } else {
+ for (String element: args) {
+ try {
+ System.out.println(MD5.getHashString(new File(element)) + " " + element);
+ } catch (IOException x){
+ System.err.println(x.getMessage());
+ }
+ }
+ }
+ }
/**
- * Padding for Final()
+ * Gets this hash sum as an array of 16 bytes.
+ *
+ * @return Array of 16 bytes, the hash of all updated bytes.
+ *
+ * @since ostermillerutils 1.00.00
*/
- static byte padding[] = { (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0 };
+ public byte[] getHash() {
+ if (!finalState.valid) {
+ finalState.copy(workingState);
+ long bitCount = finalState.bitCount;
+ // Compute the number of left over bits
+ int leftOver = (int) (((bitCount >>> 3)) & 0x3f);
+ // Compute the amount of padding to add based on number of left over bits.
+ int padlen = (leftOver < 56) ? (56 - leftOver) : (120 - leftOver);
+ // add the padding
+ update(finalState, padding, 0, padlen);
+ // add the length (computed before padding was added)
+ update(finalState, encode(bitCount), 0, 8);
+ finalState.valid = true;
+ }
+ // make a copy of the hash before returning it.
+ return encode(finalState.state, 16);
+ }
- private static boolean native_lib_loaded = false;
- private static boolean native_lib_init_pending = false;
+ /**
+ * Returns 32-character hex representation of this hash.
+ *
+ * @return String representation of this object's hash.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public String getHashString(){
+ return toHex(this.getHash());
+ }
/**
- * Initialize MD5 internal state (object can be reused just by calling
- * Init() after every Final()
+ * Gets the MD5 hash of the given byte array.
+ *
+ * @param b byte array for which an MD5 hash is desired.
+ * @return Array of 16 bytes, the hash of all updated bytes.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public synchronized void Init() {
- state = new MD5State();
- finals = null;
+ public static byte[] getHash(byte[] b){
+ MD5 md5 = new MD5();
+ md5.update(b);
+ return md5.getHash();
}
/**
- * Class constructor
+ * Gets the MD5 hash of the given byte array.
+ *
+ * @param b byte array for which an MD5 hash is desired.
+ * @return 32-character hex representation the data's MD5 hash.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public MD5() {
- if (native_lib_init_pending)
- _initNativeLibrary();
- this.Init();
+ public static String getHashString(byte[] b){
+ MD5 md5 = new MD5();
+ md5.update(b);
+ return md5.getHashString();
}
/**
- * Initialize class, and update hash with ob.toString()
- *
- * @param ob
- * Object, ob.toString() is used to update hash after
- * initialization
+ * Gets the MD5 hash the data on the given InputStream.
+ *
+ * @param in byte array for which an MD5 hash is desired.
+ * @return Array of 16 bytes, the hash of all updated bytes.
+ * @throws IOException if an I/O error occurs.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public MD5(Object ob) {
- this();
- Update(ob.toString());
+ public static byte[] getHash(InputStream in) throws IOException {
+ MD5 md5 = new MD5();
+ byte[] buffer = new byte[1024];
+ int read;
+ while ((read = in.read(buffer)) != -1){
+ md5.update(buffer, read);
+ }
+ return md5.getHash();
}
- private void Decode(byte buffer[], int shift, int[] out) {
- /*len += shift;
- for (int i = 0; shift < len; i++, shift += 4) {
- out[i] = ((int) (buffer[shift] & 0xff)) |
- (((int) (buffer[shift + 1] & 0xff)) << 8) |
- (((int) (buffer[shift + 2] & 0xff)) << 16) |
- (((int) buffer[shift + 3]) << 24);
- }*/
+ /**
+ * Gets the MD5 hash the data on the given InputStream.
+ *
+ * @param in byte array for which an MD5 hash is desired.
+ * @return 32-character hex representation the data's MD5 hash.
+ * @throws IOException if an I/O error occurs.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public static String getHashString(InputStream in) throws IOException {
+ MD5 md5 = new MD5();
+ byte[] buffer = new byte[1024];
+ int read;
+ while ((read = in.read(buffer)) != -1){
+ md5.update(buffer, read);
+ }
+ return md5.getHashString();
+ }
- // unrolled loop (original loop shown above)
- out[0] = ((int) (buffer[shift] & 0xff))
- | (((int) (buffer[shift + 1] & 0xff)) << 8)
- | (((int) (buffer[shift + 2] & 0xff)) << 16)
- | (((int) buffer[shift + 3]) << 24);
- out[1] = ((int) (buffer[shift + 4] & 0xff))
- | (((int) (buffer[shift + 5] & 0xff)) << 8)
- | (((int) (buffer[shift + 6] & 0xff)) << 16)
- | (((int) buffer[shift + 7]) << 24);
- out[2] = ((int) (buffer[shift + 8] & 0xff))
- | (((int) (buffer[shift + 9] & 0xff)) << 8)
- | (((int) (buffer[shift + 10] & 0xff)) << 16)
- | (((int) buffer[shift + 11]) << 24);
- out[3] = ((int) (buffer[shift + 12] & 0xff))
- | (((int) (buffer[shift + 13] & 0xff)) << 8)
- | (((int) (buffer[shift + 14] & 0xff)) << 16)
- | (((int) buffer[shift + 15]) << 24);
- out[4] = ((int) (buffer[shift + 16] & 0xff))
- | (((int) (buffer[shift + 17] & 0xff)) << 8)
- | (((int) (buffer[shift + 18] & 0xff)) << 16)
- | (((int) buffer[shift + 19]) << 24);
- out[5] = ((int) (buffer[shift + 20] & 0xff))
- | (((int) (buffer[shift + 21] & 0xff)) << 8)
- | (((int) (buffer[shift + 22] & 0xff)) << 16)
- | (((int) buffer[shift + 23]) << 24);
- out[6] = ((int) (buffer[shift + 24] & 0xff))
- | (((int) (buffer[shift + 25] & 0xff)) << 8)
- | (((int) (buffer[shift + 26] & 0xff)) << 16)
- | (((int) buffer[shift + 27]) << 24);
- out[7] = ((int) (buffer[shift + 28] & 0xff))
- | (((int) (buffer[shift + 29] & 0xff)) << 8)
- | (((int) (buffer[shift + 30] & 0xff)) << 16)
- | (((int) buffer[shift + 31]) << 24);
- out[8] = ((int) (buffer[shift + 32] & 0xff))
- | (((int) (buffer[shift + 33] & 0xff)) << 8)
- | (((int) (buffer[shift + 34] & 0xff)) << 16)
- | (((int) buffer[shift + 35]) << 24);
- out[9] = ((int) (buffer[shift + 36] & 0xff))
- | (((int) (buffer[shift + 37] & 0xff)) << 8)
- | (((int) (buffer[shift + 38] & 0xff)) << 16)
- | (((int) buffer[shift + 39]) << 24);
- out[10] = ((int) (buffer[shift + 40] & 0xff))
- | (((int) (buffer[shift + 41] & 0xff)) << 8)
- | (((int) (buffer[shift + 42] & 0xff)) << 16)
- | (((int) buffer[shift + 43]) << 24);
- out[11] = ((int) (buffer[shift + 44] & 0xff))
- | (((int) (buffer[shift + 45] & 0xff)) << 8)
- | (((int) (buffer[shift + 46] & 0xff)) << 16)
- | (((int) buffer[shift + 47]) << 24);
- out[12] = ((int) (buffer[shift + 48] & 0xff))
- | (((int) (buffer[shift + 49] & 0xff)) << 8)
- | (((int) (buffer[shift + 50] & 0xff)) << 16)
- | (((int) buffer[shift + 51]) << 24);
- out[13] = ((int) (buffer[shift + 52] & 0xff))
- | (((int) (buffer[shift + 53] & 0xff)) << 8)
- | (((int) (buffer[shift + 54] & 0xff)) << 16)
- | (((int) buffer[shift + 55]) << 24);
- out[14] = ((int) (buffer[shift + 56] & 0xff))
- | (((int) (buffer[shift + 57] & 0xff)) << 8)
- | (((int) (buffer[shift + 58] & 0xff)) << 16)
- | (((int) buffer[shift + 59]) << 24);
- out[15] = ((int) (buffer[shift + 60] & 0xff))
- | (((int) (buffer[shift + 61] & 0xff)) << 8)
- | (((int) (buffer[shift + 62] & 0xff)) << 16)
- | (((int) buffer[shift + 63]) << 24);
+ /**
+ * Gets the MD5 hash of the given file.
+ *
+ * @param f file for which an MD5 hash is desired.
+ * @return Array of 16 bytes, the hash of all updated bytes.
+ * @throws IOException if an I/O error occurs.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public static byte[] getHash(File f) throws IOException {
+ InputStream is = new FileInputStream(f);
+ byte[] hash = getHash(is);
+ is.close();
+ return hash;
}
- private native void Transform_native(int[] state, byte buffer[], int shift,
- int length);
+ /**
+ * Gets the MD5 hash of the given file.
+ *
+ * @param f file array for which an MD5 hash is desired.
+ * @return 32-character hex representation the data's MD5 hash.
+ * @throws IOException if an I/O error occurs.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public static String getHashString(File f) throws IOException {
+ InputStream is = new FileInputStream(f);
+ String hash = getHashString(is);
+ is.close();
+ return hash;
+ }
- private void Transform(MD5State state, byte buffer[], int shift,
- int[] decode_buf) {
- int a = state.state[0], b = state.state[1], c = state.state[2], d = state.state[3], x[] = decode_buf;
+ /**
+ * Gets the MD5 hash of the given String.
+ * The string is converted to bytes using the current
+ * platform's default character encoding.
+ *
+ * @param s String for which an MD5 hash is desired.
+ * @return Array of 16 bytes, the hash of all updated bytes.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public static byte[] getHash(String s){
+ MD5 md5 = new MD5();
+ md5.update(s);
+ return md5.getHash();
+ }
- Decode(buffer, shift, decode_buf);
+ /**
+ * Gets the MD5 hash of the given String.
+ * The string is converted to bytes using the current
+ * platform's default character encoding.
+ *
+ * @param s String for which an MD5 hash is desired.
+ * @return 32-character hex representation the data's MD5 hash.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public static String getHashString(String s){
+ MD5 md5 = new MD5();
+ md5.update(s);
+ return md5.getHashString();
+ }
- /* Round 1 */
- a += ((b & c) | (~b & d)) + x[0] + 0xd76aa478; /* 1 */
- a = ((a << 7) | (a >>> 25)) + b;
- d += ((a & b) | (~a & c)) + x[1] + 0xe8c7b756; /* 2 */
- d = ((d << 12) | (d >>> 20)) + a;
- c += ((d & a) | (~d & b)) + x[2] + 0x242070db; /* 3 */
- c = ((c << 17) | (c >>> 15)) + d;
- b += ((c & d) | (~c & a)) + x[3] + 0xc1bdceee; /* 4 */
- b = ((b << 22) | (b >>> 10)) + c;
- a += ((b & c) | (~b & d)) + x[4] + 0xf57c0faf; /* 5 */
- a = ((a << 7) | (a >>> 25)) + b;
- d += ((a & b) | (~a & c)) + x[5] + 0x4787c62a; /* 6 */
- d = ((d << 12) | (d >>> 20)) + a;
- c += ((d & a) | (~d & b)) + x[6] + 0xa8304613; /* 7 */
- c = ((c << 17) | (c >>> 15)) + d;
- b += ((c & d) | (~c & a)) + x[7] + 0xfd469501; /* 8 */
- b = ((b << 22) | (b >>> 10)) + c;
+ /**
+ * Gets the MD5 hash of the given String.
+ *
+ * @param s String for which an MD5 hash is desired.
+ * @param enc The name of a supported character encoding.
+ * @return Array of 16 bytes, the hash of all updated bytes.
+ * @throws UnsupportedEncodingException If the named encoding is not supported.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public static byte[] getHash(String s, String enc) throws UnsupportedEncodingException {
+ MD5 md5 = new MD5();
+ md5.update(s, enc);
+ return md5.getHash();
+ }
- a += ((b & c) | (~b & d)) + x[8] + 0x698098d8; /* 9 */
- a = ((a << 7) | (a >>> 25)) + b;
- d += ((a & b) | (~a & c)) + x[9] + 0x8b44f7af; /* 10 */
- d = ((d << 12) | (d >>> 20)) + a;
- c += ((d & a) | (~d & b)) + x[10] + 0xffff5bb1; /* 11 */
- c = ((c << 17) | (c >>> 15)) + d;
- b += ((c & d) | (~c & a)) + x[11] + 0x895cd7be; /* 12 */
- b = ((b << 22) | (b >>> 10)) + c;
+ /**
+ * Gets the MD5 hash of the given String.
+ *
+ * @param s String for which an MD5 hash is desired.
+ * @param enc The name of a supported character encoding.
+ * @return 32-character hex representation the data's MD5 hash.
+ * @throws UnsupportedEncodingException If the named encoding is not supported.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public static String getHashString(String s, String enc) throws UnsupportedEncodingException {
+ MD5 md5 = new MD5();
+ md5.update(s, enc);
+ return md5.getHashString();
+ }
- a += ((b & c) | (~b & d)) + x[12] + 0x6b901122; /* 13 */
- a = ((a << 7) | (a >>> 25)) + b;
- d += ((a & b) | (~a & c)) + x[13] + 0xfd987193; /* 14 */
- d = ((d << 12) | (d >>> 20)) + a;
- c += ((d & a) | (~d & b)) + x[14] + 0xa679438e; /* 15 */
- c = ((c << 17) | (c >>> 15)) + d;
- b += ((c & d) | (~c & a)) + x[15] + 0x49b40821; /* 16 */
- b = ((b << 22) | (b >>> 10)) + c;
- /* Round 2 */
- a += ((b & d) | (c & ~d)) + x[1] + 0xf61e2562; /* 17 */
- a = ((a << 5) | (a >>> 27)) + b;
- d += ((a & c) | (b & ~c)) + x[6] + 0xc040b340; /* 18 */
- d = ((d << 9) | (d >>> 23)) + a;
- c += ((d & b) | (a & ~b)) + x[11] + 0x265e5a51; /* 19 */
- c = ((c << 14) | (c >>> 18)) + d;
- b += ((c & a) | (d & ~a)) + x[0] + 0xe9b6c7aa; /* 20 */
- b = ((b << 20) | (b >>> 12)) + c;
+ /**
+ * Reset the MD5 sum to its initial state.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public void reset() {
+ workingState.reset();
+ finalState.valid = false;
+ }
- a += ((b & d) | (c & ~d)) + x[5] + 0xd62f105d; /* 21 */
- a = ((a << 5) | (a >>> 27)) + b;
- d += ((a & c) | (b & ~c)) + x[10] + 0x02441453; /* 22 */
- d = ((d << 9) | (d >>> 23)) + a;
- c += ((d & b) | (a & ~b)) + x[15] + 0xd8a1e681; /* 23 */
- c = ((c << 14) | (c >>> 18)) + d;
- b += ((c & a) | (d & ~a)) + x[4] + 0xe7d3fbc8; /* 24 */
- b = ((b << 20) | (b >>> 12)) + c;
-
- a += ((b & d) | (c & ~d)) + x[9] + 0x21e1cde6; /* 25 */
- a = ((a << 5) | (a >>> 27)) + b;
- d += ((a & c) | (b & ~c)) + x[14] + 0xc33707d6; /* 26 */
- d = ((d << 9) | (d >>> 23)) + a;
- c += ((d & b) | (a & ~b)) + x[3] + 0xf4d50d87; /* 27 */
- c = ((c << 14) | (c >>> 18)) + d;
- b += ((c & a) | (d & ~a)) + x[8] + 0x455a14ed; /* 28 */
- b = ((b << 20) | (b >>> 12)) + c;
-
- a += ((b & d) | (c & ~d)) + x[13] + 0xa9e3e905; /* 29 */
- a = ((a << 5) | (a >>> 27)) + b;
- d += ((a & c) | (b & ~c)) + x[2] + 0xfcefa3f8; /* 30 */
- d = ((d << 9) | (d >>> 23)) + a;
- c += ((d & b) | (a & ~b)) + x[7] + 0x676f02d9; /* 31 */
- c = ((c << 14) | (c >>> 18)) + d;
- b += ((c & a) | (d & ~a)) + x[12] + 0x8d2a4c8a; /* 32 */
- b = ((b << 20) | (b >>> 12)) + c;
-
- /* Round 3 */
- a += (b ^ c ^ d) + x[5] + 0xfffa3942; /* 33 */
- a = ((a << 4) | (a >>> 28)) + b;
- d += (a ^ b ^ c) + x[8] + 0x8771f681; /* 34 */
- d = ((d << 11) | (d >>> 21)) + a;
- c += (d ^ a ^ b) + x[11] + 0x6d9d6122; /* 35 */
- c = ((c << 16) | (c >>> 16)) + d;
- b += (c ^ d ^ a) + x[14] + 0xfde5380c; /* 36 */
- b = ((b << 23) | (b >>> 9)) + c;
-
- a += (b ^ c ^ d) + x[1] + 0xa4beea44; /* 37 */
- a = ((a << 4) | (a >>> 28)) + b;
- d += (a ^ b ^ c) + x[4] + 0x4bdecfa9; /* 38 */
- d = ((d << 11) | (d >>> 21)) + a;
- c += (d ^ a ^ b) + x[7] + 0xf6bb4b60; /* 39 */
- c = ((c << 16) | (c >>> 16)) + d;
- b += (c ^ d ^ a) + x[10] + 0xbebfbc70; /* 40 */
- b = ((b << 23) | (b >>> 9)) + c;
-
- a += (b ^ c ^ d) + x[13] + 0x289b7ec6; /* 41 */
- a = ((a << 4) | (a >>> 28)) + b;
- d += (a ^ b ^ c) + x[0] + 0xeaa127fa; /* 42 */
- d = ((d << 11) | (d >>> 21)) + a;
- c += (d ^ a ^ b) + x[3] + 0xd4ef3085; /* 43 */
- c = ((c << 16) | (c >>> 16)) + d;
- b += (c ^ d ^ a) + x[6] + 0x04881d05; /* 44 */
- b = ((b << 23) | (b >>> 9)) + c;
-
- a += (b ^ c ^ d) + x[9] + 0xd9d4d039; /* 33 */
- a = ((a << 4) | (a >>> 28)) + b;
- d += (a ^ b ^ c) + x[12] + 0xe6db99e5; /* 34 */
- d = ((d << 11) | (d >>> 21)) + a;
- c += (d ^ a ^ b) + x[15] + 0x1fa27cf8; /* 35 */
- c = ((c << 16) | (c >>> 16)) + d;
- b += (c ^ d ^ a) + x[2] + 0xc4ac5665; /* 36 */
- b = ((b << 23) | (b >>> 9)) + c;
-
- /* Round 4 */
- a += (c ^ (b | ~d)) + x[0] + 0xf4292244; /* 49 */
- a = ((a << 6) | (a >>> 26)) + b;
- d += (b ^ (a | ~c)) + x[7] + 0x432aff97; /* 50 */
- d = ((d << 10) | (d >>> 22)) + a;
- c += (a ^ (d | ~b)) + x[14] + 0xab9423a7; /* 51 */
- c = ((c << 15) | (c >>> 17)) + d;
- b += (d ^ (c | ~a)) + x[5] + 0xfc93a039; /* 52 */
- b = ((b << 21) | (b >>> 11)) + c;
-
- a += (c ^ (b | ~d)) + x[12] + 0x655b59c3; /* 53 */
- a = ((a << 6) | (a >>> 26)) + b;
- d += (b ^ (a | ~c)) + x[3] + 0x8f0ccc92; /* 54 */
- d = ((d << 10) | (d >>> 22)) + a;
- c += (a ^ (d | ~b)) + x[10] + 0xffeff47d; /* 55 */
- c = ((c << 15) | (c >>> 17)) + d;
- b += (d ^ (c | ~a)) + x[1] + 0x85845dd1; /* 56 */
- b = ((b << 21) | (b >>> 11)) + c;
-
- a += (c ^ (b | ~d)) + x[8] + 0x6fa87e4f; /* 57 */
- a = ((a << 6) | (a >>> 26)) + b;
- d += (b ^ (a | ~c)) + x[15] + 0xfe2ce6e0; /* 58 */
- d = ((d << 10) | (d >>> 22)) + a;
- c += (a ^ (d | ~b)) + x[6] + 0xa3014314; /* 59 */
- c = ((c << 15) | (c >>> 17)) + d;
- b += (d ^ (c | ~a)) + x[13] + 0x4e0811a1; /* 60 */
- b = ((b << 21) | (b >>> 11)) + c;
-
- a += (c ^ (b | ~d)) + x[4] + 0xf7537e82; /* 61 */
- a = ((a << 6) | (a >>> 26)) + b;
- d += (b ^ (a | ~c)) + x[11] + 0xbd3af235; /* 62 */
- d = ((d << 10) | (d >>> 22)) + a;
- c += (a ^ (d | ~b)) + x[2] + 0x2ad7d2bb; /* 63 */
- c = ((c << 15) | (c >>> 17)) + d;
- b += (d ^ (c | ~a)) + x[9] + 0xeb86d391; /* 64 */
- b = ((b << 21) | (b >>> 11)) + c;
-
- state.state[0] += a;
- state.state[1] += b;
- state.state[2] += c;
- state.state[3] += d;
+ /**
+ * Returns 32-character hex representation of this hash.
+ *
+ * @return String representation of this object's hash.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ @Override public String toString(){
+ return getHashString();
}
/**
- * Updates hash with the bytebuffer given (using at maximum length bytes
- * from that buffer)
- *
- * @param stat
- * Which state is updated
- * @param buffer
- * Array of bytes to be hashed
- * @param offset
- * Offset to buffer array
- * @param length
- * Use at maximum `length' bytes (absolute maximum is
- * buffer.length)
+ * Update this hash with the given data.
+ * <p>
+ * A state may be passed into this method so that we can add padding
+ * and finalize a md5 hash without limiting our ability to update
+ * more data later.
+ * <p>
+ * If length bytes are not available to be hashed, as many bytes as
+ * possible will be hashed.
+ *
+ * @param state Which state is updated.
+ * @param buffer Array of bytes to be hashed.
+ * @param offset Offset to buffer array.
+ * @param length number of bytes to hash.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public void Update(MD5State stat, byte buffer[], int offset, int length) {
- int index, partlen, i, start;
- finals = null;
+ private void update (MD5State state, byte buffer[], int offset, int length) {
- /* Length can be told to be shorter, but not inter */
- if ((length - offset) > buffer.length)
+ finalState.valid = false;
+
+ // if length goes beyond the end of the buffer, cut it short.
+ if ((length + offset) > buffer.length){
length = buffer.length - offset;
+ }
- /* compute number of bytes mod 64 */
+ // compute number of bytes mod 64
+ // this is what we have sitting in a buffer
+ // that have not been hashed yet
+ int index = (int) (state.bitCount >>> 3) & 0x3f;
- index = (int) (stat.count & 0x3f);
- stat.count += length;
+ // add the length to the count (translate bytes to bits)
+ state.bitCount += length << 3;
- partlen = 64 - index;
+ int partlen = 64 - index;
+ int i = 0;
if (length >= partlen) {
- if (native_lib_loaded) {
-
- // update state (using native method) to reflect input
-
- if (partlen == 64) {
- partlen = 0;
- } else {
- for (i = 0; i < partlen; i++)
- stat.buffer[i + index] = buffer[i + offset];
- Transform_native(stat.state, stat.buffer, 0, 64);
- }
- Transform_native(stat.state, buffer, partlen + offset, length
- - partlen);
- i = partlen + ((length - partlen) / 64) * 64;
- } else {
-
- // update state (using only Java) to reflect input
-
- int[] decode_buf = new int[16];
- if (partlen == 64) {
- partlen = 0;
- } else {
- for (i = 0; i < partlen; i++)
- stat.buffer[i + index] = buffer[i + offset];
- Transform(stat, stat.buffer, 0, decode_buf);
- }
- for (i = partlen; (i + 63) < length; i += 64) {
- Transform(stat, buffer, i + offset, decode_buf);
- }
+ System.arraycopy(buffer, offset, state.buffer, index, partlen);
+ transform(state, decode(state.buffer, 64, 0));
+ for (i = partlen; (i + 63) < length; i+= 64){
+ transform(state, decode(buffer, 64, i));
}
index = 0;
- } else
- i = 0;
+ }
- /* buffer remaining input */
+ // buffer remaining input
if (i < length) {
- start = i;
- for (; i < length; i++) {
- stat.buffer[index + i - start] = buffer[i + offset];
+ for (int start = i; i < length; i++) {
+ state.buffer[index + i - start] = buffer[i + offset];
}
}
}
- /*
- * Update()s for other datatypes than byte[] also. Update(byte[], int)
- * is only the main driver.
+ /**
+ * Update this hash with the given data.
+ * <p>
+ * If length bytes are not available to be hashed, as many bytes as
+ * possible will be hashed.
+ *
+ * @param buffer Array of bytes to be hashed.
+ * @param offset Offset to buffer array.
+ * @param length number of bytes to hash.
+ *
+ * @since ostermillerutils 1.00.00
*/
+ public void update (byte buffer[], int offset, int length) {
+ update(workingState, buffer, offset, length);
+ }
/**
- * Plain update, updates this object
+ * Update this hash with the given data.
+ * <p>
+ * If length bytes are not available to be hashed, as many bytes as
+ * possible will be hashed.
+ *
+ * @param buffer Array of bytes to be hashed.
+ * @param length number of bytes to hash.
+ *
+ * @since ostermillerutils 1.00.00
*/
-
- public void Update(byte buffer[], int offset, int length) {
- Update(this.state, buffer, offset, length);
+ public void update (byte buffer[], int length) {
+ update(buffer, 0, length);
}
- public void Update(byte buffer[], int length) {
- Update(this.state, buffer, 0, length);
- }
-
/**
- * Updates hash with given array of bytes
- *
- * @param buffer
- * Array of bytes to use for updating the hash
+ * Update this hash with the given data.
+ *
+ * @param buffer Array of bytes to be hashed.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public void Update(byte buffer[]) {
- Update(buffer, 0, buffer.length);
+ public void update (byte buffer[]) {
+ update(buffer, 0, buffer.length);
}
/**
- * Updates hash with a single byte
- *
- * @param b
- * Single byte to update the hash
+ * Updates this hash with a single byte.
+ *
+ * @param b byte to be hashed.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public void Update(byte b) {
+ public void update (byte b) {
byte buffer[] = new byte[1];
buffer[0] = b;
-
- Update(buffer, 1);
+ update(buffer, 1);
}
/**
- * Update buffer with given string. Note that because the version of the
- * s.getBytes() method without parameters is used to convert the string to a
- * byte array, the results of this method may be different on different
- * platforms. The s.getBytes() method converts the string into a byte array
- * using the current platform's default character set and may therefore have
- * different results on platforms with different default character sets. If
- * a version that works consistently across platforms with different default
- * character sets is desired, use the overloaded version of the Update()
- * method which takes a string and a character encoding.
- *
- * @param s
- * String to be update to hash (is used as s.getBytes())
+ * Update this hash with a String.
+ * The string is converted to bytes using the current
+ * platform's default character encoding.
+ *
+ * @param s String to be hashed.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public void Update(String s) {
- byte chars[] = s.getBytes();
- Update(chars, chars.length);
+ public void update (String s) {
+ update(s.getBytes());
}
/**
- * Update buffer with given string using the given encoding. If the given
- * encoding is null, the encoding "ISO8859_1" is used.
- *
- * @param s
- * String to be update to hash (is used as
- * s.getBytes(charset_name))
- * @param charset_name
- * The character set to use to convert s to a byte array, or null
- * if the "ISO8859_1" character set is desired.
- * @exception java.io.UnsupportedEncodingException
- * If the named charset is not supported.
+ * Update this hash with a String.
+ *
+ * @param s String to be hashed.
+ * @param enc The name of a supported character encoding.
+ * @throws UnsupportedEncodingException If the named encoding is not supported.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public void Update(String s, String charset_name)
- throws java.io.UnsupportedEncodingException {
- if (charset_name == null)
- charset_name = "ISO8859_1";
- byte chars[] = s.getBytes(charset_name);
- Update(chars, chars.length);
+ public void update (String s, String enc) throws UnsupportedEncodingException {
+ update(s.getBytes(enc));
}
/**
- * Update buffer with a single integer (only & 0xff part is used, as a byte)
- *
- * @param i
- * Integer value, which is then converted to byte as i & 0xff
+ * The current state from which the hash sum
+ * can be computed or updated.
+ *
+ * @since ostermillerutils 1.00.00
*/
+ private MD5State workingState = new MD5State();
- public void Update(int i) {
- Update((byte) (i & 0xff));
- }
+ /**
+ * Cached copy of the final MD5 hash sum. This is created when
+ * the hash is requested and it is invalidated when the hash
+ * is updated.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ private MD5State finalState = new MD5State();
- private byte[] Encode(int input[], int len) {
- int i, j;
- byte out[];
+ /**
+ * Temporary buffer cached here for performance reasons.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ private int[] decodeBuffer = new int[16];
- out = new byte[len];
+ /**
+ * 64 bytes of padding that can be added if the length
+ * is not divisible by 64.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ private static final byte padding[] = {
+ (byte) 0x80, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
- for (i = j = 0; j < len; i++, j += 4) {
- out[j] = (byte) (input[i] & 0xff);
- out[j + 1] = (byte) ((input[i] >>> 8) & 0xff);
- out[j + 2] = (byte) ((input[i] >>> 16) & 0xff);
- out[j + 3] = (byte) ((input[i] >>> 24) & 0xff);
- }
-
- return out;
- }
-
/**
- * Returns array of bytes (16 bytes) representing hash as of the current
- * state of this object. Note: getting a hash does not invalidate the hash
- * object, it only creates a copy of the real state which is finalized.
- *
- * @return Array of 16 bytes, the hash of all updated bytes
+ * Contains internal state of the MD5 class.
+ * Passes MD5 test suite as defined in RFC1321.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public synchronized byte[] Final() {
- byte bits[];
- int index, padlen;
- MD5State fin;
+ private class MD5State {
- if (finals == null) {
- fin = new MD5State(state);
+ /**
+ * True if this state is valid.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ private boolean valid = true;
- int[] count_ints = { (int) (fin.count << 3),
- (int) (fin.count >> 29) };
- bits = Encode(count_ints, 8);
+ /**
+ * Reset to initial state.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ private void reset(){
+ state[0] = 0x67452301;
+ state[1] = 0xefcdab89;
+ state[2] = 0x98badcfe;
+ state[3] = 0x10325476;
- index = (int) (fin.count & 0x3f);
- padlen = (index < 56) ? (56 - index) : (120 - index);
+ bitCount = 0;
+ }
- Update(fin, padding, 0, padlen);
- Update(fin, bits, 0, 8);
+ /**
+ * 128-byte state
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ private int state[] = new int[4];
- /* Update() sets finals to null */
- finals = fin;
+ /**
+ * 64-bit count of the number of bits that have been hashed.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ private long bitCount;
+
+ /**
+ * 64-byte buffer (512 bits) for storing to-be-hashed characters
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ private byte buffer[] = new byte[64];
+
+ private MD5State() {
+ reset();
}
- return Encode(finals.state, 16);
+ /**
+ * Set this state to be exactly the same as some other.
+ *
+ * @param from state to copy from.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ private void copy(MD5State from) {
+ System.arraycopy(from.buffer, 0, this.buffer, 0, this.buffer.length);
+ System.arraycopy(from.state, 0, this.state, 0, this.state.length);
+ this.valid = from.valid;
+ this.bitCount = from.bitCount;
+ }
}
- private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5',
- '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', };
/**
- * Turns array of bytes into string representing each byte as unsigned hex
- * number.
- *
- * @param hash
- * Array of bytes to convert to hex-string
- * @return Generated hex string
+ * Turns array of bytes into string representing each byte as
+ * a two digit unsigned hex number.
+ *
+ * @param hash Array of bytes to convert to hex-string
+ * @return Generated hex string
+ *
+ * @since ostermillerutils 1.00.00
*/
- public static String asHex(byte hash[]) {
- char buf[] = new char[hash.length * 2];
- for (int i = 0, x = 0; i < hash.length; i++) {
- buf[x++] = HEX_CHARS[(hash[i] >>> 4) & 0xf];
- buf[x++] = HEX_CHARS[hash[i] & 0xf];
+ private static String toHex(byte hash[]){
+ StringBuffer buf = new StringBuffer(hash.length * 2);
+ for (byte element: hash) {
+ int intVal = element & 0xff;
+ if (intVal < 0x10){
+ // append a zero before a one digit hex
+ // number to make it two digits.
+ buf.append("0");
+ }
+ buf.append(Integer.toHexString(intVal));
}
- return new String(buf);
+ return buf.toString();
}
- /**
- * Returns 32-character hex representation of this objects hash
- *
- * @return String of this object's hash
- */
- public String asHex() {
- return asHex(this.Final());
+ private static int FF (int a, int b, int c, int d, int x, int s, int ac) {
+ a += ((b & c) | (~b & d));
+ a += x;
+ a += ac;
+ //return rotateLeft(a, s) + b;
+ a = (a << s) | (a >>> (32 - s));
+ return a + b;
}
- public static synchronized final void initNativeLibrary(
- boolean disallow_lib_loading) {
- if (disallow_lib_loading) {
- native_lib_init_pending = false;
- } else {
- _initNativeLibrary();
- }
+ private static int GG (int a, int b, int c, int d, int x, int s, int ac) {
+ a += ((b & d) | (c & ~d));
+ a += x;
+ a += ac;
+ //return rotateLeft(a, s) + b;
+ a = (a << s) | (a >>> (32 - s));
+ return a + b;
}
- private static synchronized final void _initNativeLibrary() {
- if (!native_lib_init_pending)
- return;
- native_lib_loaded = _loadNativeLibrary();
- native_lib_init_pending = false;
+ private static int HH (int a, int b, int c, int d, int x, int s, int ac) {
+ a += (b ^ c ^ d);
+ a += x;
+ a += ac;
+ //return rotateLeft(a, s) + b;
+ a = (a << s) | (a >>> (32 - s));
+ return a + b;
}
- private static synchronized final boolean _loadNativeLibrary() {
- try {
+ private static int II (int a, int b, int c, int d, int x, int s, int ac) {
+ a += (c ^ (b | ~d));
+ a += x;
+ a += ac;
+ //return rotateLeft(a, s) + b;
+ a = (a << s) | (a >>> (32 - s));
+ return a + b;
+ }
- // don't try to load if the right property is set
+ private static byte[] encode(long l){
+ byte[] out = new byte[8];
+ out[0] = (byte) (l & 0xff);
+ out[1] = (byte) ((l >>> 8) & 0xff);
+ out[2] = (byte) ((l >>> 16) & 0xff);
+ out[3] = (byte) ((l >>> 24) & 0xff);
+ out[4] = (byte) ((l >>> 32) & 0xff);
+ out[5] = (byte) ((l >>> 40) & 0xff);
+ out[6] = (byte) ((l >>> 48) & 0xff);
+ out[7] = (byte) ((l >>> 56) & 0xff);
+ return out;
+ }
- String prop = System
- .getProperty("com.twmacinta.util.MD5.NO_NATIVE_LIB");
- if (prop != null) {
- prop = prop.trim();
- if (prop.equalsIgnoreCase("true") || prop.equals("1"))
- return false;
- }
+ private static byte[] encode(int input[], int len){
+ byte[] out = new byte[len];
+ int i, j;
+ for (i = j = 0; j < len; i++, j += 4) {
+ out[j] = (byte) (input[i] & 0xff);
+ out[j + 1] = (byte) ((input[i] >>> 8) & 0xff);
+ out[j + 2] = (byte) ((input[i] >>> 16) & 0xff);
+ out[j + 3] = (byte) ((input[i] >>> 24) & 0xff);
+ }
+ return out;
+ }
- // the library to load can be specified as a property
+ private int[] decode(byte buffer[], int len, int offset){
+ int i, j;
+ for (i = j = 0; j < len; i++, j += 4) {
+ decodeBuffer[i] = (
+ (buffer[j + offset] & 0xff)) |
+ (((buffer[j + 1 + offset] & 0xff)) << 8) |
+ (((buffer[j + 2 + offset] & 0xff)) << 16) |
+ (((buffer[j + 3 + offset] & 0xff)) << 24
+ );
+ }
+ return decodeBuffer;
+ }
- File f;
- prop = System.getProperty("com.twmacinta.util.MD5.NATIVE_LIB_FILE");
- if (prop != null) {
- f = new File(prop);
- if (f.canRead()) {
- System.load(f.getAbsolutePath());
- return true;
- }
- }
+ private static void transform(MD5State state, int[] x){
+ int a = state.state[0];
+ int b = state.state[1];
+ int c = state.state[2];
+ int d = state.state[3];
- // determine the operating system and architecture
+ /* Round 1 */
+ a = FF (a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */
+ d = FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
+ c = FF (c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
+ b = FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
+ a = FF (a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
+ d = FF (d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
+ c = FF (c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
+ b = FF (b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
+ a = FF (a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
+ d = FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
+ c = FF (c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
+ b = FF (b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
+ a = FF (a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
+ d = FF (d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
+ c = FF (c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
+ b = FF (b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
- String os_name = System.getProperty("os.name");
- String os_arch = System.getProperty("os.arch");
- if (os_name == null || os_arch == null)
- return false;
- os_name = os_name.toLowerCase();
- os_arch = os_arch.toLowerCase();
+ /* Round 2 */
+ a = GG (a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */
+ d = GG (d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
+ c = GG (c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
+ b = GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
+ a = GG (a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
+ d = GG (d, a, b, c, x[10], 9, 0x02441453); /* 22 */
+ c = GG (c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
+ b = GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
+ a = GG (a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
+ d = GG (d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
+ c = GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
+ b = GG (b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
+ a = GG (a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
+ d = GG (d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
+ c = GG (c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
+ b = GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
- // define settings which are OS arch architecture independent
+ /* Round 3 */
+ a = HH (a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */
+ d = HH (d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
+ c = HH (c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
+ b = HH (b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
+ a = HH (a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
+ d = HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
+ c = HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
+ b = HH (b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
+ a = HH (a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
+ d = HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
+ c = HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
+ b = HH (b, c, d, a, x[ 6], 23, 0x04881d05); /* 44 */
+ a = HH (a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
+ d = HH (d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
+ c = HH (c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
+ b = HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
- File arch_lib_path = null;
- String arch_libfile_suffix = null;
+ /* Round 4 */
+ a = II (a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */
+ d = II (d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
+ c = II (c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
+ b = II (b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
+ a = II (a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
+ d = II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
+ c = II (c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
+ b = II (b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
+ a = II (a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
+ d = II (d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
+ c = II (c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
+ b = II (b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
+ a = II (a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
+ d = II (d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
+ c = II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
+ b = II (b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
- // fill in settings for Linux on x86
-
- if (os_name.equals("linux")
- && (os_arch.equals("x86") || os_arch.equals("i386")
- || os_arch.equals("i486") || os_arch.equals("i586") || os_arch
- .equals("i686"))) {
- arch_lib_path = new File(new File(new File("lib"), "arch"),
- "linux_x86");
- arch_libfile_suffix = ".so";
-
- // fill in settings for Windows on x86
-
- } else if (os_name.startsWith("windows ")
- && (os_arch.equals("x86") || os_arch.equals("i386")
- || os_arch.equals("i486") || os_arch.equals("i586") || os_arch
- .equals("i686"))) {
- arch_lib_path = new File(new File(new File("lib"), "arch"),
- "win32_x86");
- arch_libfile_suffix = ".dll";
-
- // fill in settings Mac OS X on PPC
-
- } else if (os_name.startsWith("mac os x")
- && (os_arch.equals("ppc"))) {
- arch_lib_path = new File(new File(new File("lib"), "arch"),
- "darwin_ppc");
- arch_libfile_suffix = ".jnilib";
-
- // default to .so files with no architecture specific
- // subdirectory
-
- } else {
- arch_libfile_suffix = ".so";
- }
-
- // build the required filename
-
- String fname = "MD5" + arch_libfile_suffix;
-
- // try the architecture specific directory
-
- if (arch_lib_path != null) {
- f = new File(arch_lib_path, fname);
- if (f.canRead()) {
- System.load(f.getAbsolutePath());
- return true;
- }
- }
-
- // try the "lib" subdirectory
-
- f = new File(new File("lib"), fname);
- if (f.canRead()) {
- System.load(f.getAbsolutePath());
- return true;
- }
-
- // try the working directory
-
- f = new File(fname);
- if (f.canRead()) {
- System.load(f.getAbsolutePath());
- return true;
- }
-
- // discard SecurityExceptions
-
- } catch (SecurityException e) {
- }
-
- // unable to load
-
- return false;
+ state.state[0] += a;
+ state.state[1] += b;
+ state.state[2] += c;
+ state.state[3] += d;
}
-
- /**
- * Calculates and returns the hash of the contents of the given file.
- */
- public static byte[] getHash(File f) throws IOException {
- if (!f.exists())
- throw new FileNotFoundException(f.toString());
- InputStream close_me = null;
- try {
- long buf_size = f.length();
- if (buf_size < 512)
- buf_size = 512;
- if (buf_size > 65536)
- buf_size = 65536;
- byte[] buf = new byte[(int) buf_size];
- MD5InputStream in = new MD5InputStream(new FileInputStream(f));
- close_me = in;
- while (in.read(buf) != -1)
- ;
- in.close();
- return in.hash();
- } catch (IOException e) {
- if (close_me != null)
- try {
- close_me.close();
- } catch (Exception e2) {
- }
- throw e;
- }
- }
-
- /**
- * @return true iff the first 16 bytes of both hash1 and hash2 are equal;
- * both hash1 and hash2 are null; or either hash array is less than
- * 16 bytes in length and their lengths and all of their bytes are
- * equal.
- */
- public static boolean hashesEqual(byte[] hash1, byte[] hash2) {
- if (hash1 == null)
- return hash2 == null;
- if (hash2 == null)
- return false;
- int targ = 16;
- if (hash1.length < 16) {
- if (hash2.length != hash1.length)
- return false;
- targ = hash1.length;
- } else if (hash2.length < 16) {
- return false;
- }
- for (int i = 0; i < targ; i++) {
- if (hash1[i] != hash2[i])
- return false;
- }
- return true;
- }
-
}
Modified: lutinutil/trunk/src/main/java/org/codelutin/util/MD5InputStream.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/MD5InputStream.java 2009-04-24 16:18:13 UTC (rev 1447)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/MD5InputStream.java 2009-04-28 16:59:51 UTC (rev 1448)
@@ -1,210 +1,131 @@
-/**
- * *##% Lutin utilities library
- * Copyright (C) 2004 - 2008 CodeLutin
+/*
+ * Implements MD5 functionality on a stream.
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
+ * written Santeri Paavolainen, Helsinki Finland 1996
+ * (c) Santeri Paavolainen, Helsinki Finland 1996
+ * modifications Copyright (C) 2002 Stephen Ostermiller
+ * http://ostermiller.org/contact.pl?regarding=Java+Utilities
*
+ * This program 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.
+ *
* This program 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 Lesser Public License for more details.
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Lesser Public
- * License along with this program. If not, see
- * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*
+ * See COPYING.TXT for details.
+ *
+ * The original work by Santeri Paavolainen can be found a
+ * http://www.helsinki.fi/~sjpaavol/programs/md5/
*/
package org.codelutin.util;
-import java.io.BufferedInputStream;
-import java.io.FileInputStream;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
/**
- * MD5InputStream, a subclass of FilterInputStream implementing MD5
- * functionality on a stream.
+ * Implements MD5 functionality on a stream.
+ * More information about this class is available from <a target="_top" href=
+ * "http://ostermiller.org/utils/MD5.html">ostermiller.org</a>.
* <p>
- * Originally written by Santeri Paavolainen, Helsinki Finland 1996 <br>
- * (c) Santeri Paavolainen, Helsinki Finland 1996 <br>
- * Some changes Copyright (c) 2002 Timothy W Macinta <br>
+ * This class produces a 128-bit "fingerprint" or "message digest" for
+ * all data read from this stream.
+ * It is conjectured that it is computationally infeasible to produce
+ * two messages having the same message digest, or to produce any
+ * message having a given pre-specified target message digest. The MD5
+ * algorithm is intended for digital signature applications, where a
+ * large file must be "compressed" in a secure manner before being
+ * encrypted with a private (secret) key under a public-key cryptosystem
+ * such as RSA.
* <p>
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; either version 2.1 of the License, or (at your option)
- * any later version.
- * <p>
- * This library 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 Library General Public License for more
- * details.
- * <p>
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- * <p>
- * See http://www.twmacinta.com/myjava/fast_md5.php for more information on this
- * file.
- * <p>
- * Please note: I (Timothy Macinta) have put this code in the com.twmacinta.util
- * package only because it came without a package. I was not the the original
- * author of the code, although I did optimize it (substantially) and fix some
- * bugs.
- *
- * @author Santeri Paavolainen <santtu(a)cs.hut.fi>
- * @author Timothy W Macinta (twm(a)alum.mit.edu) (added main() method)
+ * For more information see RFC1321.
+ *
+ * @see MD5
+ * @see MD5OutputStream
+ *
+ * @author Santeri Paavolainen http://www.helsinki.fi/~sjpaavol/programs/md5/
+ * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
+ * @since ostermillerutils 1.00.00
*/
-
public class MD5InputStream extends FilterInputStream {
/**
* MD5 context
*/
private MD5 md5;
-
- /** The stream length. */
- private long streamLength;
/**
* Creates a MD5InputStream
- *
- * @param in
- * The input stream
+ * @param in the underlying input stream
*/
- public MD5InputStream(InputStream in) {
+ public MD5InputStream (InputStream in) {
super(in);
-
md5 = new MD5();
- streamLength = 0;
}
/**
- * Read a byte of data.
- *
- * @see java.io.FilterInputStream
+ * Reads the next byte of data from this input stream. The value byte
+ * is returned as an int in the range 0 to 255. If no byte is available
+ * because the end of the stream has been reached, the value -1 is returned.
+ * This method blocks until input data is available, the end of the stream is
+ * detected, or an exception is thrown.
+ * <p>
+ * This method simply performs in.read() and returns the result.
+ *
+ * @return the next byte of data, or -1 if the end of the stream is reached.
+ * @throws IOException if an I/O error occurs.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public int read() throws IOException {
+ @Override public int read() throws IOException {
int c = in.read();
-
- if (c == -1)
+ if (c == -1) {
return -1;
-
- if ((c & ~0xff) != 0) {
- System.out
- .println("MD5InputStream.read() got character with (c & ~0xff) != 0)!");
- } else {
- streamLength++;
- md5.Update(c);
}
-
+ md5.update((byte)(c & 0xff));
return c;
- }
+}
/**
- * Reads into an array of bytes.
- *
- * @see java.io.FilterInputStream
+ * Reads up to length bytes of data from this input stream into an
+ * array of bytes. This method blocks until some input is available.
+ *
+ * @param bytes the buffer into which the data is read.
+ * @param offset the start offset of the data.
+ * @param length the maximum number of bytes read.
+ * @throws IOException if an I/O error occurs.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public int read(byte bytes[], int offset, int length) throws IOException {
+ @Override public int read(byte[] bytes, int offset, int length) throws IOException {
int r;
-
- if ((r = in.read(bytes, offset, length)) == -1)
+ if ((r = in.read(bytes, offset, length)) == -1) {
return r;
-
- streamLength += r;
- md5.Update(bytes, offset, r);
-
+ }
+ md5.update(bytes, offset, r);
return r;
}
/**
- * Returns array of bytes representing hash of the stream as finalized for
- * the current state.
- *
- * @see MD5#Final
+ * Returns array of bytes representing hash of the stream so far.
+ *
+ * @return Array of 16 bytes, the hash of all read bytes.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public byte[] hash() {
- return md5.Final();
+ public byte[] getHash(){
+ return md5.getHash();
}
- public MD5 getMD5() {
- return md5;
- }
-
- public long getStreamLength() {
- return streamLength;
- }
-
/**
- * This method is here for testing purposes only - do not rely on it being
- * here.
+ * Get a 32-character hex representation representing hash of the stream so far.
+ *
+ * @return A string containing the hash of all written bytes.
+ *
+ * @since ostermillerutils 1.00.00
*/
- public static void main(String[] arg) {
- try {
-
- // //////////////////////////////////////////////////////////////
- //
- // usage: java com.twmacinta.util.MD5InputStream [--use-default-md5]
- // [--no-native-lib] filename
- //
- // ///////
-
- // determine the filename to use and the MD5 impelementation to use
-
- String filename = arg[arg.length - 1];
- boolean use_default_md5 = false;
- boolean use_native_lib = true;
- for (int i = 0; i < arg.length - 1; i++) {
- if (arg[i].equals("--use-default-md5")) {
- use_default_md5 = true;
- } else if (arg[i].equals("--no-native-lib")) {
- use_native_lib = false;
- }
- }
-
- // initialize common variables
-
- byte[] buf = new byte[65536];
- int num_read;
-
- // Use the default MD5 implementation that comes with Java
-
- if (use_default_md5) {
- InputStream in = new BufferedInputStream(new FileInputStream(
- filename));
- java.security.MessageDigest digest = java.security.MessageDigest
- .getInstance("MD5");
- while ((num_read = in.read(buf)) != -1) {
- digest.update(buf, 0, num_read);
- }
- System.out
- .println(MD5.asHex(digest.digest()) + " " + filename);
- in.close();
-
- // Use the optimized MD5 implementation
-
- } else {
-
- // disable the native library search, if requested
-
- if (!use_native_lib) {
- MD5.initNativeLibrary(true);
- }
-
- // calculate the checksum
-
- MD5InputStream in = new MD5InputStream(new BufferedInputStream(
- new FileInputStream(filename)));
- while ((num_read = in.read(buf)) != -1)
- ;
- System.out.println(MD5.asHex(in.hash()) + " " + filename);
- in.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
+ public String getHashString(){
+ return md5.getHashString();
}
-
}
Added: lutinutil/trunk/src/main/java/org/codelutin/util/MD5OutputStream.java
===================================================================
--- lutinutil/trunk/src/main/java/org/codelutin/util/MD5OutputStream.java (rev 0)
+++ lutinutil/trunk/src/main/java/org/codelutin/util/MD5OutputStream.java 2009-04-28 16:59:51 UTC (rev 1448)
@@ -0,0 +1,120 @@
+/*
+ * Implements MD5 functionality on a stream.
+ *
+ * written Santeri Paavolainen, Helsinki Finland 1996
+ * (c) Santeri Paavolainen, Helsinki Finland 1996
+ * modifications Copyright (C) 2002 Stephen Ostermiller
+ * http://ostermiller.org/contact.pl?regarding=Java+Utilities
+ *
+ * This program 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.
+ *
+ * This program 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.
+ *
+ * See COPYING.TXT for details.
+ *
+ * The original work by Santeri Paavolainen can be found a
+ * http://www.helsinki.fi/~sjpaavol/programs/md5/
+ */
+package org.codelutin.util;
+
+import java.io.*;
+
+/**
+ * Implements MD5 functionality on a stream.
+ * More information about this class is available from <a target="_top" href=
+ * "http://ostermiller.org/utils/MD5.html">ostermiller.org</a>.
+ * <p>
+ * This class produces a 128-bit "fingerprint" or "message digest" for
+ * all data written to this stream.
+ * It is conjectured that it is computationally infeasible to produce
+ * two messages having the same message digest, or to produce any
+ * message having a given pre-specified target message digest. The MD5
+ * algorithm is intended for digital signature applications, where a
+ * large file must be "compressed" in a secure manner before being
+ * encrypted with a private (secret) key under a public-key cryptosystem
+ * such as RSA.
+ * <p>
+ * For more information see RFC1321.
+ *
+ * @see MD5
+ * @see MD5InputStream
+ *
+ * @author Santeri Paavolainen http://www.helsinki.fi/~sjpaavol/programs/md5/
+ * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
+ * @since ostermillerutils 1.00.00
+ */
+public class MD5OutputStream extends FilterOutputStream {
+
+ /**
+ * MD5 context
+ */
+ private MD5 md5;
+
+ /**
+ * Creates MD5OutputStream
+ * @param out The output stream
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public MD5OutputStream(OutputStream out) {
+ super(out);
+ md5 = new MD5();
+ }
+
+ /**
+ * Writes the specified byte to this output stream.
+ *
+ * @param b the byte.
+ * @throws IOException if an I/O error occurs.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ @Override public void write(int b) throws IOException {
+ out.write(b);
+ md5.update((byte)(b & 0xff));
+ }
+
+ /**
+ * Writes length bytes from the specified byte array starting a
+ * offset off to this output stream.
+ *
+ * @param b the data.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @throws IOException if an I/O error occurs.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ @Override public void write(byte b[], int off, int len) throws IOException {
+ out.write(b, off, len);
+ md5.update(b, off, len);
+ }
+
+ /**
+ * Returns array of bytes representing hash of the stream so far.
+ *
+ * @return Array of 16 bytes, the hash of all written bytes.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public byte[] getHash(){
+ return md5.getHash();
+ }
+
+ /**
+ * Get a 32-character hex representation representing hash of the stream so far.
+ *
+ * @return A string containing the hash of all written bytes.
+ *
+ * @since ostermillerutils 1.00.00
+ */
+ public String getHashString(){
+ return md5.getHashString();
+ }
+}
\ No newline at end of file
1
0
[Lutinutil-commits] r1447 - lutinutil/trunk/src/test/java/org/codelutin/util
by chatellier@users.labs.libre-entreprise.org 24 Apr '09
by chatellier@users.labs.libre-entreprise.org 24 Apr '09
24 Apr '09
Author: chatellier
Date: 2009-04-24 16:18:13 +0000 (Fri, 24 Apr 2009)
New Revision: 1447
Modified:
lutinutil/trunk/src/test/java/org/codelutin/util/RecursivePropertiesTest.java
Log:
Fix imports
Modified: lutinutil/trunk/src/test/java/org/codelutin/util/RecursivePropertiesTest.java
===================================================================
--- lutinutil/trunk/src/test/java/org/codelutin/util/RecursivePropertiesTest.java 2009-04-24 16:17:54 UTC (rev 1446)
+++ lutinutil/trunk/src/test/java/org/codelutin/util/RecursivePropertiesTest.java 2009-04-24 16:18:13 UTC (rev 1447)
@@ -19,7 +19,6 @@
package org.codelutin.util;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
import org.junit.Assert;
1
0