org.bimserver.Authenticator Maven / Gradle / Ivy
package org.bimserver;
/******************************************************************************
* Copyright (C) 2009-2016 BIMserver.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see {@literal }.
*****************************************************************************/
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
public class Authenticator
{
public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";
public static final int SALT_BYTES = 24;
public static final int HASH_BYTES = 24;
public static final int PBKDF2_ITERATIONS = 1000;
public boolean validate(String givenPassword, byte[] hash, byte[] salt) {
try {
byte[] testHash = pbkdf2(givenPassword.toCharArray(), salt, PBKDF2_ITERATIONS, hash.length);
return slowEquals(hash, testHash);
} catch (NoSuchAlgorithmException e) {
return false;
} catch (InvalidKeySpecException e) {
return false;
}
}
/**
* Compares two byte arrays in length-constant time. This comparison method
* is used so that password hashes cannot be extracted from an on-line
* system using a timing attack and then attacked off-line.
*
* @param a the first byte array
* @param b the second byte array
* @return true if both byte arrays are the same, false if not
*/
private static boolean slowEquals(byte[] a, byte[] b)
{
int diff = a.length ^ b.length;
for(int i = 0; i < a.length && i < b.length; i++)
diff |= a[i] ^ b[i];
return diff == 0;
}
/**
* Computes the PBKDF2 hash of a password.
*
* @param password the password to hash.
* @param salt the salt
* @param iterations the iteration count (slowness factor)
* @param bytes the length of the hash to compute in bytes
* @return the PBDKF2 hash of the password
*/
private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes)
throws NoSuchAlgorithmException, InvalidKeySpecException
{
PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8);
SecretKeyFactory skf = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
return skf.generateSecret(spec).getEncoded();
}
public byte[] createHash(String password, byte[] salt) {
try {
byte[] hash = pbkdf2(password.toCharArray(), salt, PBKDF2_ITERATIONS, HASH_BYTES);
return hash;
} catch (NoSuchAlgorithmException e) {
return null;
} catch (InvalidKeySpecException e) {
return null;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy