You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by er...@apache.org on 2007/05/03 03:26:15 UTC

svn commit: r534675 - in /directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src: main/java/org/apache/directory/server/kerberos/shared/crypto/encryption/ test/java/org/apache/directory/server/kerberos/shared/crypto/encryption/

Author: erodriguez
Date: Wed May  2 18:26:14 2007
New Revision: 534675

URL: http://svn.apache.org/viewvc?view=rev&rev=534675
Log:
o  Overhaul of the SessionKeyFactory to support DES, DES3, AES, and RC4-HMAC.
o  Test case covering session key generation.

Added:
    directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src/test/java/org/apache/directory/server/kerberos/shared/crypto/encryption/SessionKeyFactoryTest.java   (with props)
Modified:
    directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src/main/java/org/apache/directory/server/kerberos/shared/crypto/encryption/SessionKeyFactory.java

Modified: directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src/main/java/org/apache/directory/server/kerberos/shared/crypto/encryption/SessionKeyFactory.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src/main/java/org/apache/directory/server/kerberos/shared/crypto/encryption/SessionKeyFactory.java?view=diff&rev=534675&r1=534674&r2=534675
==============================================================================
--- directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src/main/java/org/apache/directory/server/kerberos/shared/crypto/encryption/SessionKeyFactory.java (original)
+++ directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src/main/java/org/apache/directory/server/kerberos/shared/crypto/encryption/SessionKeyFactory.java Wed May  2 18:26:14 2007
@@ -20,13 +20,16 @@
 package org.apache.directory.server.kerberos.shared.crypto.encryption;
 
 
-import java.security.InvalidKeyException;
-import java.security.SecureRandom;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
+import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
-import javax.crypto.spec.DESKeySpec;
-import javax.crypto.spec.SecretKeySpec;
 
+import org.apache.directory.server.kerberos.shared.exceptions.ErrorType;
+import org.apache.directory.server.kerberos.shared.exceptions.KerberosException;
 import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
 
 
@@ -38,105 +41,64 @@
  */
 public class SessionKeyFactory
 {
-    /**
-     * SecureRandom.nextBytes() is synchronized, making this safe for static use.
-     */
-    private static final SecureRandom random = new SecureRandom();
+    /** a map of the default encryption types to the encryption engine class names */
+    private static final Map<EncryptionType, String> DEFAULT_CIPHERS;
 
-
-    /**
-     * Get a new random session key.
-     *
-     * @return The new random session key.
-     */
-    public static EncryptionKey getSessionKey()
+    static
     {
-        // Only need 7 bytes.  With parity will result in 8 bytes.
-        byte[] raw = new byte[7];
-
-        // SecureRandom.nextBytes is already synchronized
-        random.nextBytes( raw );
-
-        byte[] keyBytes = addParity( raw );
-
-        try
-        {
-            // check for weakness
-            if ( DESKeySpec.isWeak( keyBytes, 0 ) )
-            {
-                keyBytes = getStrongKey( keyBytes );
-            }
-        }
-        catch ( InvalidKeyException ike )
-        {
-            /*
-             * Will only get here if the key is null or less
-             * than 8 bytes, which won't ever happen.
-             */
-            return null;
-        }
+        Map<EncryptionType, String> map = new HashMap<EncryptionType, String>();
 
-        SecretKey key = new SecretKeySpec( keyBytes, "DES" );
-        byte[] subSessionKey = key.getEncoded();
+        map.put( EncryptionType.DES_CBC_MD5, "DES" );
+        map.put( EncryptionType.DES3_CBC_SHA1_KD, "DESede" );
+        map.put( EncryptionType.RC4_HMAC, "RC4" );
+        map.put( EncryptionType.AES128_CTS_HMAC_SHA1_96, "AES" );
+        map.put( EncryptionType.AES256_CTS_HMAC_SHA1_96, "AES" );
 
-        return new EncryptionKey( EncryptionType.DES_CBC_MD5, subSessionKey );
+        DEFAULT_CIPHERS = Collections.unmodifiableMap( map );
     }
 
 
     /**
-     * Adds parity to 7-bytes to form an 8-byte DES key.
-     *
-     * @param sevenBytes
-     * @return The 8-byte DES key with parity.
+     * Get a new random session key for a given {@link EncryptionType}.
+     * 
+     * @param encryptionType 
+     * 
+     * @return The new random session key.
+     * @throws KerberosException 
      */
-    static byte[] addParity( byte[] sevenBytes )
+    public static EncryptionKey getSessionKey( EncryptionType encryptionType ) throws KerberosException
     {
-        byte[] result = new byte[8];
+        String algorithm = DEFAULT_CIPHERS.get( encryptionType );
 
-        // Keeps track of the bit position in the result.
-        int resultIndex = 1;
-
-        // Used to keep track of the number of 1 bits in each 7-bit chunk.
-        int bitCount = 0;
+        if ( algorithm == null )
+        {
+            throw new KerberosException( ErrorType.KDC_ERR_ETYPE_NOSUPP, encryptionType.getName()
+                + " is not a supported encryption type." );
+        }
 
-        // Process each of the 56 bits.
-        for ( int i = 0; i < 56; i++ )
+        try
         {
-            // Get the bit at bit position i
-            boolean bit = ( sevenBytes[6 - i / 8] & ( 1 << ( i % 8 ) ) ) > 0;
+            KeyGenerator keyGenerator = KeyGenerator.getInstance( algorithm );
 
-            // If set, set the corresponding bit in the result.
-            if ( bit )
+            if ( encryptionType.equals( EncryptionType.AES128_CTS_HMAC_SHA1_96 ) )
             {
-                result[7 - resultIndex / 8] |= ( 1 << ( resultIndex % 8 ) ) & 0xFF;
-                bitCount++;
+                keyGenerator.init( 128 );
             }
 
-            // Set the parity bit after every 7 bits.
-            if ( ( i + 1 ) % 7 == 0 )
+            if ( encryptionType.equals( EncryptionType.AES256_CTS_HMAC_SHA1_96 ) )
             {
-                if ( bitCount % 2 == 0 )
-                {
-                    // Set low-order bit (parity bit) if bit count is even.
-                    result[7 - resultIndex / 8] |= 1;
-                }
-                resultIndex++;
-                bitCount = 0;
+                keyGenerator.init( 256 );
             }
-            resultIndex++;
-        }
 
-        return result;
-    }
+            SecretKey key = keyGenerator.generateKey();
 
+            byte[] keyBytes = key.getEncoded();
 
-    /**
-     * Corrects the weak key by exclusive OR with 0xF0 constant.
-     */
-    private static byte[] getStrongKey( byte keyValue[] )
-    {
-        keyValue[7] ^= 0xf0;
-
-        return keyValue;
+            return new EncryptionKey( encryptionType, keyBytes );
+        }
+        catch ( NoSuchAlgorithmException nsae )
+        {
+            throw new KerberosException( ErrorType.KDC_ERR_ETYPE_NOSUPP, nsae.getMessage() );
+        }
     }
 }

