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/22 17:24:57 UTC
svn commit: r1731680 - in
/directory/studio/trunk/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core:
model/Password.java utils/UnixCrypt.java
Author: seelmann
Date: Mon Feb 22 16:24:57 2016
New Revision: 1731680
URL: http://svn.apache.org/viewvc?rev=1731680&view=rev
Log:
DIRSTUDIO-738: Add support for modular crypt format password
* Remove duplicate code, use PasswordUtil from API instead
Removed:
directory/studio/trunk/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/utils/UnixCrypt.java
Modified:
directory/studio/trunk/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/Password.java
Modified: directory/studio/trunk/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/Password.java
URL: http://svn.apache.org/viewvc/directory/studio/trunk/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/Password.java?rev=1731680&r1=1731679&r2=1731680&view=diff
==============================================================================
--- directory/studio/trunk/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/Password.java (original)
+++ directory/studio/trunk/plugins/ldapbrowser.core/src/main/java/org/apache/directory/studio/ldapbrowser/core/model/Password.java Mon Feb 22 16:24:57 2016
@@ -21,19 +21,11 @@
package org.apache.directory.studio.ldapbrowser.core.model;
-import java.security.Key;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.spec.KeySpec;
-
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
-
import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
+import org.apache.directory.api.ldap.model.password.PasswordDetails;
+import org.apache.directory.api.ldap.model.password.PasswordUtil;
import org.apache.directory.api.util.Strings;
import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
-import org.apache.directory.studio.ldapbrowser.core.utils.UnixCrypt;
import org.apache.directory.studio.ldifparser.LdifUtils;
@@ -63,23 +55,11 @@ import org.apache.directory.studio.ldifp
*/
public class Password
{
- /** The hash method */
- private LdapSecurityConstants hashMethod;
-
- /** The hashed password */
- private byte[] hashedPassword;
-
- /** The salt */
- private byte[] salt;
-
- /** The 'unsupported hash' flag */
- private boolean isUnsupportedHashMethod = false;
-
- /** The 'invalid hash' flag */
- private boolean isInvalidHashValue = false;
-
- /** The trash, used for unknown hash methods. */
- private String trash;
+ /** The password, either plain text or in encrypted format */
+ private final byte[] password;
+
+ /** The password details */
+ private final PasswordDetails passwordDetails;
/**
@@ -89,7 +69,15 @@ public class Password
*/
public Password( byte[] password )
{
- this( LdifUtils.utf8decode( password ) );
+ if ( password == null )
+ {
+ throw new IllegalArgumentException( BrowserCoreMessages.model__empty_password );
+ }
+ else
+ {
+ this.password = password;
+ this.passwordDetails = PasswordUtil.splitCredentials( password );
+ }
}
@@ -104,87 +92,10 @@ public class Password
{
throw new IllegalArgumentException( BrowserCoreMessages.model__empty_password );
}
- else if ( ( password.indexOf( '{' ) == 0 ) && ( password.indexOf( '}' ) > 0 ) )
- {
- try
- {
- // Getting the hash method
- String hashMethodString = password.substring( password.indexOf( '{' ) + 1, password.indexOf( '}' ) );
- hashMethod = LdapSecurityConstants.getAlgorithm( hashMethodString );
-
- // Getting the rest of the hashed password
- String rest = password.substring( hashMethodString.length() + 2 );
-
- if ( ( LdapSecurityConstants.HASH_METHOD_SHA == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SHA256 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SHA384 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SHA512 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_MD5 == hashMethod ) )
- {
- hashedPassword = LdifUtils.base64decodeToByteArray( rest );
- salt = null;
- }
- else if ( ( LdapSecurityConstants.HASH_METHOD_SSHA == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA256 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA384 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA512 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SMD5 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_PKCS5S2 == hashMethod ) )
- {
- switch ( hashMethod )
- {
- case HASH_METHOD_SSHA:
- hashedPassword = new byte[20];
- break;
- case HASH_METHOD_SSHA256:
- hashedPassword = new byte[32];
- break;
- case HASH_METHOD_SSHA384:
- hashedPassword = new byte[48];
- break;
- case HASH_METHOD_SSHA512:
- hashedPassword = new byte[64];
- break;
- case HASH_METHOD_SMD5:
- hashedPassword = new byte[16];
- break;
- case HASH_METHOD_PKCS5S2:
- hashedPassword = new byte[20];
- break;
- default:
- break;
- }
-
- byte[] hashedPasswordWithSalt = LdifUtils.base64decodeToByteArray( rest );
- salt = new byte[hashedPasswordWithSalt.length - hashedPassword.length];
- split( hashedPasswordWithSalt, hashedPassword, salt );
- }
- else if ( LdapSecurityConstants.HASH_METHOD_CRYPT == hashMethod )
- {
- byte[] saltWithPassword = LdifUtils.utf8encode( rest );
- salt = new byte[2];
- hashedPassword = new byte[saltWithPassword.length - salt.length];
- split( saltWithPassword, salt, hashedPassword );
- }
- else
- {
- isUnsupportedHashMethod = true;
- trash = password;
- }
- }
- catch ( RuntimeException e )
- {
- // happens if 'rest' is not valid BASE64
- isInvalidHashValue = true;
- trash = password;
- }
- }
else
{
- // plain text
- hashMethod = null;
- hashedPassword = LdifUtils.utf8encode( password );
- salt = null;
+ this.password = Strings.getBytesUtf8( password );
+ this.passwordDetails = PasswordUtil.splitCredentials( this.password );
}
}
@@ -199,65 +110,14 @@ public class Password
*/
public Password( LdapSecurityConstants hashMethod, String passwordAsPlaintext )
{
- // Checking the password as plain text
if ( passwordAsPlaintext == null )
{
throw new IllegalArgumentException( BrowserCoreMessages.model__empty_password );
}
-
- // Setting the hash method
- this.hashMethod = hashMethod;
-
- // Setting the salt
- if ( ( LdapSecurityConstants.HASH_METHOD_SSHA == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA256 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA384 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA512 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SMD5 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_PKCS5S2 == hashMethod ) )
- {
- this.salt = new byte[8];
- new SecureRandom().nextBytes( this.salt );
- }
- else if ( LdapSecurityConstants.HASH_METHOD_CRYPT == hashMethod )
- {
- this.salt = new byte[2];
- SecureRandom sr = new SecureRandom();
- int i1 = sr.nextInt( 64 );
- int i2 = sr.nextInt( 64 );
- this.salt[0] = ( byte ) ( i1 < 12 ? ( i1 + '.' ) : i1 < 38 ? ( i1 + 'A' - 12 ) : ( i1 + 'a' - 38 ) );
- this.salt[1] = ( byte ) ( i2 < 12 ? ( i2 + '.' ) : i2 < 38 ? ( i2 + 'A' - 12 ) : ( i2 + 'a' - 38 ) );
- }
else
{
- this.salt = null;
- }
-
- // Setting the hashed password
- if ( hashMethod == null )
- {
- this.hashedPassword = LdifUtils.utf8encode( passwordAsPlaintext );
- }
- else if ( ( LdapSecurityConstants.HASH_METHOD_SHA == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SHA256 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA256 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SHA384 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA384 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SHA512 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA512 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_MD5 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SMD5 == hashMethod ) )
- {
- this.hashedPassword = digest( hashMethod, passwordAsPlaintext, this.salt );
- }
- else if ( LdapSecurityConstants.HASH_METHOD_CRYPT == hashMethod )
- {
- this.hashedPassword = crypt( passwordAsPlaintext, this.salt );
- }
- else if ( LdapSecurityConstants.HASH_METHOD_PKCS5S2 == hashMethod )
- {
- this.hashedPassword = generatePbkdf2Hash( passwordAsPlaintext.getBytes(), hashMethod, salt );
+ this.password = PasswordUtil.createStoragePassword( passwordAsPlaintext, hashMethod );
+ this.passwordDetails = PasswordUtil.splitCredentials( this.password );
}
}
@@ -276,44 +136,7 @@ public class Password
return false;
}
- boolean verified = false;
-
- if ( isInvalidHashValue || isUnsupportedHashMethod )
- {
- return false;
- }
-
- if ( hashMethod == null )
- {
- verified = testPasswordAsPlaintext.equals( LdifUtils.utf8decode( hashedPassword ) );
- }
- else if ( ( LdapSecurityConstants.HASH_METHOD_SHA == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SHA256 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA256 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SHA384 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA384 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SHA512 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SSHA512 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_MD5 == hashMethod )
- || ( LdapSecurityConstants.HASH_METHOD_SMD5 == hashMethod ) )
- {
- byte[] hash = digest( hashMethod, testPasswordAsPlaintext, salt );
- verified = equals( hash, hashedPassword );
- }
- else if ( LdapSecurityConstants.HASH_METHOD_CRYPT == hashMethod )
- {
- byte[] crypted = crypt( testPasswordAsPlaintext, salt );
- verified = equals( crypted, hashedPassword );
- }
- else if ( LdapSecurityConstants.HASH_METHOD_PKCS5S2 == hashMethod )
- {
- byte[] hash = generatePbkdf2Hash( testPasswordAsPlaintext.getBytes(),
- LdapSecurityConstants.HASH_METHOD_PKCS5S2, salt );
- verified = equals( hash, hashedPassword );
- }
-
- return verified;
+ return PasswordUtil.compareCredentials( Strings.getBytesUtf8( testPasswordAsPlaintext ), this.password );
}
@@ -324,7 +147,7 @@ public class Password
*/
public LdapSecurityConstants getHashMethod()
{
- return hashMethod;
+ return passwordDetails.getAlgorithm();
}
@@ -335,7 +158,7 @@ public class Password
*/
public byte[] getHashedPassword()
{
- return hashedPassword;
+ return passwordDetails.getPassword();
}
@@ -346,7 +169,7 @@ public class Password
*/
public String getHashedPasswordAsHexString()
{
- return LdifUtils.hexEncode( hashedPassword );
+ return LdifUtils.hexEncode( passwordDetails.getPassword() );
}
@@ -357,7 +180,7 @@ public class Password
*/
public byte[] getSalt()
{
- return salt;
+ return passwordDetails.getSalt();
}
@@ -368,7 +191,7 @@ public class Password
*/
public String getSaltAsHexString()
{
- return LdifUtils.hexEncode( salt );
+ return LdifUtils.hexEncode( passwordDetails.getSalt() );
}
@@ -388,164 +211,7 @@ public class Password
*/
public String toString()
{
- StringBuffer sb = new StringBuffer();
-
- if ( isUnsupportedHashMethod || isInvalidHashValue )
- {
- sb.append( trash );
- }
- else if ( LdapSecurityConstants.HASH_METHOD_CRYPT == hashMethod )
- {
- sb.append( '{' ).append( hashMethod.getPrefix() ).append( '}' );
- sb.append( LdifUtils.utf8decode( salt ) );
- sb.append( LdifUtils.utf8decode( hashedPassword ) );
- }
- else if ( hashMethod != null )
- {
- sb.append( '{' ).append( hashMethod.getPrefix() ).append( '}' );
- if ( salt != null )
- {
- byte[] hashedPasswordWithSaltBytes = new byte[hashedPassword.length + salt.length];
- merge( hashedPasswordWithSaltBytes, hashedPassword, salt );
- sb.append( LdifUtils.base64encode( hashedPasswordWithSaltBytes ) );
- }
- else
- {
- sb.append( LdifUtils.base64encode( hashedPassword ) );
- }
- }
- else
- {
- sb.append( LdifUtils.utf8decode( hashedPassword ) );
- }
-
- return sb.toString();
+ return Strings.utf8ToString( password );
}
-
- private static void split( byte[] all, byte[] left, byte[] right )
- {
- System.arraycopy( all, 0, left, 0, left.length );
- System.arraycopy( all, left.length, right, 0, right.length );
- }
-
-
- private static void merge( byte[] all, byte[] left, byte[] right )
- {
- System.arraycopy( left, 0, all, 0, left.length );
- System.arraycopy( right, 0, all, left.length, right.length );
- }
-
-
- /**
- * Checks equality between two byte arrays.
- *
- * @param data1 the first byte array
- * @param data2 the first byte array
- * @return <code>true</code> if the two byte arrays are equal
- */
- private static boolean equals( byte[] data1, byte[] data2 )
- {
- if ( data1 == data2 )
- {
- return true;
- }
-
- if ( data1 == null || data2 == null )
- {
- return false;
- }
-
- if ( data1.length != data2.length )
- {
- return false;
- }
-
- for ( int i = 0; i < data1.length; i++ )
- {
- if ( data1[i] != data2[i] )
- {
- return false;
- }
- }
-
- return true;
- }
-
-
- /**
- * Computes the hashed value of a password with the given hash method and optional salt.
- *
- * @param hashMethod the hash method
- * @param password the password
- * @param salt the optional salt (can be <code>null</code>)
- * @return the hashed value of the password
- */
- private static byte[] digest( LdapSecurityConstants hashMethod, String password, byte[] salt )
- {
- // Converting password to byte array
- byte[] passwordBytes = LdifUtils.utf8encode( password );
-
- // Getting the message digest associated with the hash method
- try
- {
- MessageDigest digest = MessageDigest.getInstance( hashMethod.getAlgorithm() );
-
- // Computing the hashed password (salted or not)
- if ( salt != null )
- {
- digest.update( passwordBytes );
- digest.update( salt );
- return digest.digest();
- }
- else
- {
- return digest.digest( passwordBytes );
- }
- }
- catch ( NoSuchAlgorithmException e1 )
- {
- return null;
- }
- }
-
-
- /**
- * Computes the crypt value of a password (with salt).
- *
- * @param password the password
- * @param salt the salt
- * @return the crypt value of the password
- */
- private static byte[] crypt( String password, byte[] salt )
- {
- String saltWithCrypted = UnixCrypt.crypt( password, LdifUtils.utf8decode( salt ) );
- String crypted = saltWithCrypted.substring( 2 );
- return LdifUtils.utf8encode( crypted );
- }
-
-
- /**
- * generates a hash based on the <a href="http://en.wikipedia.org/wiki/PBKDF2">PKCS5S2 spec</a>
- *
- * @param algorithm the algorithm to use
- * @param password the credentials
- * @param salt the optional salt
- * @return the digested credentials
- */
- private static byte[] generatePbkdf2Hash( byte[] credentials, LdapSecurityConstants algorithm, byte[] salt )
- {
- try
- {
- SecretKeyFactory sk = SecretKeyFactory.getInstance( algorithm.getAlgorithm() );
- char[] password = Strings.utf8ToString( credentials ).toCharArray();
- KeySpec keySpec = new PBEKeySpec( password, salt, 1000, 160 );
- Key key = sk.generateSecret( keySpec );
- return key.getEncoded();
- }
- catch ( Exception e )
- {
- throw new RuntimeException( e );
- }
- }
}