harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From smish...@apache.org
Subject svn commit: r400245 - in /incubator/harmony/enhanced/classlib/trunk/modules/auth/src: main/java/common/javax/security/auth/kerberos/KerberosKey.java test/java/common/javax/security/auth/kerberos/KerberosKeyTest.java
Date Sat, 06 May 2006 06:18:00 GMT
Author: smishura
Date: Fri May  5 23:17:57 2006
New Revision: 400245

URL: http://svn.apache.org/viewcvs?rev=400245&view=rev
Log:
First draft for generating DES key from password - needs further improvement

Modified:
    incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/javax/security/auth/kerberos/KerberosKey.java
    incubator/harmony/enhanced/classlib/trunk/modules/auth/src/test/java/common/javax/security/auth/kerberos/KerberosKeyTest.java

Modified: incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/javax/security/auth/kerberos/KerberosKey.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/javax/security/auth/kerberos/KerberosKey.java?rev=400245&r1=400244&r2=400245&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/javax/security/auth/kerberos/KerberosKey.java
(original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/javax/security/auth/kerberos/KerberosKey.java
Fri May  5 23:17:57 2006
@@ -27,7 +27,10 @@
 import java.io.Serializable;
 import java.util.Arrays;
 
+import javax.crypto.Cipher;
 import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
 import javax.security.auth.DestroyFailedException;
 import javax.security.auth.Destroyable;
 
@@ -36,6 +39,7 @@
 /**
  * @com.intel.drl.spec_ref
  * 
+ * @see http://www.ietf.org/rfc/rfc3961.txt
  */
 public class KerberosKey implements SecretKey, Destroyable {
 
@@ -178,7 +182,49 @@
     
     //  indicates the ticket state
     private transient boolean destroyed;
-    
+
+    // Pre-calculated parity values 
+    // TODO the alternative for boolean table - any acceptable algorithm?
+    private final static boolean[] PARITY = new boolean[] { false, true, true,
+            false, true, false, false, true, true, false, false, true, false,
+            true, true, false, true, false, false, true, false, true, true,
+            false, false, true, true, false, true, false, false, true, true,
+            false, false, true, false, true, true, false, false, true, true,
+            false, true, false, false, true, false, true, true, false, true,
+            false, false, true, true, false, false, true, false, true, true,
+            false, true, false, false, true, false, true, true, false, false,
+            true, true, false, true, false, false, true, false, true, true,
+            false, true, false, false, true, true, false, false, true, false,
+            true, true, false, false, true, true, false, true, false, false,
+            true, true, false, false, true, false, true, true, false, true,
+            false, false, true, false, true, true, false, false, true, true,
+            false, true, false, false, true, true, false, false, true, false,
+            true, true, false, false, true, true, false, true, false, false,
+            true, false, true, true, false, true, false, false, true, true,
+            false, false, true, false, true, true, false, false, true, true,
+            false, true, false, false, true, true, false, false, true, false,
+            true, true, false, true, false, false, true, false, true, true,
+            false, false, true, true, false, true, false, false, true, false,
+            true, true, false, true, false, false, true, true, false, false,
+            true, false, true, true, false, true, false, false, true, false,
+            true, true, false, false, true, true, false, true, false, false,
+            true, true, false, false, true, false, true, true, false, false,
+            true, true, false, true, false, false, true, false, true, true,
+            false, true, false, false, true, true, false, false, true, false,
+            true, true, false };
+
+    // Pre-calculated reversed values 
+    // TODO any acceptable alternative algorithm instead of table?
+    private static final byte[] REVERSE = new byte[] { 0, 64, 32, 96, 16, 80,
+            48, 112, 8, 72, 40, 104, 24, 88, 56, 120, 4, 68, 36, 100, 20, 84,
+            52, 116, 12, 76, 44, 108, 28, 92, 60, 124, 2, 66, 34, 98, 18, 82,
+            50, 114, 10, 74, 42, 106, 26, 90, 58, 122, 6, 70, 38, 102, 22, 86,
+            54, 118, 14, 78, 46, 110, 30, 94, 62, 126, 1, 65, 33, 97, 17, 81,
+            49, 113, 9, 73, 41, 105, 25, 89, 57, 121, 5, 69, 37, 101, 21, 85,
+            53, 117, 13, 77, 45, 109, 29, 93, 61, 125, 3, 67, 35, 99, 19, 83,
+            51, 115, 11, 75, 43, 107, 27, 91, 59, 123, 7, 71, 39, 103, 23, 87,
+            55, 119, 15, 79, 47, 111, 31, 95, 63, 127 };
+
     /**
      * creates a secret key from a given raw bytes
      * 
@@ -199,6 +245,10 @@
      */
     public KeyImpl(KerberosPrincipal principal, char[] password, String algorithm) {
 
+        //
+        // See http://www.ietf.org/rfc/rfc3961.txt for algorithm description
+        //
+        
         if (principal == null || password == null) {
             throw new NullPointerException();
         }
@@ -210,9 +260,89 @@
         keyType = 3; // DES algorithm
         keyBytes = new byte[8];
         
-        //FIXME: implement key generation from password 
+        String realm = principal.getRealm();
+        String pname = principal.getName();
+
+        StringBuffer buf = new StringBuffer();
+        buf.append(password);
+        buf.append(realm);
+        buf.append(pname.substring(0, pname.length() - realm.length() - 1));
+
+        byte[] tmp = buf.toString().getBytes();
+
+        // pad with 0x00 to 8 byte boundary
+        byte[] raw = new byte[tmp.length
+                + ((tmp.length % 8) == 0 ? 0 : (8 - tmp.length % 8))];
+        System.arraycopy(tmp, 0, raw, 0, tmp.length);
+
+        long k1, k2 = 0;
+        boolean isOdd = false;
+        // for each 8-byte block in raw byte array
+        for (int i = 0; i < raw.length; i = i + 8, isOdd = !isOdd) {
+
+            k1 = 0;
+            if (isOdd) {
+                //reverse
+                for (int j = 7; j > -1; j--) {
+                    k1 = (k1 << 7) + REVERSE[raw[i + j] & 0x7F];
+                }
+            } else {
+                for (int j = 0; j < 8; j++) {
+                    k1 = (k1 << 7) + (raw[i + j] & 0x7F);
+                }
+            }
+            k2 = k2 ^ k1;
+        }
+        
+        // 56-bit long to byte array (8 bytes)
+        for (int i = 7; i > -1; i--) {
+            keyBytes[i] = (byte) k2;
+            keyBytes[i] = (byte) (keyBytes[i] << 1);
+            k2 = k2 >> 7;
+        }
+        keyCorrection(keyBytes);
+
+        // calculate DES-CBC check sum
+        try {
+            Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
+
+            // use tmp key as IV
+            IvParameterSpec IV = new IvParameterSpec(keyBytes);
+
+            // do DES encryption 
+            SecretKey secretKey = new SecretKeySpec(keyBytes, "DES");
+            cipher.init(Cipher.ENCRYPT_MODE, secretKey, IV);
+            byte[] enc = cipher.doFinal(raw);
+
+            // final last block is check sum
+            System.arraycopy(enc, enc.length - 8, keyBytes, 0, 8);
+            
+            keyCorrection(keyBytes);
+
+        } catch (Exception e) {
+            throw new RuntimeException(
+                    "Failed to generate DES key from password.", e);
+        }
     }
-    
+
+    private void keyCorrection(byte[] key) {
+        
+        // fix parity
+        for (int i = 0; i < 8; i++) {
+            if (!PARITY[key[i] & 0xFF]) {
+                if ((key[i] & 0x01) == 0) {
+                    key[i]++;
+                } else {
+                    key[i]--;
+                }
+            }
+        }
+        
+        // TODO if is week do XOR
+        //if(DESKeySpec.isWeak(keyBytes,0)){
+        //}
+    }
+
     /**
      * Method is described in 
      * <code>getAlgorithm</code> in interface <code>Key</code>

Modified: incubator/harmony/enhanced/classlib/trunk/modules/auth/src/test/java/common/javax/security/auth/kerberos/KerberosKeyTest.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/auth/src/test/java/common/javax/security/auth/kerberos/KerberosKeyTest.java?rev=400245&r1=400244&r2=400245&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/auth/src/test/java/common/javax/security/auth/kerberos/KerberosKeyTest.java
(original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/auth/src/test/java/common/javax/security/auth/kerberos/KerberosKeyTest.java
Fri May  5 23:17:57 2006
@@ -25,6 +25,8 @@
 
 /**
  * Tests KerberosKey class implementation.
+ * 
+ * @see http://www.ietf.org/rfc/rfc3961.txt
  */
 public class KerberosKeyTest extends TestCase {
 
@@ -115,10 +117,41 @@
 
         byte[] keyBytes1 = key.getEncoded();
         assertTrue("encoded", Arrays.equals(keyBytes, keyBytes1));
-        
+
         // bytes are copied each time we invoke the method
         assertNotSame("keyBytes immutability 1 ", keyBytes, keyBytes1);
         assertNotSame("keyBytes immutability 2 ", keyBytes1, key.getEncoded());
+
+        // Test generation of DES key from password
+        // test data from RFC 3961 (http://www.ietf.org/rfc/rfc3961.txt)
+        // see A.2 test vectors
+        // test data format: principal/password/DES key
+        Object[][] testcases = {
+                {
+                        "raeburn@ATHENA.MIT.EDU",
+                        "password",
+                        new byte[] { (byte) 0xcb, (byte) 0xc2, (byte) 0x2f,
+                                (byte) 0xae, (byte) 0x23, (byte) 0x52,
+                                (byte) 0x98, (byte) 0xe3 } },
+                {
+                        "danny@WHITEHOUSE.GOV",
+                        "potatoe",
+                        new byte[] { (byte) 0xdf, (byte) 0x3d, (byte) 0x32,
+                                (byte) 0xa7, (byte) 0x4f, (byte) 0xd9,
+                                (byte) 0x2a, (byte) 0x01 } },
+        // TODO add "pianist@EXAMPLE.COM" and "Juri ... @ATHENA.MIT.EDU"
+        };
+
+        for (int i = 0; i < testcases.length; i++) {
+            KerberosPrincipal kp = new KerberosPrincipal(
+                    (String) testcases[i][0], 1);
+
+            key = new KerberosKey(kp, ((String) testcases[i][1]).toCharArray(),
+                    "DES");
+
+            assertTrue("Testcase: " + (String) testcases[i][0], Arrays.equals(
+                    (byte[]) testcases[i][2], key.getEncoded()));
+        }
     }
 
     /**
@@ -129,7 +162,7 @@
         KerberosKey key = new KerberosKey(principal, new char[10], "DES");
 
         assertFalse("not destroyed", key.isDestroyed());
-        
+
         key.destroy();
         assertTrue("destroyed", key.isDestroyed());
 



Mime
View raw message