From e3deb8b9b6b1e1fbf53309380f5b30da848c507f Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Fri, 12 Sep 2014 14:36:55 +0000
Subject: [PATCH] CR-4097 Big code cleanup of some storage schemes.

---
 opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java |  131 ++++++++++++++++++++++---------------------
 1 files changed, 67 insertions(+), 64 deletions(-)

diff --git a/opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java b/opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java
index 014324f..beb1543 100644
--- a/opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java
+++ b/opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java
@@ -90,7 +90,6 @@
   /** The secure random number generator to use to generate the salt values. */
   private SecureRandom random;
 
-
   /**
    * Creates a new instance of this password storage scheme.  Note that no
    * initialization should be performed here, as all initialization should be
@@ -131,8 +130,7 @@
       throws DirectoryException
   {
     byte[] saltBytes      = new byte[NUM_SALT_BYTES];
-    byte[] digestBytes = createRandomSaltAndEncode(plaintext, saltBytes);
-    // Append the hashed value to the salt and base64-the whole thing.
+    byte[] digestBytes = encodeWithRandomSalt(plaintext, saltBytes);
     byte[] hashPlusSalt = concatenateSaltPlusHash(saltBytes, digestBytes);
 
     return ByteString.valueOf(Base64.encode(hashPlusSalt));
@@ -156,7 +154,6 @@
     try
     {
       String stored = storedPassword.toString();
-
       byte[] decodedBytes = Base64.decode(stored);
 
       if (decodedBytes.length != NUM_SALT_BYTES + SHA1_LENGTH)
@@ -167,8 +164,8 @@
       }
 
       final int saltLength = NUM_SALT_BYTES;
-      byte[] saltBytes = new byte[saltLength];
-      byte[] digestBytes = new byte[SHA1_LENGTH];
+      final byte[] digestBytes = new byte[SHA1_LENGTH];
+      final byte[] saltBytes = new byte[saltLength];
       System.arraycopy(decodedBytes, 0, saltBytes, 0, saltLength);
       System.arraycopy(decodedBytes, saltLength, digestBytes, 0, SHA1_LENGTH);
       return encodeAndMatch(plaintextPassword, saltBytes, digestBytes, iterations);
@@ -202,7 +199,7 @@
       throws DirectoryException
   {
     byte[] saltBytes      = new byte[NUM_SALT_BYTES];
-    byte[] digestBytes = createRandomSaltAndEncode(plaintext, saltBytes);
+    byte[] digestBytes = encodeWithRandomSalt(plaintext, saltBytes);
     // Encode and return the value.
     return ByteString.valueOf(AUTH_PASSWORD_SCHEME_NAME_PKCS5S2 + '$'
         + iterations + ':' + Base64.encode(saltBytes) + '$'
@@ -219,7 +216,7 @@
       int pos = authInfo.indexOf(':');
       if (pos == -1)
       {
-        return false;
+        throw new Exception();
       }
       int iterations = Integer.parseInt(authInfo.substring(0, pos));
       byte[] saltBytes   = Base64.decode(authInfo.substring(pos + 1));
@@ -277,87 +274,53 @@
    * 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.
    */
   public static String encodeOffline(byte[] passwordBytes)
       throws DirectoryException
   {
     byte[] saltBytes = new byte[NUM_SALT_BYTES];
-    byte[] digestBytes;
-
-    try
-    {
-      SecureRandom.getInstance(SECURE_PRNG_SHA1).nextBytes(saltBytes);
-
-      char[] plaintextChars = Arrays.toString(passwordBytes).toCharArray();
-      KeySpec spec = new PBEKeySpec(plaintextChars, saltBytes,iterations,
-          SHA1_LENGTH * 8);
-      digestBytes = SecretKeyFactory
-          .getInstance(MESSAGE_DIGEST_ALGORITHM_PBKDF2)
-          .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);
-    }
-
-    // Append the hashed value to the salt and base64-the whole thing.
+    byte[] digestBytes = encodeWithRandomSalt(ByteString.wrap(passwordBytes), saltBytes);
     byte[] hashPlusSalt = concatenateSaltPlusHash(saltBytes, digestBytes);
 
     return '{' + STORAGE_SCHEME_NAME_PKCS5S2 + '}' +
         Base64.encode(hashPlusSalt);
   }
 