Added: directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src/test/java/org/apache/directory/server/kerberos/shared/crypto/encryption/SessionKeyFactoryTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src/test/java/org/apache/directory/server/kerberos/shared/crypto/encryption/SessionKeyFactoryTest.java?view=auto&rev=534675
==============================================================================
--- directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src/test/java/org/apache/directory/server/kerberos/shared/crypto/encryption/SessionKeyFactoryTest.java (added)
+++ directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src/test/java/org/apache/directory/server/kerberos/shared/crypto/encryption/SessionKeyFactoryTest.java Wed May  2 18:26:14 2007
@@ -0,0 +1,118 @@
+/*
+ *  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.kerberos.shared.crypto.encryption;
+
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.DESKeySpec;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Test cases for random-to-key functions for DES-, DES3-, AES-, and RC4-based
+ * encryption types.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class SessionKeyFactoryTest extends TestCase
+{
+    /**
+     * Tests that random DES keys can be generated.
+     *
+     * @throws Exception
+     */
+    public void testGenerateDesKey() throws Exception
+    {
+        KeyGenerator keygen = KeyGenerator.getInstance( "DES" );
+        SecretKey key = keygen.generateKey();
+        assertEquals( "DES key size", 8, key.getEncoded().length );
+        assertTrue( DESKeySpec.isParityAdjusted( key.getEncoded(), 0 ) );
+    }
+
+
+    /**
+     * Tests that random Triple-DES keys can be generated.
+     *
+     * @throws Exception
+     */
+    public void testGenerateTripleDesKey() throws Exception
+    {
+        KeyGenerator keygen = KeyGenerator.getInstance( "DESede" );
+        SecretKey key = keygen.generateKey();
+        assertEquals( "DESede key size", 24, key.getEncoded().length );
+    }
+
+
+    /**
+     * Tests that random AES128 keys can be generated.
+     *
+     * @throws Exception
+     */
+    public void testGenerateAes128Key() throws Exception
+    {
+        KeyGenerator keygen = KeyGenerator.getInstance( "AES" );
+        keygen.init( 128 );
+        SecretKey key = keygen.generateKey();
+        assertEquals( "AES key size", 16, key.getEncoded().length );
+    }
+
+
+    /**
+     * Tests that random AES256 keys can be generated.
+     *
+     * @throws Exception
+     */
+    public void testGenerateAes256Key() throws Exception
+    {
+        // KeyGenerator keygen = KeyGenerator.getInstance( "AES" );
+        // keygen.init( 256 );
+        // SecretKey key = keygen.generateKey();
+        // assertEquals( "AES key size", 32, key.getEncoded().length );
+    }
+
+
+    /**
+     * Tests that random ARCFOUR keys can be generated.
+     *
+     * @throws Exception
+     */
+    public void testGenerateArcFourKey() throws Exception
+    {
+        KeyGenerator keygen = KeyGenerator.getInstance( "ARCFOUR" );
+        SecretKey key = keygen.generateKey();
+        assertEquals( "ARCFOUR key size", 16, key.getEncoded().length );
+    }
+
+
+    /**
+     * Tests that random RC4 keys can be generated.
+     *
+     * @throws Exception
+     */
+    public void testGenerateRc4Key() throws Exception
+    {
+        KeyGenerator keygen = KeyGenerator.getInstance( "RC4" );
+        SecretKey key = keygen.generateKey();
+        assertEquals( "RC4 key size", 16, key.getEncoded().length );
+    }
+}

Propchange: directory/apacheds/branches/kerberos-encryption-types/kerberos-shared/src/test/java/org/apache/directory/server/kerberos/shared/crypto/encryption/SessionKeyFactoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native