You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ka...@apache.org on 2013/09/17 08:15:43 UTC

svn commit: r1523919 - in /directory: apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/ shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/ shared/trunk/ldap/model/src/main/java/org/a...

Author: kayyagari
Date: Tue Sep 17 06:15:42 2013
New Revision: 1523919

URL: http://svn.apache.org/r1523919
Log:
support for PKCS5S2 hashing mechanism (DIRSERVER-1898)

Added:
    directory/apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/Pkcs5s2PasswordHashingInterceptor.java
Modified:
    directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapSecurityConstants.java
    directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/EncryptionMethod.java
    directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java

Added: directory/apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/Pkcs5s2PasswordHashingInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/Pkcs5s2PasswordHashingInterceptor.java?rev=1523919&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/Pkcs5s2PasswordHashingInterceptor.java (added)
+++ directory/apacheds/trunk/interceptors/hash/src/main/java/org/apache/directory/server/core/hash/Pkcs5s2PasswordHashingInterceptor.java Tue Sep 17 06:15:42 2013
@@ -0,0 +1,47 @@
+/*
+ *   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.server.core.hash;
+
+
+import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
+
+
+/**
+ * PasswordHashingInterceptor using PBKDF2WithHmacSHA1 encryption algorithm
+ * to generate a secret key and use its encoded value as the password hash
+ * with {PKCS5S2} prefix.
+ * 
+ * See <a href="http://en.wikipedia.org/wiki/PBKDF2">PBKDF2 spec</a> for more
+ * details.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class Pkcs5s2PasswordHashingInterceptor extends PasswordHashingInterceptor
+{
+    /**
+     * Creates an instance of a Pkcs5s2PasswordHashingInterceptor
+     */
+    public Pkcs5s2PasswordHashingInterceptor()
+    {
+        super( "Pkcs5s2PasswordHashingInterceptor", LdapSecurityConstants.HASH_METHOD_PKCS5S2 );
+    }
+
+}

Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapSecurityConstants.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapSecurityConstants.java?rev=1523919&r1=1523918&r2=1523919&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapSecurityConstants.java (original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/constants/LdapSecurityConstants.java Tue Sep 17 06:15:42 2013
@@ -61,7 +61,10 @@ public enum LdapSecurityConstants
     HASH_METHOD_SMD5("SMD5", "MD5", "smd5"),
 
     /** The crypt encryption method */
-    HASH_METHOD_CRYPT("CRYPT", "CRYPT", "crypt");
+    HASH_METHOD_CRYPT("CRYPT", "CRYPT", "crypt"),
+
+    /** The PBKDF2-based encryption method */
+    HASH_METHOD_PKCS5S2("PKCS5S2", "PBKDF2WithHmacSHA1", "PKCS5S2");
 
     /* These encryption types are not yet supported 
     ** The AES encryption method *
@@ -216,6 +219,12 @@ public enum LdapSecurityConstants
             return HASH_METHOD_SSHA512;
         }
 
+        if ( HASH_METHOD_PKCS5S2.getName().equalsIgnoreCase( algorithm )
+            || HASH_METHOD_PKCS5S2.getPrefix().equalsIgnoreCase( algorithm ) )
+        {
+            return HASH_METHOD_PKCS5S2;
+        }
+
         /*
         if ( ENC_METHOD_AES.getName().equalsIgnoreCase( algorithm ) )
         {

Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/EncryptionMethod.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/EncryptionMethod.java?rev=1523919&r1=1523918&r2=1523919&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/EncryptionMethod.java (original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/EncryptionMethod.java Tue Sep 17 06:15:42 2013
@@ -39,10 +39,10 @@ import org.apache.directory.api.util.Str
  * {<algorithm>}<encrypted password>
  * where the encrypted password format can be :
  * - MD5/SHA : base64(<password>)
- * - SMD5/SSH : base64(<salted-password-digest><salt (4 or 8 bytes)>)
+ * - SMD5/SSH/PKCS5S2 : base64(<salted-password-digest><salt (4 or 8 bytes)>)
  * - crypt : <salt (2 btytes)><password>
  *
- * Algorithm are currently MD5, SMD5, SHA, SSHA, SHA2, SSHA-2 (except SHA-224), CRYPT and empty
+ * Algorithm are currently MD5, SMD5, SHA, SSHA, SHA2, SSHA-2 (except SHA-224), PKCS5S2, CRYPT and empty
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 public class EncryptionMethod

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=1523919&r1=1523918&r2=1523919&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 Tue Sep 17 06:15:42 2013
@@ -1,6 +1,6 @@
 /*
- *   Licensed to the Apache Software Foundation (ASF) under one
  *   or more contributor license agreements.  See the NOTICE file
+ *   Licensed to the Apache Software Foundation (ASF) under one
  *   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
@@ -22,12 +22,17 @@ package org.apache.directory.api.ldap.mo
 
 
 import java.io.UnsupportedEncodingException;
+import java.security.Key;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.security.spec.KeySpec;
 import java.util.Arrays;
 import java.util.Date;
 
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
 import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
 import org.apache.directory.api.util.Base64;
 import org.apache.directory.api.util.DateUtils;
@@ -58,6 +63,8 @@ public class PasswordUtil
     /** The MD5 hash length */
     public static final int MD5_LENGTH = 16;
 
+    /** The PKCS5S2 hash length */
+    public static final int PKCS5S2_LENGTH = 20;
 
     /**
      * Get the algorithm from the stored password. 
@@ -142,6 +149,7 @@ public class PasswordUtil
             case HASH_METHOD_SSHA384:
             case HASH_METHOD_SSHA512:
             case HASH_METHOD_SMD5:
+            case HASH_METHOD_PKCS5S2:
                 salt = new byte[8]; // we use 8 byte salt always except for "crypt" which needs 2 byte salt
                 new SecureRandom().nextBytes( salt );
                 break;
@@ -202,6 +210,7 @@ public class PasswordUtil
      * <li>- SHA-2(256, 384 and 512 and their salted versions)</li>
      * <li>- MD5</li>
      * <li>- SMD5 (slated MD5)</li>
+     * <li>- PKCS5S2 (PBKDF2)</li>
      * <li>- crypt (unix crypt)</li>
      * <li>- plain text, ie no encryption.</li>
      * </ul>
@@ -211,8 +220,9 @@ public class PasswordUtil
      *  </p>
      *  If the password is using SSHA, SMD5 or crypt, some 'salt' is added to the password :
      *  <ul>
-     *  <li>- length(password) - 20, starting at 21th position for SSHA</li>
+     *  <li>- length(password) - 20, starting at 21st position for SSHA</li>
      *  <li>- length(password) - 16, starting at 16th position for SMD5</li>
+     *  <li>- length(password) - 20, starting at 21st position for PKCS5S2</li>
      *  <li>- length(password) - 2, starting at 3rd position for crypt</li>
      *  </ul>
      *  <p>
@@ -303,6 +313,9 @@ public class PasswordUtil
 
                 return Strings.getBytesUtf8( crypted );
 
+            case HASH_METHOD_PKCS5S2:
+                return generatePbkdf2Hash( credentials, algorithm, salt );
+                
             default:
                 return credentials;
         }
@@ -415,6 +428,9 @@ public class PasswordUtil
             case HASH_METHOD_SSHA512:
                 return getCredentials( credentials, algoLength, SHA512_LENGTH, encryptionMethod );
 
+            case HASH_METHOD_PKCS5S2:
+                return getCredentials( credentials, algoLength, PKCS5S2_LENGTH, encryptionMethod );
+                
             case HASH_METHOD_CRYPT:
                 // The password is associated with a salt. Decompose it
                 // in two parts, storing the salt into the EncryptionMethod structure.
@@ -503,4 +519,30 @@ public class PasswordUtil
 
         return expired;
     }
+    
+    
+    /**
+     * 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 );
+        }
+    }
+    
 }