-
-  private boolean encodeAndMatch(ByteSequence plaintext,
-                                 byte[] saltBytes, byte[] digestBytes, int iterations)
+  private static byte[] encodeWithRandomSalt(ByteString plaintext, byte[] saltBytes)
+      throws DirectoryException
   {
     try
     {
-      byte[] userDigestBytes = encodeWithSalt(plaintext, saltBytes, iterations);
-      return Arrays.equals(digestBytes, userDigestBytes);
+      final SecureRandom random = SecureRandom.getInstance(SECURE_PRNG_SHA1);
+      final SecretKeyFactory factory = SecretKeyFactory.getInstance(MESSAGE_DIGEST_ALGORITHM_PBKDF2);
+      return encodeWithRandomSalt(plaintext, saltBytes, random, factory);
+    }
+    catch (DirectoryException e)
+    {
+      throw e;
     }
     catch (Exception e)
     {
-      return false;
+      throw cannotEncodePassword(e);
     }
   }
 
-
-  private byte[] createRandomSaltAndEncode(ByteSequence plaintext, byte[] saltBytes) throws DirectoryException {
-    synchronized(factoryLock)
-    {
-      random.nextBytes(saltBytes);
-      return encodeWithSalt(plaintext, saltBytes, iterations);
-    }
-  }
-
-  private byte[] encodeWithSalt(ByteSequence plaintext, byte[] saltBytes, int iterations) throws DirectoryException {
-    char[] plaintextChars = null;
+  private static byte[] encodeWithSalt(ByteSequence plaintext, byte[] saltBytes,
+      int iterations, final SecretKeyFactory factory) throws DirectoryException
+  {
+    final char[] plaintextChars = plaintext.toString().toCharArray();
     try
     {
-      plaintextChars = plaintext.toString().toCharArray();
-      KeySpec spec = new PBEKeySpec(
-          plaintextChars, saltBytes,
-          iterations, SHA1_LENGTH * 8);
+      KeySpec spec =
+          new PBEKeySpec(plaintextChars, saltBytes, iterations, SHA1_LENGTH * 8);
       return 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);
+      throw cannotEncodePassword(e);
     }
     finally
     {
@@ -368,12 +331,52 @@
     }
   }
 
-  private static byte[] concatenateSaltPlusHash(byte[] saltBytes, byte[] digestBytes) {
-    byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
+  private boolean encodeAndMatch(ByteSequence plaintext, byte[] saltBytes,
+      byte[] digestBytes, int iterations)
+  {
+    synchronized (factoryLock)
+    {
+      try
+      {
+        final byte[] userDigestBytes =
+            encodeWithSalt(plaintext, saltBytes, iterations, factory);
+        return Arrays.equals(digestBytes, userDigestBytes);
+      }
+      catch (Exception e)
+      {
+        return false;
+      }
+    }
+  }
 
+  private byte[] encodeWithRandomSalt(ByteSequence plaintext, byte[] saltBytes)
+      throws DirectoryException
+  {
+    synchronized (factoryLock)
+    {
+      return encodeWithRandomSalt(plaintext, saltBytes, random, factory);
+    }
+  }
+
+  private static byte[] encodeWithRandomSalt(ByteSequence plaintext, byte[] saltBytes,
+      SecureRandom random, final SecretKeyFactory factory) throws DirectoryException
+  {
+    random.nextBytes(saltBytes);
+    return encodeWithSalt(plaintext, saltBytes, iterations, factory);
+  }
+
+  private static DirectoryException cannotEncodePassword(Exception e)
+  {
+    logger.traceException(e);
+
+    LocalizableMessage message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get(CLASS_NAME, getExceptionMessage(e));
+    return new DirectoryException(DirectoryServer.getServerErrorResultCode(), message, e);
+  }
+
+  private static byte[] concatenateSaltPlusHash(byte[] saltBytes, byte[] digestBytes) {
+    final byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
     System.arraycopy(saltBytes, 0, hashPlusSalt, 0, NUM_SALT_BYTES);
-    System.arraycopy(digestBytes, 0, hashPlusSalt, NUM_SALT_BYTES,
-        digestBytes.length);
+    System.arraycopy(digestBytes, 0, hashPlusSalt, NUM_SALT_BYTES, digestBytes.length);
     return hashPlusSalt;
   }
 

--
Gitblit v1.10.0