package cologne.eck.peafactory.crypto;
/*
* Peafactory - Production of Password Encryption Archives
* Copyright (C) 2015 Axel von dem Bruch
*
* This library 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 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 General Public License for more details.
* See: http://www.gnu.org/licenses/gpl-2.0.html
* You should have received a copy of the GNU General Public License
* along with this library.
*/
/**
* Handles hash functions.
*/
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.generators.HKDFBytesGenerator;
import org.bouncycastle.crypto.params.HKDFParameters;
import cologne.eck.all_peas.data.PeaProperties;
import cologne.eck.tools.Comparator;
import cologne.eck.tools.Zeroizer;
public class HashStuff {
private static Digest hashAlgo;
// use another instance for HMac
// this must not be the same instance as for other hashes: HMac does not
// reset the Digest instead it updates the Digest with inputPad...
private static Digest hmacDigest = null;
/**
* Performs a hash function and clears the input immediately
*
* @param input the input to hash
* @return the output of the hash function
*/
public static final byte[] hashAndOverwrite(byte[] input) {
hashAlgo.update(input, 0, input.length);
byte[] digest = new byte[hashAlgo.getDigestSize()];
hashAlgo.doFinal(digest, 0);
hashAlgo.reset();
Zeroizer.zero(input);
return digest;
}
/**
* Perform a hash function
*
* @param input the input to hash
* @return the output of the hash function
*/
public static final byte[] hash(byte[] input) {
hashAlgo.update(input, 0, input.length);
byte[] digest = new byte[hashAlgo.getDigestSize()];
hashAlgo.doFinal(digest, 0);
hashAlgo.reset();
return digest;
}
/**
* Extract and expand keying material to required size
* using the HKDF scheme.
*
* @param input the keying material
* @param salt the salt
* @param length the required length
*
* @return the generated key of required length
*/
public static final byte[] generateHKDFBytes(byte[] input, byte[] salt, int length) {
byte[] result = new byte[length];
if (PeaProperties.getWorkingMode().equals("-t")){
Comparator.checkNullVector(input);
Comparator.checkNullVector(salt);
}
HKDFParameters hkdfParams = new HKDFParameters(
input, // keying material: seed or password
salt, // salt
null); // context variable
HKDFBytesGenerator hkdf = new HKDFBytesGenerator( hmacDigest );
hkdf.init(hkdfParams);
hkdf.generateBytes(
result, // output
0, // output offset
length); // length
// no chance to clear the password otherwise: getIKM() returns just another copy of the input
// HMac loads inputPad in reset(), so reset the underlying Digest:
hmacDigest.reset();
return result;
}
//=================
// Getter & Setter:
/**
* Get the used hash function
*
* @return the hash function
*/
public static final Digest getHashAlgo() {
return hashAlgo;
}
/**
* Set the hash function
*
* @param _hashAlgo the hash function to be used
*/
public static final void setHashAlgo(Digest _hashAlgo) {
hashAlgo = _hashAlgo;
}
/**
* Set the hash function for HMac
*
* @param _hashAlgo the hash function to be used in HMac
*/
public static final void setHMacAlgo(Digest _hashAlgo) {
hmacDigest = _hashAlgo;
}
}