You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by se...@apache.org on 2016/02/21 10:26:16 UTC
svn commit: r1731515 - in /directory/shared/trunk/ldap/model/src:
main/java/org/apache/directory/api/ldap/model/password/
test/java/org/apache/directory/api/ldap/model/password/
Author: seelmann
Date: Sun Feb 21 09:26:15 2016
New Revision: 1731515
URL: http://svn.apache.org/viewvc?rev=1731515&view=rev
Log:
* Cleanup PasswordUtil class and add tests
* Replace EncryptionMethod class with immutable PasswordDetails
Added:
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordDetails.java (with props)
Removed:
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/EncryptionMethod.java
Modified:
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java
directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java
Added: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordDetails.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordDetails.java?rev=1731515&view=auto
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordDetails.java (added)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordDetails.java Sun Feb 21 09:26:15 2016
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.directory.api.ldap.model.password;
+
+
+import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
+
+
+/**
+ * A class to store all informations about an password.
+ *
+ * This includes:
+ * - the used algorithm
+ * - the salt if any
+ * - the password itself.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordDetails
+{
+ private final LdapSecurityConstants algorithm;
+ private final byte[] salt;
+ private final byte[] password;
+
+
+ public PasswordDetails( LdapSecurityConstants algorithm, byte[] salt, byte[] password )
+ {
+ this.algorithm = algorithm;
+ this.salt = salt;
+ this.password = password;
+ }
+
+
+ /**
+ * The hash algorithm used to hash the password, null for plain text passwords.
+ *
+ * @return the hash algorithm used to hash the password, null for plain text passwords
+ */
+ public LdapSecurityConstants getAlgorithm()
+ {
+ return algorithm;
+ }
+
+
+ /**
+ * The salt used to hash the password, null if no salt was used.
+ *
+ * @return the salt used to hash the password, null if no salt was used
+ */
+ public byte[] getSalt()
+ {
+ return salt;
+ }
+
+
+ /**
+ * The hashed or plain text password.
+ *
+ * @return the hashed or plain text password
+ */
+ public byte[] getPassword()
+ {
+ return password;
+ }
+
+}
Propchange: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordDetails.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java?rev=1731515&r1=1731514&r2=1731515&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java (original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java Sun Feb 21 09:26:15 2016
@@ -144,6 +144,12 @@ public final class PasswordUtil
*/
public static byte[] createStoragePassword( byte[] credentials, LdapSecurityConstants algorithm )
{
+ // check plain text password
+ if ( algorithm == null )
+ {
+ return credentials;
+ }
+
byte[] salt;
switch ( algorithm )
@@ -264,21 +270,19 @@ public final class PasswordUtil
if ( algorithm != null )
{
- EncryptionMethod encryptionMethod = new EncryptionMethod( algorithm, null );
-
// Let's get the encrypted part of the stored password
// We should just keep the password, excluding the algorithm
// and the salt, if any.
// But we should also get the algorithm and salt to
// be able to encrypt the submitted user password in the next step
- byte[] encryptedStored = PasswordUtil.splitCredentials( storedCredentials, encryptionMethod );
+ PasswordDetails passwordDetails = PasswordUtil.splitCredentials( storedCredentials );
// Reuse the saltedPassword informations to construct the encrypted
// password given by the user.
- byte[] userPassword = PasswordUtil.encryptPassword( receivedCredentials, encryptionMethod.getAlgorithm(),
- encryptionMethod.getSalt() );
+ byte[] userPassword = PasswordUtil.encryptPassword( receivedCredentials, passwordDetails.getAlgorithm(),
+ passwordDetails.getSalt() );
- return compareBytes( userPassword, encryptedStored );
+ return compareBytes( userPassword, passwordDetails.getPassword() );
}
else
{
@@ -419,66 +423,57 @@ public final class PasswordUtil
* @return The password
* @param credentials the credentials to split
*/
- public static byte[] splitCredentials( byte[] credentials, EncryptionMethod encryptionMethod )
+ public static PasswordDetails splitCredentials( byte[] credentials )
{
- int algoLength = encryptionMethod.getAlgorithm().getPrefix().length() + 2;
+ LdapSecurityConstants algorithm = findAlgorithm( credentials );
- switch ( encryptionMethod.getAlgorithm() )
+ // check plain text password
+ if ( algorithm == null )
{
- case HASH_METHOD_MD5:
- case HASH_METHOD_SHA:
- // We just have the password just after the algorithm, base64 encoded.
- // Just decode the password and return it.
- return Base64.decode(
- Strings.utf8ToString( credentials, algoLength, credentials.length - algoLength ).toCharArray() );
+ return new PasswordDetails( null, null, credentials );
+ }
- case HASH_METHOD_SMD5:
- // The password is associated with a salt. Decompose it
- // in two parts, after having decoded the password.
- // The salt will be stored into the EncryptionMethod structure
- // The salt is at the end of the credentials, and is 8 bytes long
- byte[] passwordAndSalt = Base64.decode(
- Strings.utf8ToString( credentials, algoLength, credentials.length - algoLength ).toCharArray() );
-
- int saltLength = passwordAndSalt.length - MD5_LENGTH;
- encryptionMethod.setSalt( new byte[saltLength] );
- byte[] password = new byte[MD5_LENGTH];
- split( passwordAndSalt, 0, password, encryptionMethod.getSalt() );
+ int algoLength = algorithm.getPrefix().length() + 2;
+ byte[] password = null;
- return password;
+ switch ( algorithm )
+ {
+ case HASH_METHOD_MD5:
+ case HASH_METHOD_SMD5:
+ return getCredentials( credentials, algoLength, MD5_LENGTH, algorithm );
+ case HASH_METHOD_SHA:
case HASH_METHOD_SSHA:
- return getCredentials( credentials, algoLength, SHA1_LENGTH, encryptionMethod );
+ return getCredentials( credentials, algoLength, SHA1_LENGTH, algorithm );
case HASH_METHOD_SHA256:
case HASH_METHOD_SSHA256:
- return getCredentials( credentials, algoLength, SHA256_LENGTH, encryptionMethod );
+ return getCredentials( credentials, algoLength, SHA256_LENGTH, algorithm );
case HASH_METHOD_SHA384:
case HASH_METHOD_SSHA384:
- return getCredentials( credentials, algoLength, SHA384_LENGTH, encryptionMethod );
+ return getCredentials( credentials, algoLength, SHA384_LENGTH, algorithm );
case HASH_METHOD_SHA512:
case HASH_METHOD_SSHA512:
- return getCredentials( credentials, algoLength, SHA512_LENGTH, encryptionMethod );
+ return getCredentials( credentials, algoLength, SHA512_LENGTH, algorithm );
case HASH_METHOD_PKCS5S2:
- return getPbkdf2Credentials( credentials, algoLength, encryptionMethod );
+ return getPbkdf2Credentials( credentials, algoLength, algorithm );
case HASH_METHOD_CRYPT:
// The password is associated with a salt. Decompose it
// in two parts, storing the salt into the EncryptionMethod structure.
// The salt comes first, not like for SSHA and SMD5, and is 2 bytes long
- encryptionMethod.setSalt( new byte[2] );
- byte[] password2 = new byte[credentials.length - encryptionMethod.getSalt().length - algoLength];
- split( credentials, algoLength, encryptionMethod.getSalt(), password2 );
+ byte[] salt = new byte[2];
+ password = new byte[credentials.length - salt.length - algoLength];
+ split( credentials, algoLength, salt, password );
- return password2;
+ return new PasswordDetails( algorithm, salt, password );
default:
// unknown method
- return credentials;
-
+ throw new IllegalArgumentException( "Unknown hash algorithm " + algorithm );
}
}
@@ -486,8 +481,8 @@ public final class PasswordUtil
/**
* Compute the credentials
*/
- private static byte[] getCredentials( byte[] credentials, int algoLength, int hashLen,
- EncryptionMethod encryptionMethod )
+ private static PasswordDetails getCredentials( byte[] credentials, int algoLength, int hashLen,
+ LdapSecurityConstants algorithm )
{
// The password is associated with a salt. Decompose it
// in two parts, after having decoded the password.
@@ -497,18 +492,21 @@ public final class PasswordUtil
.decode( Strings.utf8ToString( credentials, algoLength, credentials.length - algoLength ).toCharArray() );
int saltLength = passwordAndSalt.length - hashLen;
- encryptionMethod.setSalt( new byte[saltLength] );
+ byte[] salt = saltLength == 0 ? null : new byte[saltLength];
byte[] password = new byte[hashLen];
- split( passwordAndSalt, 0, password, encryptionMethod.getSalt() );
+ split( passwordAndSalt, 0, password, salt );
- return password;
+ return new PasswordDetails( algorithm, salt, password );
}
private static void split( byte[] all, int offset, byte[] left, byte[] right )
{
System.arraycopy( all, offset, left, 0, left.length );
- System.arraycopy( all, offset + left.length, right, 0, right.length );
+ if ( right != null )
+ {
+ System.arraycopy( all, offset + left.length, right, 0, right.length );
+ }
}
@@ -579,7 +577,7 @@ public final class PasswordUtil
* Gets the credentials from a PKCS5S2 hash.
* The salt for PKCS5S2 hash is prepended to the password
*/
- private static byte[] getPbkdf2Credentials( byte[] credentials, int algoLength, EncryptionMethod encryptionMethod )
+ private static PasswordDetails getPbkdf2Credentials( byte[] credentials, int algoLength, LdapSecurityConstants algorithm )
{
// The password is associated with a salt. Decompose it
// in two parts, after having decoded the password.
@@ -589,12 +587,12 @@ public final class PasswordUtil
.decode( Strings.utf8ToString( credentials, algoLength, credentials.length - algoLength ).toCharArray() );
int saltLength = passwordAndSalt.length - PKCS5S2_LENGTH;
- encryptionMethod.setSalt( new byte[saltLength] );
+ byte[] salt = new byte[saltLength];
byte[] password = new byte[PKCS5S2_LENGTH];
- split( passwordAndSalt, 0, encryptionMethod.getSalt(), password );
+ split( passwordAndSalt, 0, salt, password );
- return password;
+ return new PasswordDetails( algorithm, salt, password );
}
}
Modified: directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java?rev=1731515&r1=1731514&r2=1731515&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java (original)
+++ directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/password/PasswordUtilTest.java Sun Feb 21 09:26:15 2016
@@ -20,12 +20,36 @@
package org.apache.directory.api.ldap.model.password;
-import static org.junit.Assert.assertTrue;
+
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_CRYPT;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_MD5;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_PKCS5S2;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SHA;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SHA256;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SHA384;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SHA512;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SMD5;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SSHA;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SSHA256;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SSHA384;
+import static org.apache.directory.api.ldap.model.constants.LdapSecurityConstants.HASH_METHOD_SSHA512;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.MD5_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.PKCS5S2_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.SHA1_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.SHA256_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.SHA384_LENGTH;
+import static org.apache.directory.api.ldap.model.password.PasswordUtil.SHA512_LENGTH;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
import org.apache.directory.api.util.Strings;
import org.junit.Test;
+
/**
* A test for the PasswordUtil class.
*
@@ -39,21 +63,258 @@ public class PasswordUtilTest
{
// Simple cases
assertTrue( PasswordUtil.compareCredentials( null, null ) );
- assertTrue( PasswordUtil.compareCredentials( new byte[]{}, new byte[]{} ) );
- assertTrue( PasswordUtil.compareCredentials( new byte[]{ 0x01 }, new byte[]{ 0x01 } ) );
-
+ assertTrue( PasswordUtil.compareCredentials( new byte[]
+ {}, new byte[]
+ {} ) );
+ assertTrue( PasswordUtil.compareCredentials( new byte[]
+ { 0x01 }, new byte[]
+ { 0x01 } ) );
+
// Simple failures
- assertFalse( PasswordUtil.compareCredentials( null, new byte[]{ 0x01 } ) );
- assertFalse( PasswordUtil.compareCredentials( new byte[]{ 0x01 }, null ) );
- assertFalse( PasswordUtil.compareCredentials( new byte[]{ 0x01 }, new byte[]{ 0x02 } ) );
-
+ assertFalse( PasswordUtil.compareCredentials( null, new byte[]
+ { 0x01 } ) );
+ assertFalse( PasswordUtil.compareCredentials( new byte[]
+ { 0x01 }, null ) );
+ assertFalse( PasswordUtil.compareCredentials( new byte[]
+ { 0x01 }, new byte[]
+ { 0x02 } ) );
+
// With some different lengths
- assertFalse( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ), Strings.getBytesUtf8( "Password1 " ) ) );
+ assertFalse( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ),
+ Strings.getBytesUtf8( "Password1 " ) ) );
// With different passwords
- assertFalse( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ), Strings.getBytesUtf8( "password1" ) ) );
+ assertFalse( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ),
+ Strings.getBytesUtf8( "password1" ) ) );
// With same passwords
- assertTrue( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ), Strings.getBytesUtf8( "Password1" ) ) );
+ assertTrue( PasswordUtil.compareCredentials( Strings.getBytesUtf8( "Password1" ),
+ Strings.getBytesUtf8( "Password1" ) ) );
+ }
+
+
+ @Test
+ public void testPasswordPlainText()
+ {
+ testPassword( "secret", "secret", null, 6, 0 );
+ }
+
+
+ @Test
+ public void testPasswordMD5Encrypted()
+ {
+ testPassword( "secret", "{MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ==", HASH_METHOD_MD5, MD5_LENGTH, 0 );
+ }
+
+
+ @Test
+ public void testPasswordMD5EncryptedLowercase()
+ {
+ testPassword( "secret", "{md5}Xr4ilOzQ4PCOq3aQ0qbuaQ==", HASH_METHOD_MD5, MD5_LENGTH, 0 );
+ }
+
+
+ @Test
+ public void testPasswordSMD5Encrypted()
+ {
+ testPassword( "secret", "{SMD5}tQ9wo/VBuKsqBtylMMCcORbnYOJFMyDJ", HASH_METHOD_SMD5, MD5_LENGTH, 8 );
+ }
+
+
+ @Test
+ public void testPasswordSMD5EncryptedLowercase()
+ {
+ testPassword( "secret", "{smd5}tQ9wo/VBuKsqBtylMMCcORbnYOJFMyDJ", HASH_METHOD_SMD5, MD5_LENGTH, 8 );
+ }
+
+
+ @Test
+ public void testPasswordSHAEncrypted()
+ {
+ testPassword( "secret", "{SHA}5en6G6MezRroT3XKqkdPOmY/BfQ=", HASH_METHOD_SHA, SHA1_LENGTH, 0 );
+ }
+
+
+ @Test
+ public void testPasswordSHAEncryptedLowercase()
+ {
+ testPassword( "secret", "{sha}5en6G6MezRroT3XKqkdPOmY/BfQ=", HASH_METHOD_SHA, SHA1_LENGTH, 0 );
+ }
+
+
+ @Test
+ public void testPasswordSSHAEncrypted()
+ {
+ testPassword( "secret", "{SSHA}mjVVxasFkk59wMW4L1Ldt+YCblfhULHs03WW7g==", HASH_METHOD_SSHA, SHA1_LENGTH, 8 );
}
+
+
+ @Test
+ public void testPasswordSSHAEncryptedLowercase()
+ {
+ testPassword( "secret", "{ssha}mjVVxasFkk59wMW4L1Ldt+YCblfhULHs03WW7g==", HASH_METHOD_SSHA, SHA1_LENGTH, 8 );
+ }
+
+
+ @Test
+ public void testPasswordSHA256Encrypted()
+ {
+ testPassword( "secret", "{SHA256}K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=", HASH_METHOD_SHA256,
+ SHA256_LENGTH, 0 );
+ }
+
+
+ @Test
+ public void testPasswordSHA256EncryptedLowercase()
+ {
+ testPassword( "secret", "{sha256}K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=",
+ HASH_METHOD_SHA256, SHA256_LENGTH, 0 );
+ }
+
+
+ @Test
+ public void testPasswordSSHA256Encrypted()
+ {
+ testPassword( "secret", "{SSHA256}MVfpHvqPUIXJb1uZCVtX1JeDokt9EHgHMMSexe/92lb2vfMrmUHnkw==",
+ HASH_METHOD_SSHA256, SHA256_LENGTH, 8 );
+ }
+
+
+ @Test
+ public void testPasswordSSHA256EncryptedLowercase()
+ {
+ testPassword( "secret", "{ssha256}MVfpHvqPUIXJb1uZCVtX1JeDokt9EHgHMMSexe/92lb2vfMrmUHnkw==",
+ HASH_METHOD_SSHA256, SHA256_LENGTH, 8 );
+ }
+
+
+ @Test
+ public void testPasswordSHA384Encrypted()
+ {
+ testPassword( "secret", "{SHA384}WKd1ukESvjAFrkQHznV9iP2nHUBJe7gCbsrFTU4//HIyzo3jq1rLMK45dg/ufFPt",
+ HASH_METHOD_SHA384, SHA384_LENGTH, 0 );
+ }
+
+
+ @Test
+ public void testPasswordSHA384EncryptedLowercase()
+ {
+ testPassword( "secret", "{sha384}WKd1ukESvjAFrkQHznV9iP2nHUBJe7gCbsrFTU4//HIyzo3jq1rLMK45dg/ufFPt",
+ HASH_METHOD_SHA384, SHA384_LENGTH, 0 );
+ }
+
+
+ @Test
+ public void testPasswordSSHA384Encrypted()
+ {
+ testPassword( "secret", "{SSHA384}Ryj+LRp+FKIt0X6PhsqT4kK/76hO6bNeQWha0sMflaY2x2L+nSv/Z7oVMQFTde8Vttn+RFJFIL0=",
+ HASH_METHOD_SSHA384, SHA384_LENGTH, 8 );
+ }
+
+
+ @Test
+ public void testPasswordSSHA384EncryptedLowercase()
+ {
+ testPassword( "secret", "{ssha384}Ryj+LRp+FKIt0X6PhsqT4kK/76hO6bNeQWha0sMflaY2x2L+nSv/Z7oVMQFTde8Vttn+RFJFIL0=",
+ HASH_METHOD_SSHA384, SHA384_LENGTH, 8 );
+ }
+
+
+ @Test
+ public void testPasswordSHA512Encrypted()
+ {
+ testPassword( "secret",
+ "{SHA512}vSsar3708Jvp9Szi2NWZZ02Bqp1qRCFpbcTZPdBhnWgs5WtNZKnvCXdhztmeD2cmW192CF5bDufKRpayrW/isg==",
+ HASH_METHOD_SHA512, SHA512_LENGTH, 0 );
+ }
+
+
+ @Test
+ public void testPasswordSHA512EncryptedLowercase()
+ {
+ testPassword( "secret",
+ "{sha512}vSsar3708Jvp9Szi2NWZZ02Bqp1qRCFpbcTZPdBhnWgs5WtNZKnvCXdhztmeD2cmW192CF5bDufKRpayrW/isg==",
+ HASH_METHOD_SHA512, SHA512_LENGTH, 0 );
+ }
+
+
+ @Test
+ public void testPasswordSSHA512Encrypted()
+ {
+ testPassword( "secret",
+ "{SSHA512}ZXa+mKUUX657jXwVF4t6djmniDAZG2O2Xk8YTbmau5qWjpZ6FGH0Nql0uR18+sUxATjJbF6YHZr6GjRxVDLgknh9nUZmK26+",
+ HASH_METHOD_SSHA512, SHA512_LENGTH, 8 );
+ }
+
+
+ @Test
+ public void testPasswordSSHA512EncryptedLowercase()
+ {
+ testPassword( "secret",
+ "{ssha512}ZXa+mKUUX657jXwVF4t6djmniDAZG2O2Xk8YTbmau5qWjpZ6FGH0Nql0uR18+sUxATjJbF6YHZr6GjRxVDLgknh9nUZmK26+",
+ HASH_METHOD_SSHA512, SHA512_LENGTH, 8 );
+ }
+
+
+ @Test
+ public void testPasswordPKCS5S2Encrypted()
+ {
+ testPassword( "secret", "{PKCS5S2}3L9Bz29r+5fGHlItzYcMlWeJHl7xWYTlaeEOzzx5aHntdP4DyK4hKQCidxcHMwz8",
+ HASH_METHOD_PKCS5S2, PKCS5S2_LENGTH, 16 );
+ }
+
+
+ @Test
+ public void testPasswordPKCS5S2EncryptedLowercase()
+ {
+ testPassword( "secret", "{pkcs5s2}3L9Bz29r+5fGHlItzYcMlWeJHl7xWYTlaeEOzzx5aHntdP4DyK4hKQCidxcHMwz8",
+ HASH_METHOD_PKCS5S2, PKCS5S2_LENGTH, 16 );
+ }
+
+
+ @Test
+ public void testPasswordCRYPTEncrypted()
+ {
+ testPassword( "secret", "{CRYPT}qFkH8Z1woBlXw", HASH_METHOD_CRYPT, 11, 2 );
+ }
+
+
+ @Test
+ public void testPasswordCRYPTEncryptedLowercase()
+ {
+ testPassword( "secret", "{crypt}qFkH8Z1woBlXw", HASH_METHOD_CRYPT, 11, 2 );
+ }
+
+
+ private void testPassword( String plainText, String encrypted, LdapSecurityConstants algorithm, int passwordLength,
+ int saltLength )
+ {
+ // assert findAlgorithm
+ assertEquals( algorithm, PasswordUtil.findAlgorithm( Strings.getBytesUtf8( encrypted ) ) );
+
+ // assert compareCredentials
+ assertTrue(
+ PasswordUtil.compareCredentials( Strings.getBytesUtf8( plainText ), Strings.getBytesUtf8( encrypted ) ) );
+
+ // assert splitCredentials
+ PasswordDetails passwordDetails = PasswordUtil.splitCredentials( Strings.getBytesUtf8( encrypted ) );
+ assertEquals( algorithm, passwordDetails.getAlgorithm() );
+ if ( saltLength == 0 )
+ {
+ assertNull( passwordDetails.getSalt() );
+ }
+ else
+ {
+ assertNotNull( passwordDetails.getSalt() );
+ assertEquals( saltLength, passwordDetails.getSalt().length );
+ }
+ assertNotNull( passwordDetails.getPassword() );
+ assertEquals( passwordLength, passwordDetails.getPassword().length );
+
+ // assert createStoragePassword / compareCredentials roundtrip
+ byte[] generated = PasswordUtil.createStoragePassword( plainText, algorithm );
+ assertTrue(
+ PasswordUtil.compareCredentials( Strings.getBytesUtf8( plainText ), generated ) );
+ }
+
}