X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.util%2Fsrc%2Forg%2Fargeo%2Futil%2FDigestUtils.java;h=e1a19160bd5a04afe23f834b6556e41bf53d91dd;hb=00baea7c5c7bdddf6dd5aa1fae8edaf2ed7a6400;hp=52cbc5d21a3b801885a88555c1ad9d88463938b2;hpb=77a5498dd5d10d2442127022efd6501a7dbddbae;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.util/src/org/argeo/util/DigestUtils.java b/org.argeo.util/src/org/argeo/util/DigestUtils.java index 52cbc5d21..e1a19160b 100644 --- a/org.argeo.util/src/org/argeo/util/DigestUtils.java +++ b/org.argeo.util/src/org/argeo/util/DigestUtils.java @@ -1,47 +1,58 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package org.argeo.util; +import static org.argeo.util.BytesUtils.toHexString; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; +import java.nio.channels.FileChannel.MapMode; +import java.nio.file.Files; +import java.nio.file.Path; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** Utilities around cryptographic digests */ public class DigestUtils { - private static Boolean debug = true; - // TODO: make it writable + public final static String MD5 = "MD5"; + public final static String SHA1 = "SHA1"; + public final static String SHA256 = "SHA-256"; + public final static String SHA512 = "SHA-512"; + + private static Boolean debug = false; + // TODO: make it configurable private final static Integer byteBufferCapacity = 100 * 1024;// 100 KB - public static String digest(String algorithm, byte[] bytes) { + public static byte[] sha1(byte[]... bytes) { + try { + MessageDigest digest = MessageDigest.getInstance(SHA1); + for (byte[] arr : bytes) + digest.update(arr); + byte[] checksum = digest.digest(); + return checksum; + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException("SHA1 is not avalaible", e); + } + } + + public static byte[] digestAsBytes(String algorithm, byte[]... bytes) { try { MessageDigest digest = MessageDigest.getInstance(algorithm); - digest.update(bytes); + for (byte[] arr : bytes) + digest.update(arr); byte[] checksum = digest.digest(); - String res = encodeHexString(checksum); - return res; - } catch (Exception e) { - throw new UtilsException("Cannot digest with algorithm " + algorithm, e); + return checksum; + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException("Cannot digest with algorithm " + algorithm, e); } } + public static String digest(String algorithm, byte[]... bytes) { + return toHexString(digestAsBytes(algorithm, bytes)); + } + public static String digest(String algorithm, InputStream in) { try { MessageDigest digest = MessageDigest.getInstance(algorithm); @@ -56,10 +67,12 @@ public class DigestUtils { } byte[] checksum = digest.digest(); - String res = encodeHexString(checksum); + String res = toHexString(checksum); return res; - } catch (Exception e) { - throw new UtilsException("Cannot digest with algorithm " + algorithm, e); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm, e); + } catch (IOException e) { + throw new RuntimeException(e); } finally { StreamUtils.closeQuietly(in); } @@ -77,7 +90,7 @@ public class DigestUtils { ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz); return digest(algorithm, bb); } catch (IOException e) { - throw new UtilsException("Cannot digest " + file + " with algorithm " + algorithm, e); + throw new IllegalArgumentException("Cannot digest " + file + " with algorithm " + algorithm, e); } finally { StreamUtils.closeQuietly(fis); if (fc.isOpen()) @@ -95,13 +108,57 @@ public class DigestUtils { MessageDigest digest = MessageDigest.getInstance(algorithm); digest.update(bb); byte[] checksum = digest.digest(); - String res = encodeHexString(checksum); + String res = toHexString(checksum); long end = System.currentTimeMillis(); if (debug) System.out.println((end - begin) + " ms / " + ((end - begin) / 1000) + " s"); return res; } catch (NoSuchAlgorithmException e) { - throw new UtilsException("Cannot digest with algorithm " + algorithm, e); + throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm, e); + } + } + + public static String sha1hex(Path path) { + return digest(SHA1, path, byteBufferCapacity); + } + + public static String digest(String algorithm, Path path, long bufferSize) { + byte[] digest = digestAsBytes(algorithm, path, bufferSize); + return toHexString(digest); + } + + public static byte[] digestAsBytes(String algorithm, Path file, long bufferSize) { + long begin = System.currentTimeMillis(); + try { + MessageDigest md = MessageDigest.getInstance(algorithm); + FileChannel fc = FileChannel.open(file); + long fileSize = Files.size(file); + if (fileSize <= bufferSize) { + ByteBuffer bb = fc.map(MapMode.READ_ONLY, 0, fileSize); + md.update(bb); + } else { + long lastCycle = (fileSize / bufferSize) - 1; + long position = 0; + for (int i = 0; i <= lastCycle; i++) { + ByteBuffer bb; + if (i != lastCycle) { + bb = fc.map(MapMode.READ_ONLY, position, bufferSize); + position = position + bufferSize; + } else { + bb = fc.map(MapMode.READ_ONLY, position, fileSize - position); + position = fileSize; + } + md.update(bb); + } + } + long end = System.currentTimeMillis(); + if (debug) + System.out.println((end - begin) + " ms / " + ((end - begin) / 1000) + " s"); + return md.digest(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Cannot digest " + file + " with algorithm " + algorithm, e); + } catch (IOException e) { + throw new RuntimeException("Cannot digest " + file + " with algorithm " + algorithm, e); } } @@ -123,6 +180,7 @@ public class DigestUtils { System.out.println(algorithm + ": " + digest(algorithm, file)); algorithm = "SHA"; System.out.println(algorithm + ": " + digest(algorithm, file)); + System.out.println(algorithm + ": " + sha1hex(file.toPath())); algorithm = "SHA-256"; System.out.println(algorithm + ": " + digest(algorithm, file)); algorithm = "SHA-512"; @@ -130,21 +188,10 @@ public class DigestUtils { } } - final private static char[] hexArray = "0123456789ABCDEF".toCharArray(); - - /** - * From - * http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to - * -a-hex-string-in-java - */ - private static String encodeHexString(byte[] bytes) { - char[] hexChars = new char[bytes.length * 2]; - for (int j = 0; j < bytes.length; j++) { - int v = bytes[j] & 0xFF; - hexChars[j * 2] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); + /** @deprecated Use {@link BytesUtils#toHexString(byte[])} instead */ + @Deprecated + public static String encodeHexString(byte[] bytes) { + return BytesUtils.toHexString(bytes); } }