AESPasswordStorageScheme.java revision ea1068c292e9b341af6d6b563cd8988a96be20a9
5046N/A/*
5046N/A * CDDL HEADER START
5046N/A *
5046N/A * The contents of this file are subject to the terms of the
5046N/A * Common Development and Distribution License, Version 1.0 only
5046N/A * (the "License"). You may not use this file except in compliance
5046N/A * with the License.
5046N/A *
5046N/A * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
5046N/A * or http://forgerock.org/license/CDDLv1.0.html.
5046N/A * See the License for the specific language governing permissions
5046N/A * and limitations under the License.
5046N/A *
5046N/A * When distributing Covered Code, include this CDDL HEADER in each
5046N/A * file and include the License file at legal-notices/CDDLv1_0.txt.
5046N/A * If applicable, add the following below this CDDL HEADER, with the
5046N/A * fields enclosed by brackets "[]" replaced with your own identifying
5046N/A * information:
5046N/A * Portions Copyright [yyyy] [name of copyright owner]
5046N/A *
5046N/A * CDDL HEADER END
5046N/A *
5046N/A *
5046N/A * Copyright 2008 Sun Microsystems, Inc.
5046N/A * Portions Copyright 2013-2015 ForgeRock AS
5046N/A */
5046N/Apackage org.opends.server.extensions;
5046N/A
5046N/A
5046N/A
5046N/Aimport org.forgerock.i18n.LocalizableMessage;
5046N/Aimport org.opends.server.admin.std.server.AESPasswordStorageSchemeCfg;
5046N/Aimport org.opends.server.api.PasswordStorageScheme;
5046N/Aimport org.forgerock.opendj.config.server.ConfigException;
5046N/Aimport org.opends.server.core.DirectoryServer;
5046N/Aimport org.forgerock.i18n.slf4j.LocalizedLogger;
5046N/Aimport org.opends.server.types.*;
5046N/Aimport org.forgerock.opendj.ldap.ResultCode;
5046N/Aimport org.forgerock.opendj.ldap.ByteString;
5046N/Aimport org.forgerock.opendj.ldap.ByteSequence;
5046N/Aimport org.opends.server.util.Base64;
5046N/A
5046N/Aimport java.util.Arrays;
5046N/A
5046N/Aimport static org.opends.messages.ExtensionMessages.*;
5046N/Aimport static org.opends.server.extensions.ExtensionsConstants.*;
5046N/Aimport static org.opends.server.util.StaticUtils.*;
5046N/A
5046N/A
5046N/A
5046N/A/**
5046N/A * This class defines a Directory Server password storage scheme that will
5046N/A * encode values using the AES reversible encryption algorithm. This
5046N/A * implementation supports only the user password syntax and not the auth
5046N/A * password syntax.
5046N/A */
5046N/Apublic class AESPasswordStorageScheme
5046N/A extends PasswordStorageScheme<AESPasswordStorageSchemeCfg>
5046N/A{
5046N/A private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
5046N/A
5046N/A
5046N/A
5046N/A // The reference to the Directory Server crypto manager that we will use to
5046N/A // handle the encryption/decryption.
5046N/A private CryptoManager cryptoManager;
5046N/A
5046N/A
5046N/A
5046N/A /**
5046N/A * Creates a new instance of this password storage scheme. Note that no
5046N/A * initialization should be performed here, as all initialization should be
5046N/A * done in the {@code initializePasswordStorageScheme} method.
5046N/A */
5046N/A public AESPasswordStorageScheme()
5046N/A {
5046N/A super();
5046N/A }
5046N/A
5046N/A
5046N/A
5046N/A /**
5046N/A * {@inheritDoc}
5046N/A */
5046N/A @Override
5046N/A public void initializePasswordStorageScheme(
5046N/A AESPasswordStorageSchemeCfg configuration)
5046N/A throws ConfigException, InitializationException
5046N/A {
5046N/A cryptoManager = DirectoryServer.getCryptoManager();
5046N/A }
5046N/A
5046N/A
5046N/A
5046N/A /**
5046N/A * {@inheritDoc}
5046N/A */
5046N/A @Override
5046N/A public String getStorageSchemeName()
5046N/A {
5046N/A return STORAGE_SCHEME_NAME_AES;
5046N/A }
5046N/A
5046N/A
5046N/A
5046N/A /**
5046N/A * {@inheritDoc}
5046N/A */
5046N/A @Override
5046N/A public ByteString encodePassword(ByteSequence plaintext)
5046N/A throws DirectoryException
5046N/A {
5046N/A byte[] plaintextBytes = null;
5046N/A try
5046N/A {
5046N/A // TODO: Can we avoid this copy?
5046N/A plaintextBytes = plaintext.toByteArray();
5046N/A byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_AES,
5046N/A KEY_SIZE_AES,
5046N/A plaintextBytes);
5046N/A return ByteString.valueOf(Base64.encode(encodedBytes));
5046N/A }
5046N/A catch (Exception e)
5046N/A {
5046N/A logger.traceException(e);
5046N/A
5046N/A LocalizableMessage m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_AES,
5046N/A getExceptionMessage(e));
5046N/A throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
5046N/A m, e);
5046N/A }
5046N/A finally
5046N/A {
5046N/A if (plaintextBytes != null)
5046N/A Arrays.fill(plaintextBytes, (byte) 0);
5046N/A }
5046N/A }
5046N/A
5046N/A
5046N/A
5046N/A /**
5046N/A * {@inheritDoc}
5046N/A */
5046N/A @Override
5046N/A public ByteString encodePasswordWithScheme(ByteSequence plaintext)
5046N/A throws DirectoryException
5046N/A {
5046N/A StringBuilder buffer = new StringBuilder();
5046N/A buffer.append('{');
5046N/A buffer.append(STORAGE_SCHEME_NAME_AES);
5046N/A buffer.append('}');
5046N/A byte[] plaintextBytes = null;
5046N/A try
5046N/A {
5046N/A // TODO: Can we avoid this copy?
5046N/A plaintextBytes = plaintext.toByteArray();
5046N/A byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_AES,
5046N/A KEY_SIZE_AES,
5046N/A plaintextBytes);
5046N/A buffer.append(Base64.encode(encodedBytes));
5046N/A }
5046N/A catch (Exception e)
5046N/A {
logger.traceException(e);
LocalizableMessage m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_AES,
getExceptionMessage(e));
throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
m, e);
}
finally
{
if (plaintextBytes != null)
Arrays.fill(plaintextBytes, (byte) 0);
}
return ByteString.valueOf(buffer.toString());
}
/**
* {@inheritDoc}
*/
@Override
public boolean passwordMatches(ByteSequence plaintextPassword,
ByteSequence storedPassword)
{
try
{
ByteString decryptedPassword =
ByteString.wrap(cryptoManager.decrypt(
Base64.decode(storedPassword.toString())));
return plaintextPassword.equals(decryptedPassword);
}
catch (Exception e)
{
logger.traceException(e);
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean isReversible()
{
return true;
}
/**
* {@inheritDoc}
*/
@Override
public ByteString getPlaintextValue(ByteSequence storedPassword)
throws DirectoryException
{
try
{
byte[] decryptedPassword =
cryptoManager.decrypt(Base64.decode(storedPassword.toString()));
return ByteString.wrap(decryptedPassword);
}
catch (Exception e)
{
logger.traceException(e);
LocalizableMessage m = ERR_PWSCHEME_CANNOT_DECRYPT.get(STORAGE_SCHEME_NAME_AES,
getExceptionMessage(e));
throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
m, e);
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean supportsAuthPasswordSyntax()
{
// This storage scheme does not support the authentication password syntax.
return false;
}
/**
* {@inheritDoc}
*/
@Override
public ByteString encodeAuthPassword(ByteSequence plaintext)
throws DirectoryException
{
LocalizableMessage message =
ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName());
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
}
/**
* {@inheritDoc}
*/
@Override
public boolean authPasswordMatches(ByteSequence plaintextPassword,
String authInfo, String authValue)
{
// This storage scheme does not support the authentication password syntax.
return false;
}
/**
* {@inheritDoc}
*/
@Override
public ByteString getAuthPasswordPlaintextValue(String authInfo,
String authValue)
throws DirectoryException
{
LocalizableMessage message =
ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName());
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isStorageSchemeSecure()
{
// This password storage scheme should be considered secure.
return true;
}
}