From 99d33a80f9ac8ee98c24e1bcce9deab8b9815bf2 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Fri, 12 Sep 2014 14:15:15 +0000
Subject: [PATCH] Code cleanup for password storage schemes. Used AutoRefactor. Reduced variable scopes.

---
 opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PBKDF2PasswordStorageSchemeTestCase.java  |   87 +++++++
 opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageSchemeTestCase.java |   38 ++-
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java                                  |  372 +++++++++---------------------
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java                                 |  211 +++++------------
 4 files changed, 294 insertions(+), 414 deletions(-)

diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java
index d2eab2e..a842995 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java
@@ -21,35 +21,37 @@
  * CDDL HEADER END
  *
  *
- *      Portions Copyright 2013-2014 ForgeRock AS.
+ *      Copyright 2013-2014 ForgeRock AS.
  */
 package org.opends.server.extensions;
 
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.security.spec.KeySpec;
 import java.util.Arrays;
 import java.util.List;
-import java.security.spec.KeySpec;
 
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.ByteSequence;
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.ResultCode;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.server.PBKDF2PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.core.DirectoryServer;
-import org.forgerock.i18n.slf4j.LocalizedLogger;
-import org.opends.server.types.*;
-import org.forgerock.opendj.ldap.ResultCode;
-import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.ByteSequence;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.InitializationException;
 import org.opends.server.util.Base64;
 
 import static org.opends.messages.ExtensionMessages.*;
 import static org.opends.server.extensions.ExtensionsConstants.*;
-import static org.opends.server.util.StaticUtils.getExceptionMessage;
+import static org.opends.server.util.StaticUtils.*;
 
 /**
  * This class defines a Directory Server password storage scheme based on the
@@ -65,9 +67,7 @@
 {
   private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
-  /**
-   * The fully-qualified name of this class.
-   */
+  /** The fully-qualified name of this class. */
   private static final String CLASS_NAME =
        "org.opends.server.extensions.PBKDF2PasswordStorageScheme";
 
@@ -78,19 +78,19 @@
    */
   private static final int NUM_SALT_BYTES = 8;
 
-  // The number of bytes the SHA-1 algorithm produces
+  /** The number of bytes the SHA-1 algorithm produces. */
   private static final int SHA1_LENGTH = 20;
 
-  // The factory used to generate the PBKDF2 hashes.
+  /** The factory used to generate the PBKDF2 hashes. */
   private SecretKeyFactory factory;
 
-  // The lock used to provide threadsafe access to the message digest.
-  private Object factoryLock;
+  /** The lock used to provide thread-safe access to the message digest. */
+  private final Object factoryLock = new Object();
 
-  // The secure random number generator to use to generate the salt values.
+  /** The secure random number generator to use to generate the salt values. */
   private SecureRandom random;
 
-  // The current configuration for this storage scheme.
+  /** The current configuration for this storage scheme. */
   private volatile PBKDF2PasswordStorageSchemeCfg config;
 
 
