/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 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.interfaces;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import org.wildfly.common.Assert;
import org.wildfly.security.password.TwoWayPassword;
import org.wildfly.security.password.spec.IteratedPasswordAlgorithmSpec;
import org.wildfly.security.password.spec.IteratedSaltedPasswordAlgorithmSpec;
import org.wildfly.security.password.spec.MaskedPasswordAlgorithmSpec;
import org.wildfly.security.password.spec.SaltedPasswordAlgorithmSpec;
/**
* A password which has been masked, PicketBox style.
*
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
*/
public interface MaskedPassword extends TwoWayPassword {
String ALGORITHM_MASKED_MD5_DES = "masked-MD5-DES";
String ALGORITHM_MASKED_MD5_DES_CBC_PKCS5 = "masked-MD5-DES-CBC-PKCS5";
String ALGORITHM_MASKED_MD5_3DES = "masked-MD5-3DES";
String ALGORITHM_MASKED_MD5_3DES_CBC_PKCS5 = "masked-MD5-3DES-CBC-PKCS5";
String ALGORITHM_MASKED_SHA1_DES_EDE = "masked-SHA1-DES-EDE";
String ALGORITHM_MASKED_SHA1_DES_EDE_CBC_PKCS5 = "masked-SHA1-DES-EDE-CBC-PKCS5";
String ALGORITHM_MASKED_SHA1_RC2_40 = "masked-SHA1-RC2-40";
String ALGORITHM_MASKED_SHA1_RC2_40_CBC_PKCS5 = "masked-SHA1-RC2-40-CBC-PKCS5";
String ALGORITHM_MASKED_SHA1_RC2_128 = "masked-SHA1-RC2-128";
String ALGORITHM_MASKED_SHA1_RC2_128_CBC_PKCS5 = "masked-SHA1-RC2-128-CBC-PKCS5";
String ALGORITHM_MASKED_SHA1_RC4_40 = "masked-SHA1-RC4-40";
String ALGORITHM_MASKED_SHA1_RC4_40_ECB = "masked-SHA1-RC4-40-ECB";
String ALGORITHM_MASKED_SHA1_RC4_128 = "masked-SHA1-RC4-128";
String ALGORITHM_MASKED_SHA1_RC4_128_ECB = "masked-SHA1-RC4-128-ECB";
String ALGORITHM_MASKED_HMAC_SHA1_AES_128 = "masked-HMAC-SHA1-AES-128";
String ALGORITHM_MASKED_HMAC_SHA224_AES_128 = "masked-HMAC-SHA224-AES-128";
String ALGORITHM_MASKED_HMAC_SHA256_AES_128 = "masked-HMAC-SHA256-AES-128";
String ALGORITHM_MASKED_HMAC_SHA384_AES_128 = "masked-HMAC-SHA384-AES-128";
String ALGORITHM_MASKED_HMAC_SHA512_AES_128 = "masked-HMAC-SHA512-AES-128";
String ALGORITHM_MASKED_HMAC_SHA1_AES_256 = "masked-HMAC-SHA1-AES-256";
String ALGORITHM_MASKED_HMAC_SHA224_AES_256 = "masked-HMAC-SHA224-AES-256";
String ALGORITHM_MASKED_HMAC_SHA256_AES_256 = "masked-HMAC-SHA256-AES-256";
String ALGORITHM_MASKED_HMAC_SHA384_AES_256 = "masked-HMAC-SHA384-AES-256";
String ALGORITHM_MASKED_HMAC_SHA512_AES_256 = "masked-HMAC-SHA512-AES-256";
String ALGORITHM_MASKED_PBKDF_HMAC_SHA1 = "masked-PBKDF-HMAC-SHA1";
String ALGORITHM_MASKED_PBKDF_HMAC_SHA224 = "masked-PBKDF-HMAC-SHA224";
String ALGORITHM_MASKED_PBKDF_HMAC_SHA256 = "masked-PBKDF-HMAC-SHA256";
String ALGORITHM_MASKED_PBKDF_HMAC_SHA384 = "masked-PBKDF-HMAC-SHA384";
String ALGORITHM_MASKED_PBKDF_HMAC_SHA512 = "masked-PBKDF-HMAC-SHA512";
/**
* Determine if the given algorithm name is a valid masked password algorithm name.
*
* @param name the algorithm name
* @return {@code true} if the algorithm name is valid for this password type, {@code false} otherwise
*/
static boolean isMaskedAlgorithm(String name) {
return getPBEName(name) != null;
}
/**
* Get the name of the PBE algorithm that goes with the given password algorithm name.
*
* @param name the password algorithm name
* @return the PBE algorithm name, or {@code null} if the password algorithm name was {@code null} or not recognized
*/
@SuppressWarnings("SpellCheckingInspection")
static String getPBEName(String name) {
if (name == null) return null;
switch (name) {
case ALGORITHM_MASKED_MD5_DES: return "PBEWithMD5ANDdes";
case ALGORITHM_MASKED_MD5_DES_CBC_PKCS5: return "PBEWithMD5ANDtripledes";
case ALGORITHM_MASKED_MD5_3DES: return "PBEWithMD5ANDtripledes";
case ALGORITHM_MASKED_MD5_3DES_CBC_PKCS5: return "PBEWithMD5AndTRIPLEDES";
case ALGORITHM_MASKED_SHA1_DES_EDE: return "PBEwithSHA1AndDESede";
case ALGORITHM_MASKED_SHA1_DES_EDE_CBC_PKCS5: return "PBEwithSHA1AndDESede";
case ALGORITHM_MASKED_SHA1_RC2_40: return "PBEwithSHA1AndRC2_40";
case ALGORITHM_MASKED_SHA1_RC2_40_CBC_PKCS5: return "PBEwithSHA1Andrc2_40";
case ALGORITHM_MASKED_SHA1_RC2_128: return "PBEWithSHA1AndRC2_128";
case ALGORITHM_MASKED_SHA1_RC2_128_CBC_PKCS5: return "PBEWithSHA1andRC2_128";
case ALGORITHM_MASKED_SHA1_RC4_40: return "PBEWithSHA1AndRC4_40";
case ALGORITHM_MASKED_SHA1_RC4_40_ECB: return "PBEWithsha1AndRC4_40";
case ALGORITHM_MASKED_SHA1_RC4_128: return "PBEWithSHA1AndRC4_128";
case ALGORITHM_MASKED_SHA1_RC4_128_ECB: return "pbeWithSHA1AndRC4_128";
case ALGORITHM_MASKED_HMAC_SHA1_AES_128: return "PBEWithHmacSHA1AndAES_128";
case ALGORITHM_MASKED_HMAC_SHA224_AES_128: return "PBEWithHmacSHA224AndAES_128";
case ALGORITHM_MASKED_HMAC_SHA256_AES_128: return "PBEWithHmacSHA256AndAES_128";
case ALGORITHM_MASKED_HMAC_SHA384_AES_128: return "PBEWithHmacSHA384AndAES_128";
case ALGORITHM_MASKED_HMAC_SHA512_AES_128: return "PBEWithHmacSHA512AndAES_128";
case ALGORITHM_MASKED_HMAC_SHA1_AES_256: return "PBEWithHmacSHA1AndAES_256";
case ALGORITHM_MASKED_HMAC_SHA224_AES_256: return "PBEWithHmacSHA224AndAES_256";
case ALGORITHM_MASKED_HMAC_SHA256_AES_256: return "PBEWithHmacSHA256AndAES_256";
case ALGORITHM_MASKED_HMAC_SHA384_AES_256: return "PBEWithHmacSHA384AndAES_256";
case ALGORITHM_MASKED_HMAC_SHA512_AES_256: return "PBEWithHmacSHA512AndAES_256";
case ALGORITHM_MASKED_PBKDF_HMAC_SHA1: return "PBKDF2WithHmacSHA1";
case ALGORITHM_MASKED_PBKDF_HMAC_SHA224: return "PBKDF2WithHmacSHA224";
case ALGORITHM_MASKED_PBKDF_HMAC_SHA256: return "PBKDF2WithHmacSHA256";
case ALGORITHM_MASKED_PBKDF_HMAC_SHA384: return "PBKDF2WithHmacSHA384";
case ALGORITHM_MASKED_PBKDF_HMAC_SHA512: return "PBKDF2WithHmacSHA512";
default: return null;
}
}
/**
* Get the initial key material.
*
* @return the initial key material (must not be {@code null})
*/
char[] getInitialKeyMaterial();
/**
* Get the iteration count.
*
* @return the iteration count
*/
int getIterationCount();
/**
* Get the salt bytes.
*
* @return the salt bytes (must not be {@code null})
*/
byte[] getSalt();
/**
* Get the masked password bytes.
*
* @return the masked password bytes (must not be {@code null})
*/
byte[] getMaskedPasswordBytes();
default MaskedPasswordAlgorithmSpec getParameterSpec() {
return new MaskedPasswordAlgorithmSpec(getInitialKeyMaterial(), getIterationCount(), getSalt());
}
default boolean impliesParameters(AlgorithmParameterSpec parameterSpec) {
Assert.checkNotNullParam("parameterSpec", parameterSpec);
if (parameterSpec instanceof MaskedPasswordAlgorithmSpec) {
MaskedPasswordAlgorithmSpec spec = (MaskedPasswordAlgorithmSpec) parameterSpec;
return Arrays.equals(getInitialKeyMaterial(), spec.getInitialKeyMaterial())
&& getIterationCount() <= spec.getIterationCount()
&& Arrays.equals(getSalt(), spec.getSalt());
} else if (parameterSpec instanceof SaltedPasswordAlgorithmSpec) {
final SaltedPasswordAlgorithmSpec spec = (SaltedPasswordAlgorithmSpec) parameterSpec;
return Arrays.equals(getSalt(), spec.getSalt());
} else if (parameterSpec instanceof IteratedPasswordAlgorithmSpec) {
final IteratedPasswordAlgorithmSpec spec = (IteratedPasswordAlgorithmSpec) parameterSpec;
return getIterationCount() <= spec.getIterationCount();
} else if (parameterSpec instanceof IteratedSaltedPasswordAlgorithmSpec) {
final IteratedSaltedPasswordAlgorithmSpec spec = (IteratedSaltedPasswordAlgorithmSpec) parameterSpec;
return Arrays.equals(getSalt(), spec.getSalt()) && getIterationCount() <= spec.getIterationCount();
} else {
return false;
}
}
@Override
MaskedPassword clone();
/**
* Create a raw instance of this password type.
*
* @param algorithm the algorithm name (must not be {@code null})
* @param initialKeyMaterial the initial key material (must not be {@code null})
* @param iterationCount the iteration count
* @param salt the salt (must not be {@code null})
* @param maskedPasswordBytes the masked password bytes (must not be {@code null})
* @return the raw instance (not {@code null})
*/
static MaskedPassword createRaw(String algorithm, char[] initialKeyMaterial, int iterationCount, byte[] salt, byte[] maskedPasswordBytes) {
Assert.checkNotNullParam("algorithm", algorithm);
Assert.checkNotNullParam("initialKeyMaterial", initialKeyMaterial);
Assert.checkNotNullParam("salt", salt);
Assert.checkNotNullParam("maskedPasswordBytes", maskedPasswordBytes);
return new RawMaskedPassword(algorithm, initialKeyMaterial.clone(), iterationCount, salt.clone(), maskedPasswordBytes.clone());
}
}