PBKDF2PasswordStorageScheme.java revision 423f6a91805232d2116622864305b5eb129058bc
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2013-2015 ForgeRock AS.
*/
/**
* This class defines a Directory Server password storage scheme based on the
* PBKDF2 algorithm defined in RFC 2898. This is a one-way digest algorithm
* so there is no way to retrieve the original clear-text version of the
* password from the hashed value (although this means that it is not suitable
* for things that need the clear-text password like DIGEST-MD5). This
* implementation uses a configurable number of iterations.
*/
public class PBKDF2PasswordStorageScheme
{
/** The fully-qualified name of this class. */
private static final String CLASS_NAME = "org.opends.server.extensions.PBKDF2PasswordStorageScheme";
/** The number of bytes of random data to use as the salt when generating the hashes. */
private static final int NUM_SALT_BYTES = 8;
/** The number of bytes the SHA-1 algorithm produces. */
private static final int SHA1_LENGTH = 20;
/** The secure random number generator to use to generate the salt values. */
private SecureRandom random;
/** The current configuration for this storage scheme. */
private volatile PBKDF2PasswordStorageSchemeCfg config;
/**
* Creates a new instance of this password storage scheme. Note that no
* initialization should be performed here, as all initialization should be
* done in the <CODE>initializePasswordStorageScheme</CODE> method.
*/
public PBKDF2PasswordStorageScheme()
{
super();
}
/** {@inheritDoc} */
{
try
{
// Just try to verify if the algorithm is supported.
}
catch (NoSuchAlgorithmException e)
{
throw new InitializationException(null);
}
this.config = configuration;
config.addPBKDF2ChangeListener(this);
}
/** {@inheritDoc} */
{
return true;
}
/** {@inheritDoc} */
{
this.config = configuration;
return new ConfigChangeResult();
}
/** {@inheritDoc} */
public String getStorageSchemeName()
{
return STORAGE_SCHEME_NAME_PBKDF2;
}
/** {@inheritDoc} */
throws DirectoryException
{
byte[] saltBytes = new byte[NUM_SALT_BYTES];
}
/** {@inheritDoc} */
throws DirectoryException
{
}
/** {@inheritDoc} */
// Split the iterations from the stored value (separated by a ':')
// Base64-decode the remaining value and take the last 8 bytes as the salt.
try
{
if (pos == -1)
{
throw new Exception();
}
if (saltLength <= 0)
{
return false;
}
final byte[] digestBytes = new byte[SHA1_LENGTH];
final byte[] saltBytes = new byte[saltLength];
}
catch (Exception e)
{
logger.traceException(e);
return false;
}
}
/** {@inheritDoc} */
public boolean supportsAuthPasswordSyntax()
{
return true;
}
/** {@inheritDoc} */
public String getAuthPasswordSchemeName()
{
return AUTH_PASSWORD_SCHEME_NAME_PBKDF2;
}
/** {@inheritDoc} */
throws DirectoryException
{
byte[] saltBytes = new byte[NUM_SALT_BYTES];
// Encode and return the value.
}
/** {@inheritDoc} */
public boolean authPasswordMatches(ByteSequence plaintextPassword, String authInfo, String authValue)
{
try
{
if (pos == -1)
{
throw new Exception();
}
}
catch (Exception e)
{
logger.traceException(e);
return false;
}
}
/** {@inheritDoc} */
public boolean isReversible()
{
return false;
}
/** {@inheritDoc} */
throws DirectoryException
{
}
/** {@inheritDoc} */
throws DirectoryException
{
}
/** {@inheritDoc} */
public boolean isStorageSchemeSecure()
{
return true;
}
/**
* Generates an encoded password string from the given clear-text password.
* This method is primarily intended for use when it is necessary to generate a password with the server
* offline (e.g., when setting the initial root user password).
*
* @param passwordBytes The bytes that make up the clear-text password.
* @return The encoded password string, including the scheme name in curly braces.
* @throws DirectoryException If a problem occurs during processing.
*/
throws DirectoryException
{
byte[] saltBytes = new byte[NUM_SALT_BYTES];
int iterations = 10000;
}
throws DirectoryException
{
try
{
}
catch (DirectoryException e)
{
throw e;
}
catch (Exception e)
{
throw cannotEncodePassword(e);
}
}
throws DirectoryException
{
try
{
}
catch (Exception e)
{
throw cannotEncodePassword(e);
}
finally
{
}
}
private boolean encodeAndMatch(ByteSequence plaintext, byte[] saltBytes, byte[] digestBytes, int iterations)
{
try
{
}
catch (Exception e)
{
return false;
}
}
throws DirectoryException
{
}
{
logger.traceException(e);
LocalizableMessage message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get(CLASS_NAME, getExceptionMessage(e));
}
return hashPlusSalt;
}
}