@@ -104,17 +104,12 @@
     super();
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public void initializePasswordStorageScheme(
                    PBKDF2PasswordStorageSchemeCfg configuration)
          throws ConfigException, InitializationException
   {
-    factoryLock = new Object();
     try
     {
       random = SecureRandom.getInstance(SECURE_PRNG_SHA1);
@@ -129,24 +124,17 @@
     config.addPBKDF2ChangeListener(this);
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
+  @Override
   public boolean isConfigurationChangeAcceptable(
                       PBKDF2PasswordStorageSchemeCfg configuration,
                       List<LocalizableMessage> unacceptableReasons)
   {
-    // The configuration will always be acceptable.
     return true;
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
+  @Override
   public ConfigChangeResult applyConfigurationChange(
       PBKDF2PasswordStorageSchemeCfg configuration)
   {
@@ -154,57 +142,22 @@
     return new ConfigChangeResult(ResultCode.SUCCESS, false);
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public String getStorageSchemeName()
   {
     return STORAGE_SCHEME_NAME_PBKDF2;
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public ByteString encodePassword(ByteSequence plaintext)
          throws DirectoryException
   {
     byte[] saltBytes      = new byte[NUM_SALT_BYTES];
-    byte[] digestBytes;
-    char[] plaintextChars = null;
     int    iterations     = config.getPBKDF2Iterations();
 
-    synchronized(factoryLock)
-    {
-      try
-      {
-        random.nextBytes(saltBytes);
-
-        plaintextChars = plaintext.toString().toCharArray();
-        KeySpec spec = new PBEKeySpec(plaintextChars,
-            saltBytes, iterations, SHA1_LENGTH * 8);
-        digestBytes = factory.generateSecret(spec).getEncoded();
-      }
-      catch (Exception e)
-      {
-        logger.traceException(e);
-
-        LocalizableMessage message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get(
-            CLASS_NAME, getExceptionMessage(e));
-        throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
-                                     message, e);
-      }
-      finally
-      {
-        if (plaintextChars != null)
-          Arrays.fill(plaintextChars, '0');
-      }
-    }
+    byte[] digestBytes = getDigestBytes(plaintext, saltBytes, iterations);
     // Append the salt to the hashed value and base64-the whole thing.
     byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
 
@@ -212,73 +165,49 @@
     System.arraycopy(saltBytes, 0, hashPlusSalt, digestBytes.length,
                      NUM_SALT_BYTES);
 
-    StringBuilder sb = new StringBuilder();
-    sb.append(Integer.toString(iterations));
-    sb.append(':');
-    sb.append(Base64.encode(hashPlusSalt));
-    return ByteString.valueOf(sb.toString());
+    return ByteString.valueOf(iterations + ":" + Base64.encode(hashPlusSalt));
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public ByteString encodePasswordWithScheme(ByteSequence plaintext)
          throws DirectoryException
   {
-    StringBuilder buffer = new StringBuilder();
-    buffer.append('{');
-    buffer.append(STORAGE_SCHEME_NAME_PBKDF2);
-    buffer.append('}');
-
-    buffer.append(encodePassword(plaintext));
-
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf('{' + STORAGE_SCHEME_NAME_PBKDF2 + '}'
+        + encodePassword(plaintext));
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public boolean passwordMatches(ByteSequence plaintextPassword,
                                  ByteSequence storedPassword)
   {
-
-    // Split the iterations from the stored value (separated by a ":")
+    // Split the iterations from the stored value (separated by a ':')
     // Base64-decode the remaining value and take the last 8 bytes as the salt.
-    int iterations;
-    byte[] saltBytes;
-    byte[] digestBytes = new byte[SHA1_LENGTH];
-    int saltLength = 0;
     try
     {
       String stored = storedPassword.toString();
-      int stored_length = stored.length();
-      int pos = 0;
-      while (pos < stored_length && stored.charAt(pos) != ':')
+      int pos = stored.indexOf(':');
+      if (pos == -1)
       {
-        pos++;
-      }
-      if (pos >= (stored_length - 1) || pos == 0)
         throw new Exception();
+      }
 
-      iterations = Integer.parseInt(stored.substring(0, pos));
+      final int iterations = Integer.parseInt(stored.substring(0, pos));
       byte[] decodedBytes = Base64.decode(stored.substring(pos + 1));
 
-      saltLength = decodedBytes.length - SHA1_LENGTH;
+      final int saltLength = decodedBytes.length - SHA1_LENGTH;
       if (saltLength <= 0)
       {
         logger.error(ERR_PWSCHEME_INVALID_BASE64_DECODED_STORED_PASSWORD, storedPassword);
         return false;
       }
-      saltBytes = new byte[saltLength];
+
+      final byte[] digestBytes = new byte[SHA1_LENGTH];
+      final byte[] saltBytes = new byte[saltLength];
       System.arraycopy(decodedBytes, 0, digestBytes, 0, SHA1_LENGTH);
-      System.arraycopy(decodedBytes, SHA1_LENGTH, saltBytes, 0,
-                       saltLength);
+      System.arraycopy(decodedBytes, SHA1_LENGTH, saltBytes, 0, saltLength);
+      return encodeAndMatch(plaintextPassword, saltBytes, digestBytes, iterations);
     }
     catch (Exception e)
     {
@@ -286,18 +215,19 @@
       logger.error(ERR_PWSCHEME_CANNOT_BASE64_DECODE_STORED_PASSWORD, storedPassword, e);
       return false;
     }
+  }
 
-
+  private boolean encodeAndMatch(ByteSequence plaintextPassword,
+      final byte[] saltBytes, byte[] digestBytes, int iterations)
+  {
     // Use the salt to generate a digest based on the provided plain-text value.
     int plainBytesLength = plaintextPassword.length();
-    byte[] plainPlusSalt = new byte[plainBytesLength + saltLength];
+    byte[] plainPlusSalt = new byte[plainBytesLength + saltBytes.length];
     plaintextPassword.copyTo(plainPlusSalt);
-    System.arraycopy(saltBytes, 0, plainPlusSalt, plainBytesLength,
-                     saltLength);
+    System.arraycopy(saltBytes, 0, plainPlusSalt, plainBytesLength, saltBytes.length);
 
-    byte[] userDigestBytes;
+
     char[] plaintextChars = null;
-
     synchronized (factoryLock)
     {
       try
@@ -306,62 +236,58 @@
         KeySpec spec = new PBEKeySpec(
             plaintextChars, saltBytes,
             iterations, SHA1_LENGTH * 8);
-        userDigestBytes = factory.generateSecret(spec).getEncoded();
+        final byte[] userDigestBytes = factory.generateSecret(spec).getEncoded();
+        return Arrays.equals(digestBytes, userDigestBytes);
       }
       catch (Exception e)
       {
         logger.traceException(e);
-
         return false;
       }
       finally
       {
         if (plaintextChars != null)
+        {
           Arrays.fill(plaintextChars, '0');
+        }
       }
     }
-
-    return Arrays.equals(digestBytes, userDigestBytes);
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public boolean supportsAuthPasswordSyntax()
   {
-    // This storage scheme does support the authentication password syntax.
     return true;
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public String getAuthPasswordSchemeName()
   {
     return AUTH_PASSWORD_SCHEME_NAME_PBKDF2;
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public ByteString encodeAuthPassword(ByteSequence plaintext)
          throws DirectoryException
   {
     byte[] saltBytes      = new byte[NUM_SALT_BYTES];
-    byte[] digestBytes;
-    char[] plaintextChars = null;
     int    iterations     = config.getPBKDF2Iterations();
+    byte[] digestBytes = getDigestBytes(plaintext, saltBytes, iterations);
 
-    synchronized(factoryLock)
+    // Encode and return the value.
+    return ByteString.valueOf(AUTH_PASSWORD_SCHEME_NAME_PBKDF2 + '$'
+        + iterations + ':' + Base64.encode(saltBytes) + '$'
+        + Base64.encode(digestBytes));
+  }
+
+  private byte[] getDigestBytes(ByteSequence plaintext, byte[] saltBytes,
+      int iterations) throws DirectoryException
+  {
+    char[] plaintextChars = null;
+    synchronized (factoryLock)
     {
       try
       {
@@ -371,7 +297,7 @@
         KeySpec spec = new PBEKeySpec(
             plaintextChars, saltBytes,
             iterations, SHA1_LENGTH * 8);
-        digestBytes = factory.generateSecret(spec).getEncoded();
+        return factory.generateSecret(spec).getEncoded();
       }
       catch (Exception e)
       {
@@ -385,109 +311,46 @@
       finally
       {
         if (plaintextChars != null)
+        {
           Arrays.fill(plaintextChars, '0');
+        }
       }
     }
-    // Encode and return the value.
-    StringBuilder authPWValue = new StringBuilder();
-    authPWValue.append(AUTH_PASSWORD_SCHEME_NAME_PBKDF2);
-    authPWValue.append('$');
-    authPWValue.append(Integer.toString(iterations));
-    authPWValue.append(':');
-    authPWValue.append(Base64.encode(saltBytes));
-    authPWValue.append('$');
-    authPWValue.append(Base64.encode(digestBytes));
-
-    return ByteString.valueOf(authPWValue.toString());
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public boolean authPasswordMatches(ByteSequence plaintextPassword,
                                      String authInfo, String authValue)
   {
-    byte[] saltBytes;
-    byte[] digestBytes;
-    int    iterations;
-
     try
     {
-      int pos = 0;
-      int length = authInfo.length();
-      while (pos < length && authInfo.charAt(pos) != ':')
+      int pos = authInfo.indexOf(':');
+      if (pos == -1)
       {
-        pos++;
-      }
-      if (pos >= (length - 1) || pos == 0)
         throw new Exception();
-      iterations = Integer.parseInt(authInfo.substring(0, pos));
-      saltBytes   = Base64.decode(authInfo.substring(pos + 1));
-      digestBytes = Base64.decode(authValue);
+      }
+      int iterations = Integer.parseInt(authInfo.substring(0, pos));
+      byte[] saltBytes   = Base64.decode(authInfo.substring(pos + 1));
+      byte[] digestBytes = Base64.decode(authValue);
+      return encodeAndMatch(plaintextPassword, saltBytes, digestBytes, iterations);
     }
     catch (Exception e)
     {
       logger.traceException(e);
-
       return false;
     }
-
-
-    int plainBytesLength = plaintextPassword.length();
-    byte[] plainPlusSalt = new byte[plainBytesLength + saltBytes.length];
-    plaintextPassword.copyTo(plainPlusSalt);
-    System.arraycopy(saltBytes, 0, plainPlusSalt, plainBytesLength,
-                     saltBytes.length);
-
-    byte[] userDigestBytes;
-    char[] plaintextChars = null;
-
-    synchronized (factoryLock)
-    {
-      try
-      {
-        plaintextChars = plaintextPassword.toString().toCharArray();
-        KeySpec spec = new PBEKeySpec(
-            plaintextChars, saltBytes,
-            iterations, SHA1_LENGTH * 8);
-        userDigestBytes = factory.generateSecret(spec).getEncoded();
-      }
-      catch (Exception e)
-      {
-        logger.traceException(e);
-
-        return false;
-      }
-      finally
-      {
-        if (plaintextChars != null)
-          Arrays.fill(plaintextChars, '0');
-      }
-    }
-
-    return Arrays.equals(digestBytes, userDigestBytes);
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public boolean isReversible()
   {
     return false;
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public ByteString getPlaintextValue(ByteSequence storedPassword)
          throws DirectoryException
   {
@@ -496,12 +359,8 @@
     throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public ByteString getAuthPasswordPlaintextValue(String authInfo,
                                                   String authValue)
          throws DirectoryException
@@ -511,15 +370,10 @@
     throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public boolean isStorageSchemeSecure()
   {
-    // PBKDF2 should be considered secure.
     return true;
   }
 
@@ -542,19 +396,33 @@
          throws DirectoryException
   {
     byte[] saltBytes      = new byte[NUM_SALT_BYTES];
-    byte[] digestBytes;
-    char[] plaintextChars = null;
     int    iterations     = 10000;
 
+    byte[] digestBytes = getDigestBytes(passwordBytes, saltBytes, iterations);
+    // Append the salt to the hashed value and base64-the whole thing.
+    byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
+
+    System.arraycopy(digestBytes, 0, hashPlusSalt, 0, digestBytes.length);
+    System.arraycopy(saltBytes, 0, hashPlusSalt, digestBytes.length,
+                     NUM_SALT_BYTES);
+
+    return '{' + STORAGE_SCHEME_NAME_PBKDF2 + '}' + iterations + ':' +
+      Base64.encode(hashPlusSalt);
+  }
+
+  private static byte[] getDigestBytes(byte[] plaintext, byte[] saltBytes,
+      int iterations) throws DirectoryException
+  {
+    char[] plaintextChars = null;
     try
     {
       SecureRandom.getInstance(SECURE_PRNG_SHA1).nextBytes(saltBytes);
 
-      plaintextChars = passwordBytes.toString().toCharArray();
+      plaintextChars = plaintext.toString().toCharArray();
       KeySpec spec = new PBEKeySpec(
           plaintextChars, saltBytes,
           iterations, SHA1_LENGTH * 8);
-      digestBytes = SecretKeyFactory
+      return SecretKeyFactory
           .getInstance(MESSAGE_DIGEST_ALGORITHM_PBKDF2)
           .generateSecret(spec).getEncoded();
     }
@@ -570,18 +438,10 @@
     finally
     {
       if (plaintextChars != null)
+      {
         Arrays.fill(plaintextChars, '0');
+      }
     }
-
-    // Append the salt to the hashed value and base64-the whole thing.
-    byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
-
-    System.arraycopy(digestBytes, 0, hashPlusSalt, 0, digestBytes.length);
-    System.arraycopy(saltBytes, 0, hashPlusSalt, digestBytes.length,
-                     NUM_SALT_BYTES);
-
-    return "{" + STORAGE_SCHEME_NAME_PBKDF2 + "}" + iterations + ":" +
-      Base64.encode(hashPlusSalt);
   }
 
 }
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java
index a99de0c..014324f 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java
@@ -26,6 +26,14 @@
  */
 package org.opends.server.extensions;
 
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.KeySpec;
+import java.util.Arrays;
+
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.ByteSequence;
@@ -38,16 +46,9 @@
 import org.opends.server.types.InitializationException;
 import org.opends.server.util.Base64;
 
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.spec.KeySpec;
-import java.util.Arrays;
-
 import static org.opends.messages.ExtensionMessages.*;
 import static org.opends.server.extensions.ExtensionsConstants.*;
-import static org.opends.server.util.StaticUtils.getExceptionMessage;
+import static org.opends.server.util.StaticUtils.*;
 
 /**
  * This class defines a Directory Server password storage scheme based on the
@@ -63,9 +64,7 @@
 {
     private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
-  /**
-   * The fully-qualified name of this class.
-   */
+  /** The fully-qualified name of this class. */
   private static final String CLASS_NAME =
       "org.opends.server.extensions.PKCS5S2PasswordStorageScheme";
 
@@ -76,29 +75,19 @@
    */
   private static final int NUM_SALT_BYTES = 16;
 
-  /**
-   * The number of bytes the SHA-1 algorithm produces.
-   */
+  /** The number of bytes the SHA-1 algorithm produces. */
   private static final int SHA1_LENGTH = 32;
 
-  /**
-   *  Atlassian hardcoded the number of iterations to 10000.
-   */
+  /** Atlassian hardcoded the number of iterations to 10000. */
   private static final int iterations = 10000;
 
-  /**
-   * The factory used to generate the PKCS5S2 hashes.
-   */
+  /** The factory used to generate the PKCS5S2 hashes. */
   private SecretKeyFactory factory;
 
-  /**
-   * The lock used to provide thread-safe access to the message digest.
-   */
+  /** The lock used to provide thread-safe access to the message digest. */
   private final Object factoryLock = new Object();
 
-  /**
-   *  The secure random number generator to use to generate the salt values.
-   */
+  /** The secure random number generator to use to generate the salt values. */
   private SecureRandom random;
 
 
@@ -112,12 +101,8 @@
     super();
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public void initializePasswordStorageScheme(
       PKCS5S2PasswordStorageSchemeCfg configuration)
       throws InitializationException
@@ -133,21 +118,15 @@
     }
   }
 
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public String getStorageSchemeName()
   {
     return STORAGE_SCHEME_NAME_PKCS5S2;
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public ByteString encodePassword(ByteSequence plaintext)
       throws DirectoryException
   {
@@ -159,32 +138,21 @@
     return ByteString.valueOf(Base64.encode(hashPlusSalt));
   }
 
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public ByteString encodePasswordWithScheme(ByteSequence plaintext)
       throws DirectoryException
   {
-    return ByteString.valueOf("{" + STORAGE_SCHEME_NAME_PKCS5S2 + '}'
+    return ByteString.valueOf('{' + STORAGE_SCHEME_NAME_PKCS5S2 + '}'
         + encodePassword(plaintext));
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public boolean passwordMatches(ByteSequence plaintextPassword,
                                  ByteSequence storedPassword)
   {
-
     // Base64-decode the value and take the first 16 bytes as the salt.
-    byte[] saltBytes = new byte[NUM_SALT_BYTES];
-    final int saltLength = NUM_SALT_BYTES;
-    byte[] digestBytes = new byte[SHA1_LENGTH];
     try
     {
       String stored = storedPassword.toString();
@@ -197,9 +165,13 @@
             storedPassword.toString()));
         return false;
       }
+
+      final int saltLength = NUM_SALT_BYTES;
+      byte[] saltBytes = new byte[saltLength];
+      byte[] digestBytes = new byte[SHA1_LENGTH];
       System.arraycopy(decodedBytes, 0, saltBytes, 0, saltLength);
-      System.arraycopy(decodedBytes, saltLength, digestBytes, 0,
-          SHA1_LENGTH);
+      System.arraycopy(decodedBytes, saltLength, digestBytes, 0, SHA1_LENGTH);
+      return encodeAndMatch(plaintextPassword, saltBytes, digestBytes, iterations);
     }
     catch (Exception e)
     {
@@ -208,102 +180,68 @@
           storedPassword.toString(), String.valueOf(e)));
       return false;
     }
-
-    return encodeAndMatch(plaintextPassword, saltBytes, digestBytes, iterations);
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public boolean supportsAuthPasswordSyntax()
   {
     return true;
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public String getAuthPasswordSchemeName()
   {
     return AUTH_PASSWORD_SCHEME_NAME_PKCS5S2;
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public ByteString encodeAuthPassword(ByteSequence plaintext)
       throws DirectoryException
   {
     byte[] saltBytes      = new byte[NUM_SALT_BYTES];
     byte[] digestBytes = createRandomSaltAndEncode(plaintext, saltBytes);
     // Encode and return the value.
-    return ByteString.valueOf(AUTH_PASSWORD_SCHEME_NAME_PKCS5S2 + '$' +
-        iterations + ':' + Base64.encode(saltBytes) +
-        '$' + Base64.encode(digestBytes));
+    return ByteString.valueOf(AUTH_PASSWORD_SCHEME_NAME_PKCS5S2 + '$'
+        + iterations + ':' + Base64.encode(saltBytes) + '$'
+        + Base64.encode(digestBytes));
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public boolean authPasswordMatches(ByteSequence plaintextPassword,
                                      String authInfo, String authValue)
   {
-    byte[] saltBytes;
-    byte[] digestBytes;
-    int    iterations;
-
     try
     {
-      int pos = 0;
-      int length = authInfo.length();
-      while (pos < length && authInfo.charAt(pos) != ':')
+      int pos = authInfo.indexOf(':');
+      if (pos == -1)
       {
-        pos++;
+        return false;
       }
-      if (pos >= (length - 1) || pos == 0)
-        throw new Exception();
-      iterations = Integer.parseInt(authInfo.substring(0, pos));
-      saltBytes   = Base64.decode(authInfo.substring(pos + 1));
-      digestBytes = Base64.decode(authValue);
+      int iterations = Integer.parseInt(authInfo.substring(0, pos));
+      byte[] saltBytes   = Base64.decode(authInfo.substring(pos + 1));
+      byte[] digestBytes = Base64.decode(authValue);
+      return encodeAndMatch(plaintextPassword, saltBytes, digestBytes, iterations);
     }
     catch (Exception e)
     {
-        logger.traceException(e);
-        return false;
+      logger.traceException(e);
+      return false;
     }
-
-    return encodeAndMatch(plaintextPassword, saltBytes, digestBytes, iterations);
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public boolean isReversible()
   {
     return false;
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public ByteString getPlaintextValue(ByteSequence storedPassword)
       throws DirectoryException
   {
@@ -312,12 +250,8 @@
     throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public ByteString getAuthPasswordPlaintextValue(String authInfo,
                                                   String authValue)
       throws DirectoryException
@@ -327,12 +261,8 @@
     throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
+  /** {@inheritDoc} */
+  @Override
   public boolean isStorageSchemeSecure()
   {
     return true;
@@ -351,7 +281,7 @@
    * @return  The encoded password string, including the scheme name in curly
    *          braces.
    *
-   * @throws  org.opends.server.types.DirectoryException  If a problem occurs during processing.
+   * @throws  DirectoryException  If a problem occurs during processing.
    */
   public static String encodeOffline(byte[] passwordBytes)
       throws DirectoryException
@@ -382,7 +312,7 @@
     // Append the hashed value to the salt and base64-the whole thing.
     byte[] hashPlusSalt = concatenateSaltPlusHash(saltBytes, digestBytes);
 
-    return "{" + STORAGE_SCHEME_NAME_PKCS5S2 + "}"  +
+    return '{' + STORAGE_SCHEME_NAME_PKCS5S2 + '}' +
         Base64.encode(hashPlusSalt);
   }
 
@@ -390,33 +320,27 @@
   private boolean encodeAndMatch(ByteSequence plaintext,
                                  byte[] saltBytes, byte[] digestBytes, int iterations)
   {
-    byte[] userDigestBytes;
-
     try
     {
-      userDigestBytes = encodeWithSalt(plaintext, saltBytes, iterations);
+      byte[] userDigestBytes = encodeWithSalt(plaintext, saltBytes, iterations);
+      return Arrays.equals(digestBytes, userDigestBytes);
     }
     catch (Exception e)
     {
-        return false;
+      return false;
     }
-    return Arrays.equals(digestBytes, userDigestBytes);
   }
 
 
   private byte[] createRandomSaltAndEncode(ByteSequence plaintext, byte[] saltBytes) throws DirectoryException {
-    byte[] digestBytes;
-
     synchronized(factoryLock)
     {
       random.nextBytes(saltBytes);
-      digestBytes = encodeWithSalt(plaintext, saltBytes, iterations);
+      return encodeWithSalt(plaintext, saltBytes, iterations);
     }
-    return digestBytes;
   }
 
   private byte[] encodeWithSalt(ByteSequence plaintext, byte[] saltBytes, int iterations) throws DirectoryException {
-    byte[] digestBytes;
     char[] plaintextChars = null;
     try
     {
@@ -424,7 +348,7 @@
       KeySpec spec = new PBEKeySpec(
           plaintextChars, saltBytes,
           iterations, SHA1_LENGTH * 8);
-      digestBytes = factory.generateSecret(spec).getEncoded();
+      return factory.generateSecret(spec).getEncoded();
     }
     catch (Exception e)
     {
@@ -442,7 +366,6 @@
         Arrays.fill(plaintextChars, '0');
       }
     }
-    return digestBytes;
   }
 
   private static byte[] concatenateSaltPlusHash(byte[] saltBytes, byte[] digestBytes) {
diff --git a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PBKDF2PasswordStorageSchemeTestCase.java b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PBKDF2PasswordStorageSchemeTestCase.java
new file mode 100644
index 0000000..6bf6828
--- /dev/null
+++ b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PBKDF2PasswordStorageSchemeTestCase.java
@@ -0,0 +1,87 @@
+/*
+ * 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
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 2014 ForgeRock AS.
+ */
+package org.opends.server.extensions;
+
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.PBKDF2PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.PBKDF2PasswordStorageSchemeCfg;
+import org.opends.server.api.PasswordStorageScheme;
+import org.testng.annotations.DataProvider;
+
+/**
+ * A set of test cases for the PBKDF2 password storage scheme.
+ */
+public class PBKDF2PasswordStorageSchemeTestCase
+       extends PasswordStorageSchemeTestCase
+{
+  /** Creates a new instance of this storage scheme test case.   */
+  public PBKDF2PasswordStorageSchemeTestCase()
+  {
+    super("cn=PBKDF2,cn=Password Storage Schemes,cn=config");
+  }
+
+  /**
+   * Retrieves a set of passwords that may be used to test the password storage scheme.
+   *
+   * @return  A set of passwords that may be used to test the password storage scheme.
+   */
+  @Override
+  @DataProvider(name = "testPasswords")
+  public Object[][] getTestPasswords()
+  {
+    final Object[][] testPasswords = super.getTestPasswords();
+
+    // JDK Bug 6879540. Empty passwords are not accepted when generating PBESpecKey.
+    // The bug is present in Java 6 and some version of Java 7.
+    final int newLength = testPasswords.length - 2;
+    final Object[][] results = new Object[newLength][];
+    System.arraycopy(testPasswords, 2, results, 0, newLength);
+    return results;
+  }
+
+
+  /**
+   * Retrieves an initialized instance of this password storage scheme.
+   *
+   * @return  An initialized instance of this password storage scheme.
+   */
+  @Override
+  protected PasswordStorageScheme<?> getScheme() throws Exception
+  {
+    PBKDF2PasswordStorageScheme scheme =
+         new PBKDF2PasswordStorageScheme();
+
+    PBKDF2PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+              PBKDF2PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry()
+          );
+
+    scheme.initializePasswordStorageScheme(configuration);
+    return scheme;
+  }
+
+}
diff --git a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageSchemeTestCase.java b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageSchemeTestCase.java
index dfac4e3..6df2e8f 100644
--- a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageSchemeTestCase.java
+++ b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageSchemeTestCase.java
@@ -25,7 +25,6 @@
  */
 package org.opends.server.extensions;
 
-
 import org.opends.server.TestCaseUtils;
 import org.opends.server.admin.server.AdminTestCaseUtils;
 import org.opends.server.admin.std.meta.PKCS5S2PasswordStorageSchemeCfgDefn;
@@ -35,12 +34,12 @@
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-import static org.testng.Assert.assertTrue;
-
+import static org.testng.Assert.*;
 
 /**
  * A set of test cases for the PKCS5S2 password storage scheme.
  */
+@SuppressWarnings("javadoc")
 public class PKCS5S2PasswordStorageSchemeTestCase
        extends PasswordStorageSchemeTestCase
 {
@@ -52,17 +51,33 @@
     super("cn=PKCS5S2,cn=Password Storage Schemes,cn=config");
   }
 
+  /**
+   * Retrieves a set of passwords that may be used to test the password storage scheme.
+   *
+   * @return  A set of passwords that may be used to test the password storage scheme.
+   */
+  @Override
+  @DataProvider(name = "testPasswords")
+  public Object[][] getTestPasswords()
+  {
+    final Object[][] testPasswords = super.getTestPasswords();
+
+    // JDK Bug 6879540. Empty passwords are not accepted when generating PBESpecKey.
+    // The bug is present in Java 6 and some version of Java 7.
+    final int newLength = testPasswords.length - 2;
+    final Object[][] results = new Object[newLength][];
+    System.arraycopy(testPasswords, 2, results, 0, newLength);
+    return results;
+  }
 
 
   /**
    * Retrieves an initialized instance of this password storage scheme.
    *
    * @return  An initialized instance of this password storage scheme.
-   *
-   * @throws  Exception  If an unexpected problem occurs.
    */
-  protected PasswordStorageScheme getScheme()
-         throws Exception
+  @Override
+  protected PasswordStorageScheme<?> getScheme() throws Exception
   {
     PKCS5S2PasswordStorageScheme scheme =
          new PKCS5S2PasswordStorageScheme();
@@ -86,10 +101,8 @@
    * @return  A set of couple (cleartext, encrypted) passwords that
    *          may be used to test the PKCS5S2 password storage scheme
    */
-
   @DataProvider(name = "testPKCS5S2Passwords")
-  public Object[][] getTestPKCS5S2Passwords()
-         throws Exception
+  public Object[][] getTestPKCS5S2Passwords() throws Exception
   {
     return new Object[][]
     {
@@ -131,7 +144,6 @@
     boolean allowPreencodedDefault = setAllowPreencodedPasswords(true);
 
     try {
-
       Entry userEntry = TestCaseUtils.makeEntry(
        "dn: uid=testPKCS5S2.user,o=test",
        "objectClass: top",
@@ -146,8 +158,7 @@
 
       TestCaseUtils.addEntry(userEntry);
 
-      assertTrue(TestCaseUtils.canBind("uid=testPKCS5S2.user,o=test",
-                  plaintextPassword),
+      assertTrue(TestCaseUtils.canBind("uid=testPKCS5S2.user,o=test", plaintextPassword),
                "Failed to bind when pre-encoded password = \"" +
                encodedPassword + "\" and " +
                "plaintext password = \"" +
@@ -158,4 +169,3 @@
   }
 
 }
-

--
Gitblit v1.10.0