/**
* Copyright 2013-2015 Seagate Technology LLC.
*
* This Source Code Form is subject to the terms of the Mozilla
* Public License, v. 2.0. If a copy of the MPL was not
* distributed with this file, You can obtain one at
* https://mozilla.org/MP:/2.0/.
*
* This program is distributed in the hope that it will be useful,
* but is provided AS-IS, WITHOUT ANY WARRANTY; including without
* the implied warranty of MERCHANTABILITY, NON-INFRINGEMENT or
* FITNESS FOR A PARTICULAR PURPOSE. See the Mozilla Public
* License for more details.
*
* See www.openkinetic.org for more project information
*/
package com.seagate.kinetic.common.lib;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import com.google.protobuf.ByteString;
import com.seagate.kinetic.proto.Kinetic.Command.Algorithm;
/**
*
* @author chiaming
*
*/
public class MessageDigestUtil {
private final static Logger logger = Logger
.getLogger(MessageDigestUtil.class.getName());
// SHA1 tag calc instance
private static KineticTagCalc sha1Algo = null;
// SHA2 tag calc instance
private static KineticTagCalc sha2Algo = null;
// CRC32 checksum instance
private static KineticTagCalc crc32 = null;
// CRC32C checksum instance
private static KineticTagCalc crc32c = null;
public static ByteString calculateTag(Algorithm algo, byte[] value) {
ByteString tag = null;
// get md instance
KineticTagCalc tagCalc = getInstance(algo);
if (value == null) {
value = new byte[0];
}
// calculate and return digest
tag = tagCalc.calculateTag(value);
return tag;
}
public static boolean isSupportedForKineticJava(Algorithm algo) {
switch (algo) {
case SHA1:
case SHA2:
case CRC32:
case CRC32C:
return true;
default:
return false;
}
}
/**
* Get SHA1 instance.
*
* @return SHA1 instance.
*/
public static KineticTagCalc getSha1Instance() {
// check if constructed
if (sha1Algo != null) {
return sha1Algo;
}
// sync
synchronized (MessageDigestUtil.class) {
// check if alread constructed
if (sha1Algo == null) {
sha1Algo = new MessageDigestTagCalc("SHA-1");
}
}
return sha1Algo;
}
/**
* Get SHA2 instance.
*
* @return SHA2 instance.
*/
public static KineticTagCalc getSha2Instance() {
// check if constructed
if (sha2Algo != null) {
return sha2Algo;
}
// sync
synchronized (MessageDigestUtil.class) {
// check if already constructed
if (sha2Algo == null) {
sha2Algo = new MessageDigestTagCalc("SHA-256");
}
}
return sha2Algo;
}
/**
* Get CRC32 instance.
*
* @return CRC32 instance.
*/
public static KineticTagCalc getCrc32Instance() {
// check if constructed
if (crc32 != null) {
return crc32;
}
// sync
synchronized (MessageDigestUtil.class) {
// check if already constructed
if (crc32 == null) {
crc32 = new Crc32TagCalc();
}
}
return crc32;
}
/**
* Get CRC32C instance.
*
* @return CRC32C instance.
*/
public static KineticTagCalc getCrc32cInstance() {
// check if constructed
if (crc32c != null) {
return crc32c;
}
// sync
synchronized (MessageDigestUtil.class) {
// check if already constructed
if (crc32c == null) {
crc32c = new Crc32cTagCalc2();
}
}
return crc32c;
}
public static KineticTagCalc getInstance(Algorithm algo) {
switch (algo) {
case SHA1:
return getSha1Instance();
case SHA2:
return getSha2Instance();
case CRC32:
return getCrc32Instance();
case CRC32C:
return getCrc32cInstance();
default:
throw new java.lang.UnsupportedOperationException(
"unsupported algorithm., name = " + algo.name());
}
}
public static MessageDigest getDigestInstance(String algoName) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance(algoName);
} catch (NoSuchAlgorithmException e) {
logger.log(Level.WARNING, e.getMessage(), e);
}
return md;
}
public static Checksum getCrc32ChecksumInstance() {
return new CRC32();
}
public ByteString calculateTag(Checksum crc, byte[] value) {
crc.update(value, 0, value.length);
long csum = crc.getValue();
ByteBuffer buffer = ByteBuffer.allocate(8);
return ByteString.copyFrom(buffer.putLong(csum).array());
}
}