All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.wildfly.security.password.impl.SaltedSimpleDigestPasswordImpl Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.wildfly.security.password.impl;
import static org.wildfly.common.math.HashMath.multiHashOrdered;
import static org.wildfly.security.password.impl.ElytronMessages.log;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;
import org.wildfly.security.password.interfaces.SaltedSimpleDigestPassword;
import org.wildfly.security.password.spec.ClearPasswordSpec;
import org.wildfly.security.password.spec.SaltedHashPasswordSpec;
import org.wildfly.security.password.spec.SaltedPasswordAlgorithmSpec;
/**
* A {@code Password} implementation for {@link SaltedSimpleDigestPassword}.
*
* @author Darran Lofthouse
*/
class SaltedSimpleDigestPasswordImpl extends AbstractPasswordImpl implements SaltedSimpleDigestPassword {
private static final long serialVersionUID = -6754143875392946386L;
private final String algorithm;
private final byte[] digest;
private final byte[] salt;
SaltedSimpleDigestPasswordImpl(final String algorithm, final byte[] salt, final byte[] digest) {
this.algorithm = algorithm;
this.digest = digest;
this.salt = salt;
}
SaltedSimpleDigestPasswordImpl(final String algorithm, final SaltedHashPasswordSpec spec) {
this(algorithm, spec.getSalt().clone(), spec.getHash().clone());
}
SaltedSimpleDigestPasswordImpl(final SaltedSimpleDigestPassword password) {
this(password.getAlgorithm(), password.getSalt().clone(), password.getDigest().clone());
}
SaltedSimpleDigestPasswordImpl(final String algorithm, final ClearPasswordSpec spec) throws InvalidKeySpecException {
this.algorithm = algorithm;
this.salt = PasswordUtil.generateRandomSalt(DEFAULT_SALT_SIZE);
try {
this.digest = digestOf(algorithm, salt, spec.getEncodedPassword());
} catch (NoSuchAlgorithmException e) {
throw log.invalidKeySpecNoSuchMessageDigestAlgorithm(algorithm);
}
}
SaltedSimpleDigestPasswordImpl(final String algorithm, final char[] password, final SaltedPasswordAlgorithmSpec spec) throws InvalidKeySpecException {
this(algorithm, spec.getSalt().clone(), password);
}
SaltedSimpleDigestPasswordImpl(final String algorithm, final char[] password) throws InvalidKeySpecException {
this(algorithm, PasswordUtil.generateRandomSalt(DEFAULT_SALT_SIZE), password);
}
private SaltedSimpleDigestPasswordImpl(final String algorithm, final byte[] salt, final char[] password)
throws InvalidKeySpecException {
this.algorithm = algorithm;
this.salt = salt;
try {
this.digest = digestOf(algorithm, salt, password);
} catch (NoSuchAlgorithmException e) {
throw log.invalidKeySpecNoSuchMessageDigestAlgorithm(algorithm);
}
}
@Override
public String getAlgorithm() {
return algorithm;
}
@Override
public byte[] getDigest() {
return digest.clone();
}
@Override
public byte[] getSalt() {
return salt.clone();
}
@Override
S getKeySpec(Class keySpecType) throws InvalidKeySpecException {
if (keySpecType.isAssignableFrom(SaltedHashPasswordSpec.class)) {
return keySpecType.cast(new SaltedHashPasswordSpec(digest.clone(), salt.clone()));
}
throw new InvalidKeySpecException();
}
@Override
boolean verify(char[] guess) throws InvalidKeyException {
try {
return Arrays.equals(digest, digestOf(algorithm, salt, guess));
} catch (NoSuchAlgorithmException e) {
throw log.invalidKeyNoSuchMessageDigestAlgorithm(algorithm);
}
}
@Override
boolean convertibleTo(Class keySpecType) {
return keySpecType.isAssignableFrom(SaltedHashPasswordSpec.class);
}
private static byte[] digestOf(final String algorithm, final byte[] salt, final char[] password)
throws NoSuchAlgorithmException {
boolean saltFirst = isSaltFirst(algorithm);
MessageDigest md = getMessageDigest(algorithm);
byte[] passwordBytes = new String(password).getBytes(StandardCharsets.UTF_8);
if (saltFirst) {
md.update(salt);
md.update(passwordBytes);
} else {
md.update(passwordBytes);
md.update(salt);
}
return md.digest();
}
private static MessageDigest getMessageDigest(final String algorithm) throws NoSuchAlgorithmException {
switch (algorithm) {
case ALGORITHM_PASSWORD_SALT_DIGEST_MD5:
case ALGORITHM_SALT_PASSWORD_DIGEST_MD5:
return MessageDigest.getInstance("MD5");
case ALGORITHM_PASSWORD_SALT_DIGEST_SHA_1:
case ALGORITHM_SALT_PASSWORD_DIGEST_SHA_1:
return MessageDigest.getInstance("SHA-1");
case ALGORITHM_PASSWORD_SALT_DIGEST_SHA_256:
case ALGORITHM_SALT_PASSWORD_DIGEST_SHA_256:
return MessageDigest.getInstance("SHA-256");
case ALGORITHM_PASSWORD_SALT_DIGEST_SHA_384:
case ALGORITHM_SALT_PASSWORD_DIGEST_SHA_384:
return MessageDigest.getInstance("SHA-384");
case ALGORITHM_PASSWORD_SALT_DIGEST_SHA_512:
case ALGORITHM_SALT_PASSWORD_DIGEST_SHA_512:
return MessageDigest.getInstance("SHA-512");
default:
throw log.noSuchAlgorithmInvalidAlgorithm(algorithm);
}
}
private static boolean isSaltFirst(final String algorithm) throws NoSuchAlgorithmException {
switch (algorithm) {
case ALGORITHM_PASSWORD_SALT_DIGEST_MD5:
case ALGORITHM_PASSWORD_SALT_DIGEST_SHA_1:
case ALGORITHM_PASSWORD_SALT_DIGEST_SHA_256:
case ALGORITHM_PASSWORD_SALT_DIGEST_SHA_384:
case ALGORITHM_PASSWORD_SALT_DIGEST_SHA_512:
return false;
case ALGORITHM_SALT_PASSWORD_DIGEST_MD5:
case ALGORITHM_SALT_PASSWORD_DIGEST_SHA_1:
case ALGORITHM_SALT_PASSWORD_DIGEST_SHA_256:
case ALGORITHM_SALT_PASSWORD_DIGEST_SHA_384:
case ALGORITHM_SALT_PASSWORD_DIGEST_SHA_512:
return true;
default:
throw log.noSuchAlgorithmInvalidAlgorithm(algorithm);
}
}
public int hashCode() {
return multiHashOrdered(multiHashOrdered(Arrays.hashCode(digest), Arrays.hashCode(salt)), algorithm.hashCode());
}
public boolean equals(final Object obj) {
if (! (obj instanceof SaltedSimpleDigestPasswordImpl)) {
return false;
}
SaltedSimpleDigestPasswordImpl other = (SaltedSimpleDigestPasswordImpl) obj;
return algorithm.equals(other.algorithm) && Arrays.equals(digest, other.digest) && Arrays.equals(salt, other.salt);
}
private void readObject(ObjectInputStream ignored) throws NotSerializableException {
throw new NotSerializableException();
}
Object writeReplace() {
return SaltedSimpleDigestPassword.createRaw(algorithm, digest, salt);
}
public SaltedSimpleDigestPasswordImpl clone() {
return this;
}
}