You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by pl...@apache.org on 2015/11/24 08:48:51 UTC

[1/2] directory-kerby git commit: Add some implemention of pkinit anonymous.

Repository: directory-kerby
Updated Branches:
  refs/heads/pkinit-support f6d5088bc -> 146967182


http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/base/NameType.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/base/NameType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/base/NameType.java
index 9672883..1120665 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/base/NameType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/base/NameType.java
@@ -27,7 +27,8 @@ public enum NameType implements KrbEnum {
     NT_SRV_INST(2),
     NT_SRV_HST(3),
     NT_SRV_XHST(4),
-    NT_UID(5);
+    NT_UID(5),
+    KRB5_NT_WELLKNOWN(11);
     
     private int value;
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/AlgorithmIdentifier.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/AlgorithmIdentifier.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/AlgorithmIdentifier.java
index ed7a736..6f5d1b2 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/AlgorithmIdentifier.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/AlgorithmIdentifier.java
@@ -20,11 +20,9 @@
 package org.apache.kerby.kerberos.kerb.spec.cms;
 
 
-import org.apache.kerby.asn1.type.Asn1Any;
 import org.apache.kerby.asn1.type.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
-import org.apache.kerby.asn1.type.Asn1Type;
 
 /**
  AlgorithmIdentifier  ::=  SEQUENCE  {
@@ -38,7 +36,7 @@ public class AlgorithmIdentifier extends Asn1SequenceType {
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(ALGORITHM, -1, Asn1ObjectIdentifier.class),
-            new Asn1FieldInfo(PARAMETERS, -1, Asn1Any.class)
+            new Asn1FieldInfo(PARAMETERS, -1, DHParameter.class)
     };
 
     public AlgorithmIdentifier() {
@@ -53,11 +51,11 @@ public class AlgorithmIdentifier extends Asn1SequenceType {
         setFieldAs(ALGORITHM, algorithm);
     }
 
-    public Asn1Type getParameters() {
-        return getFieldAsAny(PARAMETERS);
+    public DHParameter getParameters() {
+        return getFieldAs(PARAMETERS, DHParameter.class);
     }
 
-    public void setParameters(Asn1Type parameters) {
+    public void setParameters(DHParameter parameters) {
         setFieldAsAny(PARAMETERS, parameters);
     }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/DHParameter.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/DHParameter.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/DHParameter.java
new file mode 100644
index 0000000..6e4f81d
--- /dev/null
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/DHParameter.java
@@ -0,0 +1,51 @@
+package org.apache.kerby.kerberos.kerb.spec.cms;
+
+import org.apache.kerby.asn1.type.Asn1FieldInfo;
+import org.apache.kerby.asn1.type.Asn1Integer;
+import org.apache.kerby.asn1.type.Asn1SequenceType;
+
+import java.math.BigInteger;
+
+public class DHParameter extends Asn1SequenceType {
+
+    private static final int P = 0;
+    private static final int G = 1;
+    private static final int Q = 2;
+
+    static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
+            new Asn1FieldInfo(P, -1, Asn1Integer.class),
+            new Asn1FieldInfo(G, -1, Asn1Integer.class),
+            new Asn1FieldInfo(Q, -1, Asn1Integer.class),
+    };
+
+    public DHParameter() {
+        super(fieldInfos);
+    }
+
+    public void setP(BigInteger p) {
+        setFieldAsBigInteger(P, p);
+    }
+
+    public BigInteger getP() {
+        Asn1Integer p = getFieldAs(P, Asn1Integer.class);
+        return p.getValue();
+    }
+
+    public void setG(BigInteger g) {
+        setFieldAsBigInteger(G, g);
+    }
+
+    public BigInteger getG() {
+        Asn1Integer g = getFieldAs(G, Asn1Integer.class);
+        return g.getValue();
+    }
+
+    public void setQ(BigInteger q) {
+        setFieldAsBigInteger(Q, q);
+    }
+
+    public BigInteger getQ() {
+        Asn1Integer q = getFieldAs(Q, Asn1Integer.class);
+        return q.getValue();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/SubjectPublicKeyInfo.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/SubjectPublicKeyInfo.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/SubjectPublicKeyInfo.java
index e6e4392..d273da7 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/SubjectPublicKeyInfo.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/cms/SubjectPublicKeyInfo.java
@@ -50,8 +50,8 @@ public class SubjectPublicKeyInfo extends Asn1SequenceType {
         setFieldAs(ALGORITHM, algorithm);
     }
 
-    public byte[] getSubjectPubKey() {
-        return getFieldAsOctets(SUBJECT_PUBLIC_KEY);
+    public Asn1BitString getSubjectPubKey() {
+        return getFieldAs(SUBJECT_PUBLIC_KEY, Asn1BitString.class);
     }
 
     public void setSubjectPubKey(byte[] subjectPubKey) {

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/pa/pkinit/KdcDHKeyInfo.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/pa/pkinit/KdcDHKeyInfo.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/pa/pkinit/KdcDHKeyInfo.java
index 0e9504e..d21217d 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/pa/pkinit/KdcDHKeyInfo.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/pa/pkinit/KdcDHKeyInfo.java
@@ -62,4 +62,12 @@ public class KdcDHKeyInfo extends KrbSequenceType {
     public void setNonce(int nonce) {
         setFieldAsInt(NONCE, nonce);
     }
+
+    public KerberosTime getDHKeyExpiration() {
+        return getFieldAsTime(DH_KEY_EXPIRATION);
+    }
+
+    public void setDHKeyExpiration(KerberosTime time) {
+        setFieldAs(DH_KEY_EXPIRATION, time);
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfig.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfig.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfig.java
index 82b8dfd..8d1565e 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfig.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfig.java
@@ -174,4 +174,14 @@ public class KdcConfig extends Conf {
     public List<String> getIssuers() {
         return Arrays.asList(KrbConfHelper.getStringArrayUnderSection(this, KdcConfigKey.ISSUERS));
     }
+
+    public List<String> getPkinitAnchors() {
+        return Arrays.asList(KrbConfHelper.getStringArrayUnderSection(this,
+                KdcConfigKey.PKINIT_ANCHORS));
+    }
+
+    public String getPkinitIdentity() {
+        return KrbConfHelper.getStringUnderSection(this,
+                KdcConfigKey.PKINIT_IDENTITY);
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfigKey.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfigKey.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfigKey.java
index 178d19d..5e7d8a4 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfigKey.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcConfigKey.java
@@ -51,7 +51,9 @@ public enum KdcConfigKey implements SectionConfigKey {
     KDC_MAX_DGRAM_REPLY_SIZE(4096, "kdcdefaults"),
     VERIFY_KEY(null, "kdcdefaults"),
     DECRYPTION_KEY(null, "kdcdefaults"),
-    ISSUERS(null, "kdcdefaults");
+    ISSUERS(null, "kdcdefaults"),
+    PKINIT_IDENTITY(null, "libdefaults"),
+    PKINIT_ANCHORS(null, "libdefaults");
 
     private Object defaultValue;
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthContext.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthContext.java
index 551e1b3..51e14e2 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthContext.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthContext.java
@@ -19,15 +19,19 @@
  */
 package org.apache.kerby.kerberos.kerb.server.preauth;
 
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaData;
+
 import java.util.ArrayList;
 import java.util.List;
 
 public class PreauthContext {
     private boolean preauthRequired = true;
     private List<PreauthHandle> handles = new ArrayList<PreauthHandle>(5);
+    private PaData outputPaData;
 
     public PreauthContext() {
-
+        this.outputPaData = new PaData();
     }
 
     public boolean isPreauthRequired() {
@@ -41,4 +45,12 @@ public class PreauthContext {
     public List<PreauthHandle> getHandles() {
         return handles;
     }
+
+    public void reset() {
+        this.outputPaData = new PaData();
+    }
+
+    public PaData getOutputPaData() throws KrbException {
+        return outputPaData;
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandler.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandler.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandler.java
index cff6ba6..baa6324 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandler.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/PreauthHandler.java
@@ -23,6 +23,7 @@ import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.server.KdcContext;
 import org.apache.kerby.kerberos.kerb.server.preauth.builtin.EncTsPreauth;
 import org.apache.kerby.kerberos.kerb.server.preauth.builtin.TgtPreauth;
+import org.apache.kerby.kerberos.kerb.server.preauth.pkinit.PkinitPreauth;
 import org.apache.kerby.kerberos.kerb.server.preauth.token.TokenPreauth;
 import org.apache.kerby.kerberos.kerb.server.request.KdcRequest;
 import org.apache.kerby.kerberos.kerb.spec.pa.PaData;
@@ -54,6 +55,9 @@ public class PreauthHandler {
 
         preauth = new TokenPreauth();
         preauths.add(preauth);
+
+        preauth = new PkinitPreauth();
+        preauths.add(preauth);
     }
 
     /**
@@ -70,6 +74,7 @@ public class PreauthHandler {
         PreauthContext preauthContext = new PreauthContext();
 
         KdcContext kdcContext = kdcRequest.getKdcContext();
+        initWith(kdcContext);
         preauthContext.setPreauthRequired(kdcContext.getConfig().isPreauthRequired());
 
         for (KdcPreauth preauth : preauths) {
@@ -133,4 +138,13 @@ public class PreauthHandler {
         }
         return false;
     }
+
+    public static boolean isPkinit(PaData paData) {
+        for (PaDataEntry paEntry : paData.getElements()) {
+            if (paEntry.getPaDataType() == PaDataType.PK_AS_REQ) {
+                return true;
+            }
+        }
+        return false;
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/DhServer.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/DhServer.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/DhServer.java
new file mode 100644
index 0000000..d8bf903
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/DhServer.java
@@ -0,0 +1,133 @@
+/*
+ *  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.kerby.kerberos.kerb.server.preauth.pkinit;
+
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.X509EncodedKeySpec;
+
+
+/**
+ * The server-side of Diffie-Hellman key agreement for Kerberos PKINIT.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+class DhServer {
+    private static AlgorithmParameterSpec aesIv = new IvParameterSpec(new byte[16]);
+
+    private KeyAgreement serverKeyAgree;
+    private SecretKey serverAesKey;
+
+
+    PublicKey initAndDoPhase(byte[] clientPubKeyEnc) throws Exception {
+        /*
+         * The server has received the client's public key in encoded format.  The
+         * server instantiates a DH public key from the encoded key material.
+         */
+        KeyFactory serverKeyFac = KeyFactory.getInstance("DH");
+        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(clientPubKeyEnc);
+        PublicKey clientPubKey = serverKeyFac.generatePublic(x509KeySpec);
+
+        /*
+         * The server gets the DH parameters associated with the client's public
+         * key.  The server must use the same parameters when it generates its own key pair.
+         */
+        DHParameterSpec dhParamSpec = ((DHPublicKey) clientPubKey).getParams();
+
+        // The server creates its own DH key pair.
+        KeyPairGenerator serverKpairGen = KeyPairGenerator.getInstance("DH");
+        serverKpairGen.initialize(dhParamSpec);
+        KeyPair serverKpair = serverKpairGen.generateKeyPair();
+
+        // The server creates and initializes its DH KeyAgreement object.
+        serverKeyAgree = KeyAgreement.getInstance("DH");
+        serverKeyAgree.init(serverKpair.getPrivate());
+
+        /*
+         * The server uses the client's public key for the only phase of its
+         * side of the DH protocol.
+         */
+        serverKeyAgree.doPhase(clientPubKey, true);
+
+        // The server encodes its public key, and sends it over to the client.
+        return serverKpair.getPublic();
+    }
+
+
+    byte[] generateKey(byte[] clientDhNonce, byte[] serverDhNonce) {
+        // ZZ length will be same as public key.
+        byte[] dhSharedSecret = serverKeyAgree.generateSecret();
+        byte[] x = dhSharedSecret;
+
+        if (clientDhNonce != null && clientDhNonce.length > 0
+                && serverDhNonce != null && serverDhNonce.length > 0) {
+            x = concatenateBytes(dhSharedSecret, clientDhNonce);
+            x = concatenateBytes(x, serverDhNonce);
+        }
+
+        byte[] secret = OctetString2Key.kTruncate(dhSharedSecret.length, x);
+        serverAesKey = new SecretKeySpec(secret, 0, 16, "AES");
+
+        return serverAesKey.getEncoded();
+    }
+
+
+    /**
+     * Encrypt using AES in CTS mode.
+     *
+     * @param clearText
+     * @return The cipher text.
+     * @throws Exception
+     */
+    byte[] encryptAes(byte[] clearText) throws Exception {
+        // Use the secret key to encrypt/decrypt data.
+        Cipher serverCipher = Cipher.getInstance("AES/CTS/NoPadding");
+        serverCipher.init(Cipher.ENCRYPT_MODE, serverAesKey, aesIv);
+
+        return serverCipher.doFinal(clearText);
+    }
+
+
+    byte[] concatenateBytes(byte[] array1, byte[] array2) {
+        byte[] concatenatedBytes = new byte[array1.length + array2.length];
+
+        for (int i = 0; i < array1.length; i++) {
+            concatenatedBytes[i] = array1[i];
+        }
+
+        for (int j = array1.length; j < concatenatedBytes.length; j++) {
+            concatenatedBytes[j] = array2[j - array1.length];
+        }
+
+        return concatenatedBytes;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/OctetString2Key.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/OctetString2Key.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/OctetString2Key.java
new file mode 100644
index 0000000..9829642
--- /dev/null
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/OctetString2Key.java
@@ -0,0 +1,93 @@
+/*
+ *  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.kerby.kerberos.kerb.server.preauth.pkinit;
+
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+
+/**
+ * From RFC 4556:
+ * <p/>
+ * Define the function octetstring2key() as follows:
+ * <p/>
+ * octetstring2key(x) == random-to-key(K-truncate(
+ * SHA1(0x00 | x) |
+ * SHA1(0x01 | x) |
+ * SHA1(0x02 | x) |
+ * ...
+ * ))
+ * <p/>
+ * where x is an octet string; | is the concatenation operator; 0x00,
+ * 0x01, 0x02, etc. are each represented as a single octet; random-
+ * to-key() is an operation that generates a protocol key from a
+ * bitstring of length K; and K-truncate truncates its input to the
+ * first K bits.  Both K and random-to-key() are as defined in the
+ * kcrypto profile [RFC3961] for the enctype of the AS reply key.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class OctetString2Key {
+    /**
+     * Performs the function K-truncate to generate the AS reply key k.
+     *
+     * @param k
+     * @param x
+     * @return The AS reply key value.
+     */
+    public static byte[] kTruncate(int k, byte[] x) {
+        int numberOfBytes = k / 8;
+        byte[] result = new byte[numberOfBytes];
+
+        int count = 0;
+        byte[] filler = calculateIntegrity((byte) count, x);
+
+        int position = 0;
+
+        for (int i = 0; i < numberOfBytes; i++) {
+            if (position < filler.length) {
+                result[i] = filler[position];
+                position++;
+            } else {
+                count++;
+                filler = calculateIntegrity((byte) count, x);
+                position = 0;
+                result[i] = filler[position];
+                position++;
+            }
+        }
+
+        return result;
+    }
+
+
+    private static byte[] calculateIntegrity(byte count, byte[] data) {
+        try {
+            MessageDigest digester = MessageDigest.getInstance("SHA1");
+            digester.update(count);
+
+            return digester.digest(data);
+        } catch (NoSuchAlgorithmException nsae) {
+            return new byte[0];
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitKdcContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitKdcContext.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitKdcContext.java
index 9fb9e51..137b64f 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitKdcContext.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitKdcContext.java
@@ -1,30 +1,31 @@
 /**
- *  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. 
- *  
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.kerby.kerberos.kerb.server.preauth.pkinit;
 
 import org.apache.kerby.kerberos.kerb.preauth.pkinit.IdentityOpts;
+import org.apache.kerby.kerberos.kerb.preauth.pkinit.PkinitPlgCryptoContext;
 import org.apache.kerby.kerberos.kerb.preauth.pkinit.PluginOpts;
 
 public class PkinitKdcContext {
 
-    public PluginOpts pluginOpts;
-    public IdentityOpts identityOpts;
+    public PkinitPlgCryptoContext cryptoctx = new PkinitPlgCryptoContext();
+    public PluginOpts pluginOpts = new PluginOpts();
+    public IdentityOpts identityOpts = new IdentityOpts();
     public String realm;
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java
index 08baa0e..54f0693 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java
@@ -1,42 +1,86 @@
 /**
- *  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. 
- *  
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.kerby.kerberos.kerb.server.preauth.pkinit;
 
+import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.kerberos.kerb.KrbCodec;
+import org.apache.kerby.kerberos.kerb.KrbErrorCode;
 import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.common.CheckSumUtil;
+import org.apache.kerby.kerberos.kerb.common.KrbUtil;
 import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
+import org.apache.kerby.kerberos.kerb.preauth.pkinit.CMSMessageType;
+import org.apache.kerby.kerberos.kerb.preauth.pkinit.CertificateHelper;
+import org.apache.kerby.kerberos.kerb.preauth.pkinit.PkinitCrypto;
 import org.apache.kerby.kerberos.kerb.preauth.pkinit.PkinitPreauthMeta;
 import org.apache.kerby.kerberos.kerb.server.KdcContext;
 import org.apache.kerby.kerberos.kerb.server.preauth.AbstractPreauthPlugin;
 import org.apache.kerby.kerberos.kerb.server.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.base.CheckSum;
+import org.apache.kerby.kerberos.kerb.spec.base.CheckSumType;
 import org.apache.kerby.kerberos.kerb.spec.base.PrincipalName;
+import org.apache.kerby.kerberos.kerb.spec.cms.DHParameter;
+import org.apache.kerby.kerberos.kerb.spec.cms.SubjectPublicKeyInfo;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcOption;
 import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
 import org.apache.kerby.kerberos.kerb.spec.pa.PaDataType;
+import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.AuthPack;
+import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.DHRepInfo;
+import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.KdcDHKeyInfo;
+import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.PaPkAsRep;
 import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.PaPkAsReq;
+import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.PkAuthenticator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import sun.security.pkcs.ContentInfo;
+import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.SignerInfo;
+import sun.security.util.DerValue;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.AlgorithmId;
 
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHPublicKeySpec;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Scanner;
 
 public class PkinitPreauth extends AbstractPreauthPlugin {
 
+    private static final Logger LOG = LoggerFactory.getLogger(PkinitPreauth.class);
     private final Map<String, PkinitKdcContext> pkinitContexts;
+    private static final String ID_PKINIT_DHKEYDATA = "1.3.6.1.5.2.3.2";
 
     public PkinitPreauth() {
         super(new PkinitPreauthMeta());
@@ -50,6 +94,10 @@ public class PkinitPreauth extends AbstractPreauthPlugin {
 
         PkinitKdcContext tmp = new PkinitKdcContext();
         tmp.realm = kdcContext.getKdcRealm();
+
+        String pkinitIdentity = kdcContext.getConfig().getPkinitIdentity();
+        tmp.identityOpts.identity = pkinitIdentity;
+
         pkinitContexts.put(kdcContext.getKdcRealm(), tmp);
     }
 
@@ -66,18 +114,129 @@ public class PkinitPreauth extends AbstractPreauthPlugin {
     public boolean verify(KdcRequest kdcRequest, PluginRequestContext requestContext,
                           PaDataEntry paData) throws KrbException {
 
+        LOG.info("pkinit verify padata: entered!");
+
         PkinitRequestContext reqCtx = (PkinitRequestContext) requestContext;
-        PkinitKdcContext pkinitContext = findContext(kdcRequest.getServerPrincipal());
+        PrincipalName serverPrincipal = kdcRequest.getServerEntry().getPrincipal();
+        kdcRequest.setServerPrincipal(serverPrincipal);
+        PkinitKdcContext pkinitContext = findContext(serverPrincipal);
         if (pkinitContext == null) {
             return false;
         }
 
         reqCtx.paType = paData.getPaDataType();
         if (paData.getPaDataType() == PaDataType.PK_AS_REQ) {
+
+            LOG.info("processing PK_AS_REQ");
             PaPkAsReq paPkAsReq = KrbCodec.decode(paData.getPaDataValue(), PaPkAsReq.class);
-            if (paPkAsReq == null) {
-                return false;
+
+            byte[] signedAuthPack = paPkAsReq.getSignedAuthPack();
+            PKCS7 pkcs7 = null;
+            try {
+                pkcs7 = PkinitCrypto.verifyCMSSignedData(pkinitContext.cryptoctx,
+                        CMSMessageType.CMS_SIGN_CLIENT, signedAuthPack);
+            } catch (IOException e) {
+                e.getMessage();
+            }
+
+            Boolean isSigned = PkinitCrypto.isSigned(pkcs7);
+            if (isSigned) {
+                //TODO
+                LOG.info("Signed data.");
+            } else {
+                PrincipalName clientPrincial = kdcRequest.getClientEntry().getPrincipal();
+                PrincipalName anonymousPrincipal = KrbUtil.makeAnonymousPrincipal();
+
+                /* If anonymous requests are being used, adjust the realm of the client principal. */
+                if (kdcRequest.getKdcOptions().isFlagSet(KdcOption.REQUEST_ANONYMOUS)
+                        && !KrbUtil.pricipalCompareIgnoreRealm(clientPrincial, anonymousPrincipal)) {
+                    String errMsg = "Pkinit request not signed, but client not anonymous.";
+                    LOG.error(errMsg);
+                    throw new KrbException(KrbErrorCode.KDC_ERR_PREAUTH_FAILED, errMsg);
+                }
             }
+
+            ContentInfo contentInfo = pkcs7.getContentInfo();
+            AuthPack authPack = null;
+            try {
+                authPack = KrbCodec.decode(contentInfo.getContentBytes(), AuthPack.class);
+            } catch (IOException e) {
+                LOG.error("failed to decode AuthPack " + e.getMessage());
+            }
+
+            PkAuthenticator pkAuthenticator = authPack.getPkAuthenticator();
+
+            checkClockskew(kdcRequest, pkAuthenticator.getCtime());
+            DHParameter dhParameter = null;
+            if (authPack.getClientPublicValue() != null) {
+                dhParameter = authPack.getClientPublicValue().getAlgorithm().getParameters();
+                PkinitCrypto.serverCheckDH(pkinitContext.pluginOpts, pkinitContext.cryptoctx, dhParameter);
+            } else if (!isSigned) {
+                /*Anonymous pkinit requires DH*/
+                String errMessage = "Anonymous pkinit without DH public value not supported.";
+                LOG.error(errMessage);
+                throw new KrbException(KrbErrorCode.KDC_ERR_PREAUTH_FAILED, errMessage);
+            }
+
+            CheckSum expectedCheckSum = null;
+            try {
+                expectedCheckSum = CheckSumUtil.makeCheckSum(CheckSumType.NIST_SHA,
+                        kdcRequest.getKdcReq().getReqBody().encode());
+            } catch (KrbException e) {
+                LOG.error("Unable to calculate AS REQ checksum.", e.getMessage());
+            }
+
+            CheckSum receivedCheckSum = KrbCodec.decode(pkAuthenticator.getPaChecksum(), CheckSum.class);
+
+            if (expectedCheckSum.encodingLength() != receivedCheckSum.encodingLength()
+                    || !Arrays.equals(expectedCheckSum.getChecksum(), receivedCheckSum.getChecksum())) {
+                LOG.debug("Received checksum type: " + receivedCheckSum.getCksumtype()
+                        + ", received checksum length: " + receivedCheckSum.encodingLength()
+                        + ", expected checksum type: " + expectedCheckSum.getCksumtype()
+                        + ", expected checksum length: " + expectedCheckSum.encodingLength());
+                String errorMessage = "Failed to match the checksum.";
+                LOG.error(errorMessage);
+                throw new KrbException(KrbErrorCode.KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED, errorMessage);
+            }
+
+            BigInteger p = dhParameter.getP();
+            BigInteger g = dhParameter.getG();
+
+            SubjectPublicKeyInfo publicKeyInfo = authPack.getClientPublicValue();
+            byte[] clientSubjectPubKey = publicKeyInfo.getSubjectPubKey().getValue();
+            Asn1Integer clientPubKey = KrbCodec.decode(clientSubjectPubKey, Asn1Integer.class);
+            BigInteger y = clientPubKey.getValue();
+
+            DHPublicKeySpec dhPublicKeySpec = new DHPublicKeySpec(y, p, g);
+
+            KeyFactory keyFactory = null;
+            try {
+                keyFactory = KeyFactory.getInstance("DH");
+            } catch (NoSuchAlgorithmException e) {
+                e.printStackTrace();
+            }
+            DHPublicKey dhPublicKey = null;
+            try {
+                dhPublicKey = (DHPublicKey) keyFactory.generatePublic(dhPublicKeySpec);
+            } catch (InvalidKeySpecException e) {
+                e.printStackTrace();
+            }
+
+            DhServer server = new DhServer();
+            DHPublicKey serverPubKey = null;
+            try {
+                serverPubKey = (DHPublicKey) server.initAndDoPhase(dhPublicKey.getEncoded());
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            server.generateKey(null, null);
+
+            String identity = pkinitContext.identityOpts.identity;
+
+            PaPkAsRep paPkAsRep = makePaPkAsRep(serverPubKey, identity);
+            PaDataEntry paDataEntry = makeEntry(paPkAsRep);
+
+            kdcRequest.getPreauthContext().getOutputPaData().add(paDataEntry);
         }
 
         return true;
@@ -90,4 +249,109 @@ public class PkinitPreauth extends AbstractPreauthPlugin {
         }
         return null;
     }
+
+    /**
+     * Make padata entry.
+     *
+     * @param paPkAsRep The PaPkAsRep
+     * @return PaDataEntry to be made.
+     */
+    private PaDataEntry makeEntry(PaPkAsRep paPkAsRep) throws KrbException {
+
+        PaDataEntry paDataEntry = new PaDataEntry();
+        paDataEntry.setPaDataType(PaDataType.PK_AS_REP);
+        paDataEntry.setPaDataValue(paPkAsRep.encode());
+        return paDataEntry;
+    }
+
+    private PaPkAsRep makePaPkAsRep(DHPublicKey severPubKey, String identityString) {
+
+        List<String> identityList = Arrays.asList(identityString.split(","));
+
+        List<X509Certificate> certificates = new ArrayList<>();
+        for (String identity : identityList) {
+            File file = new File(identity);
+
+            try {
+                Scanner scanner = new Scanner(file);
+                String found = scanner.findInLine("CERTIFICATE");
+
+                if (found != null) {
+                    InputStream res = null;
+                    try {
+                        res = new FileInputStream(identity);
+                    } catch (FileNotFoundException e) {
+                        e.printStackTrace();
+                    }
+                    X509Certificate certificate = null;
+                    try {
+                        certificate = (X509Certificate) CertificateHelper.loadCerts(res).iterator().next();
+                    } catch (KrbException e) {
+                        e.printStackTrace();
+                    }
+                    certificates.add(certificate);
+                }
+            } catch (FileNotFoundException e) {
+                e.getMessage();
+            }
+        }
+
+        PaPkAsRep paPkAsRep = new PaPkAsRep();
+
+        DHRepInfo dhRepInfo = new DHRepInfo();
+
+        KdcDHKeyInfo kdcDhKeyInfo = new KdcDHKeyInfo();
+
+        Asn1Integer publickey = new Asn1Integer(severPubKey.getY());
+        kdcDhKeyInfo.setSubjectPublicKey(publickey.encode());
+        kdcDhKeyInfo.setNonce(1);
+        kdcDhKeyInfo.setDHKeyExpiration(
+                new KerberosTime(System.currentTimeMillis() + KerberosTime.DAY));
+
+        ByteArrayOutputStream signedData = null;
+        try {
+            signedData = cmsSignedDataCreate(kdcDhKeyInfo, certificates);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        dhRepInfo.setDHSignedData(signedData.toByteArray());
+
+        paPkAsRep.setDHRepInfo(dhRepInfo);
+//        paPkAsRep.setEncKeyPack("enckey".getBytes());
+
+        return paPkAsRep;
+    }
+
+
+    public static ContentInfo createContentInfo(byte[] data, ObjectIdentifier oid) {
+
+        ContentInfo contentInfo = new ContentInfo(
+                oid,
+                new DerValue(DerValue.tag_OctetString, data));
+        return contentInfo;
+    }
+
+    public static ByteArrayOutputStream cmsSignedDataCreate(KdcDHKeyInfo kdcDHKeyInfo,
+                                                            List<X509Certificate> certificates) throws IOException {
+
+        ObjectIdentifier oid = new ObjectIdentifier(ID_PKINIT_DHKEYDATA);
+        ContentInfo contentInfo = createContentInfo(kdcDHKeyInfo.encode(), oid);
+
+        PKCS7 p7 = new PKCS7(new AlgorithmId[0], contentInfo,
+                certificates.toArray(new X509Certificate[certificates.size()]), new SignerInfo[0]);
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+        p7.encodeSignedData(bytes);
+        return bytes;
+    }
+
+    public boolean checkClockskew(KdcRequest kdcRequest, KerberosTime time) throws KrbException {
+        long clockSkew = kdcRequest.getKdcContext().getConfig().getAllowableClockSkew() * 1000;
+
+        if (!time.isInClockSkew(clockSkew)) {
+            throw new KrbException(KrbErrorCode.KDC_ERR_PREAUTH_FAILED);
+        } else {
+            return true;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java
index 2765673..6ccd774 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/AsRequest.java
@@ -129,6 +129,10 @@ public class AsRequest extends KdcRequest {
             clientKey, KeyUsage.AS_REP_ENCPART);
         reply.setEncryptedEncPart(encryptedData);
 
+        if (isPkinit()) {
+            reply.setPaData(getPreauthContext().getOutputPaData());
+        }
+
         setReply(reply);
     }
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
index 521ab51..2a014b1 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
@@ -54,6 +54,8 @@ import org.apache.kerby.kerberos.kerb.spec.fast.ArmorType;
 import org.apache.kerby.kerberos.kerb.spec.fast.KrbFastArmor;
 import org.apache.kerby.kerberos.kerb.spec.fast.KrbFastArmoredReq;
 import org.apache.kerby.kerberos.kerb.spec.fast.KrbFastReq;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcOption;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcOptions;
 import org.apache.kerby.kerberos.kerb.spec.kdc.KdcRep;
 import org.apache.kerby.kerberos.kerb.spec.kdc.KdcReq;
 import org.apache.kerby.kerberos.kerb.spec.pa.PaData;
@@ -92,6 +94,7 @@ public abstract class KdcRequest {
     private byte[] innerBodyout;
     private AuthToken token;
     private Boolean isToken = false;
+    private Boolean isPkinit = false;
     private EncryptionKey sessionKey;
 
     /**
@@ -167,6 +170,9 @@ public abstract class KdcRequest {
             checkClient();
             checkServer();
         } else {
+            if (PreauthHandler.isPkinit(getKdcReq().getPaData())) {
+                isPkinit = true;
+            }
             checkClient();
             checkServer();
             preauth();
@@ -537,10 +543,17 @@ public abstract class KdcRequest {
         PaData preAuthData = request.getPaData();
 
         if (isPreauthRequired()) {
+            if (getKdcOptions().isFlagSet(KdcOption.REQUEST_ANONYMOUS) && !isPkinit) {
+                LOG.info("Need PKINIT.");
+                KrbError krbError = makePreAuthenticationError(kdcContext, request,
+                        KrbErrorCode.KDC_ERR_PREAUTH_REQUIRED, true);
+                throw new KdcRecoverableException(krbError);
+            }
+
             if (preAuthData == null || preAuthData.isEmpty()) {
                 LOG.info("The preauth data is empty.");
                 KrbError krbError = makePreAuthenticationError(kdcContext, request,
-                        KrbErrorCode.KDC_ERR_PREAUTH_REQUIRED);
+                        KrbErrorCode.KDC_ERR_PREAUTH_REQUIRED, false);
                 throw new KdcRecoverableException(krbError);
             } else {
                 getPreauthHandler().verify(this, preAuthData);
@@ -646,7 +659,7 @@ public abstract class KdcRequest {
      * @return The krb error reply to client
      */
     protected KrbError makePreAuthenticationError(KdcContext kdcContext, KdcReq request,
-                                                  KrbErrorCode errorCode)
+                                                  KrbErrorCode errorCode, boolean pkinit)
             throws KrbException {
         List<EncryptionType> encryptionTypes = kdcContext.getConfig().getEncryptionTypes();
         List<EncryptionType> clientEtypes = request.getReqBody().getEtypes();
@@ -685,6 +698,11 @@ public abstract class KdcRequest {
         }
         methodData.add(new PaDataEntry(PaDataType.ETYPE_INFO2, encTypeInfo2));
 
+        if(pkinit) {
+            methodData.add(new PaDataEntry(PaDataType.PK_AS_REQ, "empty".getBytes()));
+            methodData.add(new PaDataEntry(PaDataType.PK_AS_REP, "empty".getBytes()));
+        }
+
         KrbError krbError = new KrbError();
         krbError.setErrorCode(errorCode);
         byte[] encodedData = KrbCodec.encode(methodData);
@@ -782,4 +800,12 @@ public abstract class KdcRequest {
     protected AuthToken getToken() {
         return token;
     }
+
+    protected boolean isPkinit() {
+        return isPkinit;
+    }
+
+    public KdcOptions getKdcOptions() {
+        return kdcReq.getReqBody().getKdcOptions();
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/KinitTool.java
----------------------------------------------------------------------
diff --git a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/KinitTool.java b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/KinitTool.java
index a89e4f5..5ea108a 100644
--- a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/KinitTool.java
+++ b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/kinit/KinitTool.java
@@ -116,6 +116,7 @@ public class KinitTool {
 
         if (ktOptions.contains(KinitOption.ANONYMOUS)) {
             ktOptions.add(KrbOption.USE_PKINIT_ANONYMOUS);
+            ktOptions.add(KrbOption.PKINIT_X509_ANCHORS);
         } else if (!ktOptions.contains(KinitOption.USE_KEYTAB)) {
             //If not request tickets by keytab than by password.
             ktOptions.add(KinitOption.USE_PASSWD);


[2/2] directory-kerby git commit: Add some implemention of pkinit anonymous.

Posted by pl...@apache.org.
Add some implemention of pkinit anonymous.


Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/14696718
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/14696718
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/14696718

Branch: refs/heads/pkinit-support
Commit: 146967182411d0bce1d48e7ce8499184f8f7fb1c
Parents: f6d5088
Author: plusplusjiajia <ji...@intel.com>
Authored: Tue Nov 24 15:55:04 2015 +0800
Committer: plusplusjiajia <ji...@intel.com>
Committed: Tue Nov 24 15:55:04 2015 +0800

----------------------------------------------------------------------
 docs/kerby-checkstyle.xml                       |   2 +-
 .../org/apache/kerby/asn1/UniversalTag.java     |   3 +-
 .../kerby/asn1/type/Asn1CollectionType.java     |   5 +
 kerby-dist/kdc-dist/conf/kdc.conf               |   4 +-
 kerby-dist/tool-dist/conf/krb5.conf             |   5 +-
 kerby-dist/tool-dist/pom.xml                    |   5 +
 .../kerby/kerberos/kdc/WithCertKdcTest.java     |  41 +++
 .../kerby/kerberos/kerb/client/KrbClient.java   |   4 +-
 .../kerby/kerberos/kerb/client/KrbHandler.java  |   1 +
 .../client/impl/AbstractInternalKrbClient.java  |   7 +-
 .../kerb/client/preauth/PreauthHandler.java     |   3 +-
 .../kerb/client/preauth/pkinit/DhClient.java    |   6 +-
 .../kerb/client/preauth/pkinit/DhServer.java    |   4 +-
 .../client/preauth/pkinit/PkinitContext.java    |   3 +-
 .../client/preauth/pkinit/PkinitCrypto.java     | 144 ---------
 .../client/preauth/pkinit/PkinitPreauth.java    | 164 ++++++++--
 .../preauth/pkinit/PkinitRequestOpts.java       |   2 +-
 .../client/preauth/pkinit/SignedDataEngine.java |  95 +++---
 .../kerb/client/preauth/pkinit/Util.java        | 153 ++++++++++
 .../kerberos/kerb/client/request/AsRequest.java |   8 +-
 .../kerb/client/request/AsRequestWithCert.java  |  49 ++-
 .../preauth/pkinit/DhKeyAgreementTest.java      |  68 ++++-
 .../kerby/kerberos/kerb/common/KrbUtil.java     |  63 ++--
 .../kerb/preauth/pkinit/CMSMessageType.java     |  59 ++++
 .../kerb/preauth/pkinit/CertificateHelper.java  |  45 +++
 .../kerb/preauth/pkinit/PkinitCrypto.java       | 170 +++++++++++
 .../preauth/pkinit/PkinitPlgCryptoContext.java  | 141 +++++++++
 .../kerb/preauth/pkinit/PluginOpts.java         |   2 +-
 .../kerby/kerberos/kerb/spec/base/KrbFlags.java |   4 +-
 .../kerby/kerberos/kerb/spec/base/NameType.java |   3 +-
 .../kerb/spec/cms/AlgorithmIdentifier.java      |  10 +-
 .../kerberos/kerb/spec/cms/DHParameter.java     |  51 ++++
 .../kerb/spec/cms/SubjectPublicKeyInfo.java     |   4 +-
 .../kerb/spec/pa/pkinit/KdcDHKeyInfo.java       |   8 +
 .../kerby/kerberos/kerb/server/KdcConfig.java   |  10 +
 .../kerberos/kerb/server/KdcConfigKey.java      |   4 +-
 .../kerb/server/preauth/PreauthContext.java     |  14 +-
 .../kerb/server/preauth/PreauthHandler.java     |  14 +
 .../kerb/server/preauth/pkinit/DhServer.java    | 133 ++++++++
 .../server/preauth/pkinit/OctetString2Key.java  |  93 ++++++
 .../server/preauth/pkinit/PkinitKdcContext.java |  39 +--
 .../server/preauth/pkinit/PkinitPreauth.java    | 304 +++++++++++++++++--
 .../kerberos/kerb/server/request/AsRequest.java |   4 +
 .../kerb/server/request/KdcRequest.java         |  30 +-
 .../kerby/kerberos/tool/kinit/KinitTool.java    |   1 +
 45 files changed, 1680 insertions(+), 302 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/docs/kerby-checkstyle.xml
----------------------------------------------------------------------
diff --git a/docs/kerby-checkstyle.xml b/docs/kerby-checkstyle.xml
index 3538cd6..6af4748 100644
--- a/docs/kerby-checkstyle.xml
+++ b/docs/kerby-checkstyle.xml
@@ -67,7 +67,7 @@
         <!-- Checks for imports                              -->
         <!-- See http://checkstyle.sf.net/config_import.html -->
         <module name="AvoidStarImport"/>
-        <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
+        <!--module name="IllegalImport"/--> <!-- defaults to sun.* packages -->
         <module name="RedundantImport"/>
         <module name="UnusedImports"/>
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-asn1/src/main/java/org/apache/kerby/asn1/UniversalTag.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/UniversalTag.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/UniversalTag.java
index 7bc1868..d007dac 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/UniversalTag.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/UniversalTag.java
@@ -26,7 +26,7 @@ package org.apache.kerby.asn1;
  */
 public enum UniversalTag {
     UNKNOWN             (-1),
-    CHOICE              (-2),   // Only for internal using
+    CHOICE              (0x20),   // Only for internal using
     BER_UNDEFINED_LENGTH(0),    // Used to encode undefined length with BER
     BOOLEAN             (0x01),
     INTEGER             (0x02),
@@ -118,6 +118,7 @@ public enum UniversalTag {
             case 0x1D : return CHARACTER_STRING;
             case 0x1E : return BMP_STRING;
             case 0x1F : return RESERVED_31;
+            case 0x20 : return CHOICE;
             default : return UNKNOWN;
         }
     }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java
index 194ae8c..f5be6c6 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java
@@ -24,6 +24,7 @@ import org.apache.kerby.asn1.TagClass;
 import org.apache.kerby.asn1.TaggingOption;
 
 import java.io.IOException;
+import java.math.BigInteger;
 import java.nio.ByteBuffer;
 
 /**
@@ -180,6 +181,10 @@ public abstract class Asn1CollectionType extends AbstractAsn1Type<Asn1Collection
         setFieldAs(index, new Asn1Integer(value));
     }
 
+    protected void setFieldAsBigInteger(int index, BigInteger value) {
+        setFieldAs(index, new Asn1Integer(value));
+    }
+
     protected Asn1Type getFieldAsAny(int index) {
         Asn1Any any = getFieldAs(index, Asn1Any.class);
         if (any != null) {

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-dist/kdc-dist/conf/kdc.conf
----------------------------------------------------------------------
diff --git a/kerby-dist/kdc-dist/conf/kdc.conf b/kerby-dist/kdc-dist/conf/kdc.conf
index ac72940..e92345a 100644
--- a/kerby-dist/kdc-dist/conf/kdc.conf
+++ b/kerby-dist/kdc-dist/conf/kdc.conf
@@ -18,6 +18,6 @@
 
 [kdcdefaults]
   kdc_host = localhost
-  kdc_udp_port = 8014
-  kdc_tcp_port = 8015
+  kdc_udp_port = 88
+  kdc_tcp_port = 88
   kdc_realm = EXAMPLE.COM

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-dist/tool-dist/conf/krb5.conf
----------------------------------------------------------------------
diff --git a/kerby-dist/tool-dist/conf/krb5.conf b/kerby-dist/tool-dist/conf/krb5.conf
index 698daac..e857b84 100644
--- a/kerby-dist/tool-dist/conf/krb5.conf
+++ b/kerby-dist/tool-dist/conf/krb5.conf
@@ -19,5 +19,6 @@
 [libdefaults]
     kdc_realm = EXAMPLE.COM
     default_realm = EXAMPLE.COM
-    kdc_udp_port = 8014
-    kdc_tcp_port = 8015
+    kdc_udp_port = 88
+    kdc_tcp_port = 88
+    pkinit_anchors = /etc/krb5/cacert.pem

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-dist/tool-dist/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-dist/tool-dist/pom.xml b/kerby-dist/tool-dist/pom.xml
index 7bf67ce..f8e8ec0 100644
--- a/kerby-dist/tool-dist/pom.xml
+++ b/kerby-dist/tool-dist/pom.xml
@@ -64,6 +64,11 @@
       <artifactId>log4j</artifactId>
       <version>${log4j.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-jdk15on</artifactId>
+      <version>1.52</version>
+    </dependency>
   </dependencies>
 
   <profiles>

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithCertKdcTest.java
----------------------------------------------------------------------
diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithCertKdcTest.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithCertKdcTest.java
index 7947a63..201e736 100644
--- a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithCertKdcTest.java
+++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/WithCertKdcTest.java
@@ -22,13 +22,16 @@ package org.apache.kerby.kerberos.kdc;
 import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.KrbRuntime;
 import org.apache.kerby.kerberos.kerb.provider.PkiLoader;
+import org.apache.kerby.kerberos.kerb.server.KdcConfigKey;
 import org.apache.kerby.kerberos.kerb.server.KdcTestBase;
 import org.apache.kerby.kerberos.kerb.spec.ticket.ServiceTicket;
 import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket;
 import org.apache.kerby.kerberos.provider.pki.KerbyPkiProvider;
 import org.junit.Before;
+import org.junit.Test;
 
 import java.io.InputStream;
+import java.net.URL;
 import java.security.PrivateKey;
 import java.security.cert.Certificate;
 
@@ -49,6 +52,7 @@ public class WithCertKdcTest extends KdcTestBase {
     private String serverPrincipal;
     private Certificate userCert;
     private PrivateKey userKey;
+    private Certificate caCert;
 
     @Before
     public void setUp() throws Exception {
@@ -59,12 +63,49 @@ public class WithCertKdcTest extends KdcTestBase {
     }
 
     @Override
+    protected void configKdcSeverAndClient() {
+        super.configKdcSeverAndClient();
+
+        String pkinitIdentity = getClass().getResource("/kdccert.pem").getPath() + ","
+                + getClass().getResource("/kdckey.pem").getPath();
+        getKdcServer().getKdcConfig().setString(KdcConfigKey.PKINIT_IDENTITY, pkinitIdentity);
+    }
+
+    @Override
     protected void setUpClient() throws Exception {
         super.setUpClient();
 
         loadCredentials();
     }
 
+    @Override
+    protected void createPrincipals() throws KrbException {
+        super.createPrincipals();
+        //Anonymity support is not enabled by default.
+        //To enable it, you must create the principal WELLKNOWN/ANONYMOUS
+        getKdcServer().createPrincipal("WELLKNOWN/ANONYMOUS");
+    }
+
+    @Test
+    public void testAnonymity() throws Exception {
+
+        getKrbClient().init();
+
+        URL url = getClass().getResource("/cacert.pem");
+        TgtTicket tgt = null;
+        try {
+            tgt = getKrbClient().requestTgtWithPkintAnonymous(url.getPath());
+        } catch (KrbException te) {
+            assertThat(te.getMessage().contains("timeout")).isTrue();
+            return;
+        }
+        assertThat(tgt).isNull();
+
+        serverPrincipal = getServerPrincipal();
+        ServiceTicket tkt = getKrbClient().requestServiceTicketWithTgt(tgt, serverPrincipal);
+        assertThat(tkt).isNull();
+    }
+
     //@Test
     public void testKdc() throws Exception {
         assertThat(userCert).isNotNull();

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbClient.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbClient.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbClient.java
index b5ec953..0b61f80 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbClient.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbClient.java
@@ -214,9 +214,11 @@ public class KrbClient {
      * @return TGT
      * @throws KrbException e
      */
-    public TgtTicket requestTgtWithPkintAnonymous() throws KrbException {
+    public TgtTicket requestTgtWithPkintAnonymous(String certificatePath) throws KrbException {
         KOptions requestOptions = new KOptions();
         requestOptions.add(KrbOption.USE_PKINIT_ANONYMOUS);
+        requestOptions.add(KrbOption.CLIENT_PRINCIPAL, "WELLKNOWN/ANONYMOUS");
+        requestOptions.add(KrbOption.PKINIT_X509_ANCHORS, certificatePath);
         return requestTgtWithOptions(requestOptions);
     }
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java
index 89eb1f5..7e6f928 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java
@@ -108,6 +108,7 @@ public abstract class KrbHandler {
 
         KrbMessageType messageType = kdcRep.getMsgType();
         if (messageType == KrbMessageType.AS_REP) {
+
             kdcRequest.processResponse((KdcRep) kdcRep);
         } else if (messageType == KrbMessageType.TGS_REP) {
             kdcRequest.processResponse((KdcRep) kdcRep);

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/AbstractInternalKrbClient.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/AbstractInternalKrbClient.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/AbstractInternalKrbClient.java
index 2c55ff8..baf97d8 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/AbstractInternalKrbClient.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/AbstractInternalKrbClient.java
@@ -33,6 +33,7 @@ import org.apache.kerby.kerberos.kerb.client.request.AsRequestWithToken;
 import org.apache.kerby.kerberos.kerb.client.request.TgsRequest;
 import org.apache.kerby.kerberos.kerb.client.request.TgsRequestWithTgt;
 import org.apache.kerby.kerberos.kerb.client.request.TgsRequestWithToken;
+import org.apache.kerby.kerberos.kerb.spec.base.NameType;
 import org.apache.kerby.kerberos.kerb.spec.base.PrincipalName;
 import org.apache.kerby.kerberos.kerb.spec.ticket.ServiceTicket;
 import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket;
@@ -98,7 +99,11 @@ public abstract class AbstractInternalKrbClient implements InternalKrbClient {
             String principal = requestOptions.getStringOption(
                     KrbOption.CLIENT_PRINCIPAL);
             principal = fixPrincipal(principal);
-            asRequest.setClientPrincipal(new PrincipalName(principal));
+            PrincipalName principalName = new PrincipalName(principal);
+            if (requestOptions.contains(KrbOption.USE_PKINIT_ANONYMOUS)) {
+                principalName.setNameType(NameType.KRB5_NT_WELLKNOWN);
+            }
+            asRequest.setClientPrincipal(principalName);
         }
         asRequest.setKrbOptions(requestOptions);
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandler.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandler.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandler.java
index 7494a5c..3eda45e 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandler.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandler.java
@@ -87,6 +87,7 @@ public class PreauthHandler {
             return;
         }
 
+        setPreauthOptions(kdcRequest, kdcRequest.getPreauthOptions());
         if (!preauthContext.hasInputPaData()) {
             tryFirst(kdcRequest, preauthContext.getOutputPaData());
             return;
@@ -94,8 +95,6 @@ public class PreauthHandler {
 
         // attemptETypeInfo(kdcRequest, preauthContext.getInputPaData());
 
-        setPreauthOptions(kdcRequest, kdcRequest.getPreauthOptions());
-
         prepareUserResponses(kdcRequest, preauthContext.getInputPaData());
 
         preauthContext.getUserResponser().respondQuestions();

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhClient.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhClient.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhClient.java
index ca2be20..834da2f 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhClient.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhClient.java
@@ -23,6 +23,7 @@ package org.apache.kerby.kerberos.kerb.client.preauth.pkinit;
 import javax.crypto.Cipher;
 import javax.crypto.KeyAgreement;
 import javax.crypto.SecretKey;
+import javax.crypto.interfaces.DHPublicKey;
 import javax.crypto.spec.DHParameterSpec;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
@@ -47,7 +48,7 @@ class DhClient {
     private SecretKey clientAesKey;
 
 
-    byte[] init(DHParameterSpec dhParamSpec) throws Exception {
+    DHPublicKey init(DHParameterSpec dhParamSpec) throws Exception {
         // The client creates its own DH key pair, using the DH parameters from above.
         KeyPairGenerator clientKpairGen = KeyPairGenerator.getInstance("DH");
         clientKpairGen.initialize(dhParamSpec);
@@ -58,7 +59,8 @@ class DhClient {
         clientKeyAgree.init(clientKpair.getPrivate());
 
         // The client encodes its public key, and sends it over to the server.
-        return clientKpair.getPublic().getEncoded();
+//        return clientKpair.getPublic().getEncoded();
+        return (DHPublicKey) clientKpair.getPublic();
     }
 
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhServer.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhServer.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhServer.java
index 0c8aa0d..60084ea 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhServer.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhServer.java
@@ -49,7 +49,7 @@ class DhServer {
     private SecretKey serverAesKey;
 
 
-    byte[] initAndDoPhase(byte[] clientPubKeyEnc) throws Exception {
+    PublicKey initAndDoPhase(byte[] clientPubKeyEnc) throws Exception {
         /*
          * The server has received the client's public key in encoded format.  The
          * server instantiates a DH public key from the encoded key material.
@@ -80,7 +80,7 @@ class DhServer {
         serverKeyAgree.doPhase(clientPubKey, true);
 
         // The server encodes its public key, and sends it over to the client.
-        return serverKpair.getPublic().getEncoded();
+        return serverKpair.getPublic();
     }
 
 

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitContext.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitContext.java
index 3e4f136..685ecfa 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitContext.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitContext.java
@@ -19,11 +19,12 @@
 package org.apache.kerby.kerberos.kerb.client.preauth.pkinit;
 
 import org.apache.kerby.kerberos.kerb.preauth.pkinit.IdentityOpts;
+import org.apache.kerby.kerberos.kerb.preauth.pkinit.PkinitPlgCryptoContext;
 import org.apache.kerby.kerberos.kerb.preauth.pkinit.PluginOpts;
 
 public class PkinitContext {
 
+    public PkinitPlgCryptoContext cryptoctx = new PkinitPlgCryptoContext();
     public PluginOpts pluginOpts = new PluginOpts();
     public IdentityOpts identityOpts = new IdentityOpts();
-
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitCrypto.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitCrypto.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitCrypto.java
deleted file mode 100644
index 34e3558..0000000
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitCrypto.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
- * 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
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * 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.kerby.kerberos.kerb.client.preauth.pkinit;
-
-import org.apache.kerby.kerberos.kerb.KrbException;
-
-import javax.crypto.spec.DHParameterSpec;
-import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-
-public class PkinitCrypto {
-
-    /*
-     * http://www.ietf.org/rfc/rfc2409.txt
-     * This group is assigned id 2.
-     * The prime is 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
-     */
-    public static BigInteger getPkinit1024Prime() {
-        StringBuffer sb = new StringBuffer();
-        sb.append("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1");
-        sb.append("29024E088A67CC74020BBEA63B139B22514A08798E3404DD");
-        sb.append("EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245");
-        sb.append("E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED");
-        sb.append("EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381");
-        sb.append("FFFFFFFFFFFFFFFF");
-
-        return new BigInteger(sb.toString(), 16);
-    }
-
-    /*
-     * http://www.ietf.org/rfc/rfc3526.txt
-     * 2048-bit MODP Group
-     * This group is assigned id 14.
-     * This prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
-     */
-    public static BigInteger getPkinit2048Prime() {
-        StringBuffer sb = new StringBuffer();
-        sb.append("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1");
-        sb.append("29024E088A67CC74020BBEA63B139B22514A08798E3404DD");
-        sb.append("EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245");
-        sb.append("E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED");
-        sb.append("EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D");
-        sb.append("C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F");
-        sb.append("83655D23DCA3AD961C62F356208552BB9ED529077096966D");
-        sb.append("670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B");
-        sb.append("E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9");
-        sb.append("DE2BCBF6955817183995497CEA956AE515D2261898FA0510");
-        sb.append("15728E5A8AACAA68FFFFFFFFFFFFFFFF");
-
-        return new BigInteger(sb.toString(), 16);
-    }
-
-    /*
-     * http://www.ietf.org/rfc/rfc3526.txt
-     * 4096-bit MODP Group
-     * This group is assigned id 16.
-     * This prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }
-     */
-    public static BigInteger getPkinit4096Prime() {
-        StringBuffer sb = new StringBuffer();
-        sb.append("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1");
-        sb.append("29024E088A67CC74020BBEA63B139B22514A08798E3404DD");
-        sb.append("EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245");
-        sb.append("E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED");
-        sb.append("EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D");
-        sb.append("C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F");
-        sb.append("83655D23DCA3AD961C62F356208552BB9ED529077096966D");
-        sb.append("670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B");
-        sb.append("E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9");
-        sb.append("DE2BCBF6955817183995497CEA956AE515D2261898FA0510");
-        sb.append("15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64");
-        sb.append("ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7");
-        sb.append("ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B");
-        sb.append("F12FFA06D98A0864D87602733EC86A64521F2B18177B200C");
-        sb.append("BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31");
-        sb.append("43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7");
-        sb.append("88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA");
-        sb.append("2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6");
-        sb.append("287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED");
-        sb.append("1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9");
-        sb.append("93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199");
-        sb.append("FFFFFFFFFFFFFFFF");
-
-        return new BigInteger(sb.toString(), 16);
-    }
-
-    public static DHParameterSpec createDHParameterSpec(int dhSize) throws KrbException {
-        BigInteger g = BigInteger.valueOf(2);
-        BigInteger p = null;
-
-        switch (dhSize) {
-            case 1024:
-                p = getPkinit1024Prime();
-                break;
-            case 2048:
-                p = getPkinit2048Prime();
-                break;
-            case 4096:
-                p = getPkinit4096Prime();
-                break;
-            default:
-                throw new KrbException("Unsupported dh size:" + dhSize);
-        }
-
-        return new DHParameterSpec(p, g);
-    }
-
-    public static KeyPair getKeyPair(DHParameterSpec dhParameterSpec) {
-        String algo = "DH";
-        KeyPairGenerator keyPairGenerator = null;
-        try {
-            keyPairGenerator = KeyPairGenerator.getInstance(algo);
-        } catch (NoSuchAlgorithmException e) {
-            e.printStackTrace();
-        }
-        if (keyPairGenerator != null) {
-            try {
-                keyPairGenerator.initialize(dhParameterSpec);
-            } catch (InvalidAlgorithmParameterException e) {
-                e.printStackTrace();
-            }
-        }
-        return keyPairGenerator.generateKeyPair();
-    }
-}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitPreauth.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitPreauth.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitPreauth.java
index 8f2cea0..fa362f4 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitPreauth.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitPreauth.java
@@ -20,32 +20,51 @@
 package org.apache.kerby.kerberos.kerb.client.preauth.pkinit;
 
 import org.apache.kerby.KOptions;
+import org.apache.kerby.asn1.type.Asn1Integer;
+import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.client.KrbContext;
 import org.apache.kerby.kerberos.kerb.client.KrbOption;
 import org.apache.kerby.kerberos.kerb.client.preauth.AbstractPreauthPlugin;
 import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.common.CheckSumUtil;
 import org.apache.kerby.kerberos.kerb.preauth.PaFlag;
 import org.apache.kerby.kerberos.kerb.preauth.PaFlags;
 import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
+import org.apache.kerby.kerberos.kerb.preauth.pkinit.CertificateHelper;
 import org.apache.kerby.kerberos.kerb.preauth.pkinit.PkinitIdenity;
 import org.apache.kerby.kerberos.kerb.preauth.pkinit.PkinitPreauthMeta;
 import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.base.CheckSum;
+import org.apache.kerby.kerberos.kerb.spec.base.CheckSumType;
 import org.apache.kerby.kerberos.kerb.spec.base.EncryptionKey;
 import org.apache.kerby.kerberos.kerb.spec.base.EncryptionType;
-import org.apache.kerby.kerberos.kerb.spec.base.PrincipalName;
+import org.apache.kerby.kerberos.kerb.spec.cms.AlgorithmIdentifier;
+import org.apache.kerby.kerberos.kerb.spec.cms.DHParameter;
+import org.apache.kerby.kerberos.kerb.spec.cms.SubjectPublicKeyInfo;
 import org.apache.kerby.kerberos.kerb.spec.pa.PaData;
 import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
 import org.apache.kerby.kerberos.kerb.spec.pa.PaDataType;
 import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.AuthPack;
-import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.DHNonce;
 import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.PaPkAsReq;
 import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.PkAuthenticator;
 import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.TrustedCertifiers;
-import org.apache.kerby.kerberos.kerb.spec.cms.SubjectPublicKeyInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.List;
 
-@SuppressWarnings("PMD")
 public class PkinitPreauth extends AbstractPreauthPlugin {
+    private static final Logger LOG = LoggerFactory.getLogger(PkinitPreauth.class);
 
     private PkinitContext pkinitContext;
 
@@ -87,8 +106,15 @@ public class PkinitPreauth extends AbstractPreauthPlugin {
         }
 
         if (options.contains(KrbOption.PKINIT_X509_ANCHORS)) {
-            pkinitContext.identityOpts.anchors.add(
-                    options.getStringOption(KrbOption.PKINIT_X509_ANCHORS));
+            String anchorsString = options.getStringOption(KrbOption.PKINIT_X509_ANCHORS);
+
+            List<String> anchors;
+            if (anchorsString == null) {
+                anchors = kdcRequest.getContext().getConfig().getPkinitAnchors();
+            } else {
+                anchors = Arrays.asList(anchorsString);
+            }
+            pkinitContext.identityOpts.anchors.addAll(anchors);
         }
 
         if (options.contains(KrbOption.PKINIT_USING_RSA)) {
@@ -123,6 +149,11 @@ public class PkinitPreauth extends AbstractPreauthPlugin {
                          PluginRequestContext requestContext,
                          PaData outPadata) throws KrbException {
 
+        long now = System.currentTimeMillis();
+        PaPkAsReq paPkAsReq = makePaPkAsReq(kdcRequest,
+                (PkinitRequestContext) requestContext,
+                1, new KerberosTime(now), 1, null);
+        outPadata.addElement(makeEntry(paPkAsReq));
     }
 
     /**
@@ -163,51 +194,127 @@ public class PkinitPreauth extends AbstractPreauthPlugin {
 
     }
 
-    private PaPkAsReq makePaPkAsReq(PkinitContext pkinitContext, PkinitRequestContext reqCtx,
-                                    KerberosTime ctime, int cusec, int nonce, byte[] checksum,
-                                    PrincipalName client, PrincipalName server) {
+    private PaPkAsReq makePaPkAsReq(KdcRequest kdcRequest,
+                                    PkinitRequestContext reqCtx,
+                                    int cusec, KerberosTime ctime, int nonce, byte[] checksum) {
 
         PaPkAsReq paPkAsReq = new PaPkAsReq();
         AuthPack authPack = new AuthPack();
-        SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo();
         PkAuthenticator pkAuthen = new PkAuthenticator();
 
         boolean usingRsa = reqCtx.requestOpts.usingRsa;
         reqCtx.paType = PaDataType.PK_AS_REQ;
 
-        pkAuthen.setCtime(ctime);
         pkAuthen.setCusec(cusec);
+        pkAuthen.setCtime(ctime);
         pkAuthen.setNonce(nonce);
-        pkAuthen.setPaChecksum(checksum);
+
+        CheckSum checkSum = null;
+        try {
+            checkSum = CheckSumUtil.makeCheckSum(CheckSumType.NIST_SHA,
+                    kdcRequest.getKdcReq().getReqBody().encode());
+        } catch (KrbException e) {
+            e.printStackTrace();
+        }
+//        pkAuthen.setPaChecksum(checkSum.getChecksum());
+        pkAuthen.setPaChecksum(checkSum.encode());
 
         authPack.setPkAuthenticator(pkAuthen);
-        DHNonce dhNonce = new DHNonce();
-        authPack.setClientDhNonce(dhNonce);
-        authPack.setClientPublicValue(pubInfo);
 
-        authPack.setsupportedCmsTypes(pkinitContext.pluginOpts.createSupportedCMSTypes());
+//        authPack.setsupportedCmsTypes(pkinitContext.pluginOpts.createSupportedCMSTypes());
 
-        if (usingRsa) {
+        if (!usingRsa) {
             System.out.println(); // DH case
+
+            AlgorithmIdentifier dhAlg = new AlgorithmIdentifier();
+
+//            byte[] dh_oid = new byte[]{0, 7, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0xce,
+//                    (byte) 0x3e, (byte) 0x02, (byte) 0x01};
+//            String dhOidStr = Utf8.toString(dh_oid);
+//            String dhOidStr = "0.7.42.840.10046.2.1";
+
+            String content = "0x06 07 2A 86 48 ce 3e 02 01";
+            Asn1ObjectIdentifier decoded = new Asn1ObjectIdentifier();
+            decoded.getEncodingOption().useDer();
+            try {
+                decoded.decode(Util.hex2bytes(content));
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+
+            dhAlg.setAlgorithm(decoded);
+
+            DhClient client = new DhClient();
+
+            DHPublicKey clientPubKey = null;
+            try {
+                clientPubKey = client.init(DhGroup.MODP_GROUP14);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+            DHParameterSpec spec = clientPubKey.getParams();
+            BigInteger q = spec.getP().shiftRight(1);
+            DHParameter dhParameter = new DHParameter();
+            dhParameter.setP(spec.getP());
+            dhParameter.setG(spec.getG());
+            dhParameter.setQ(q);
+            dhAlg.setParameters(dhParameter);
+
+            SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo();
+            pubInfo.setAlgorithm(dhAlg);
+
+            Asn1Integer publickey = new Asn1Integer(clientPubKey.getY());
+            pubInfo.setSubjectPubKey(publickey.encode());
+
+            authPack.setClientPublicValue(pubInfo);
+
+//            DHNonce dhNonce = new DHNonce();
+//            authPack.setClientDhNonce(dhNonce);
+
         } else {
             authPack.setClientPublicValue(null);
         }
 
-        byte[] signedAuthPack = signAuthPack(pkinitContext, reqCtx, authPack);
+        byte[] signedAuthPack = signAuthPack(kdcRequest, reqCtx, authPack);
+
         paPkAsReq.setSignedAuthPack(signedAuthPack);
 
         TrustedCertifiers trustedCertifiers = pkinitContext.pluginOpts.createTrustedCertifiers();
         paPkAsReq.setTrustedCertifiers(trustedCertifiers);
 
-        byte[] kdcPkId = pkinitContext.pluginOpts.createIssuerAndSerial();
-        paPkAsReq.setKdcPkId(kdcPkId);
+//        byte[] kdcPkId = pkinitContext.pluginOpts.createIssuerAndSerial();
+//        paPkAsReq.setKdcPkId(kdcPkId);
 
         return paPkAsReq;
     }
 
-    private byte[] signAuthPack(PkinitContext pkinitContext,
+    private byte[] signAuthPack(KdcRequest kdcRequest,
                                 PkinitRequestContext reqCtx, AuthPack authPack) {
-        return null;
+
+        List<String> anchors = pkinitContext.identityOpts.anchors;
+
+        InputStream res = null;
+        try {
+            res = new FileInputStream(anchors.get(0));
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        X509Certificate certificate = null;
+        try {
+            certificate = (X509Certificate) CertificateHelper.loadCerts(res).iterator().next();
+        } catch (KrbException e) {
+            e.printStackTrace();
+        }
+
+        byte[] signedDataBytes = new byte[0];
+        try {
+            signedDataBytes = SignedDataEngine.cmsSignedDataCreate(authPack, certificate).toByteArray();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return signedDataBytes;
     }
 
     private void processReply(KdcRequest kdcRequest,
@@ -263,4 +370,17 @@ public class PkinitPreauth extends AbstractPreauthPlugin {
         return paFlags;
     }
 
+    /**
+     * Make padata entry.
+     *
+     * @param paPkAsReq The PaPkAsReq
+     * @return PaDataEntry to be made.
+     */
+    private PaDataEntry makeEntry(PaPkAsReq paPkAsReq) throws KrbException {
+
+        PaDataEntry paDataEntry = new PaDataEntry();
+        paDataEntry.setPaDataType(PaDataType.PK_AS_REQ);
+        paDataEntry.setPaDataValue(paPkAsReq.encode());
+        return paDataEntry;
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitRequestOpts.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitRequestOpts.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitRequestOpts.java
index 97e989f..9796f78 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitRequestOpts.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitRequestOpts.java
@@ -30,7 +30,7 @@ public class PkinitRequestOpts {
     // allow UPN-SAN instead of pkinit-SAN
     public boolean allowUpn = true;
     // selects DH or RSA based pkinit
-    public boolean usingRsa = true;
+    public boolean usingRsa = false;
     // require CRL for a CA (default is false)
     public boolean requireCrlChecking = false;
     // initial request DH modulus size (default=1024)

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/SignedDataEngine.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/SignedDataEngine.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/SignedDataEngine.java
index c245579..4d2aef8 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/SignedDataEngine.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/SignedDataEngine.java
@@ -32,20 +32,22 @@ import org.bouncycastle.cms.CMSSignedDataGenerator;
 import org.bouncycastle.cms.CMSTypedData;
 import org.bouncycastle.cms.SignerInformation;
 import org.bouncycastle.cms.SignerInformationStore;
-import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
 import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
-import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.operator.OperatorCreationException;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
-import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
 import org.bouncycastle.util.Store;
-
+import sun.security.pkcs.ContentInfo;
+import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.SignerInfo;
+import sun.security.util.DerValue;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.AlgorithmId;
+
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
 import java.security.PrivateKey;
-import java.security.cert.CertStoreException;
+import java.security.Security;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
@@ -80,16 +82,14 @@ public class SignedDataEngine {
      * @param certificate
      * @param authPack
      * @return The CMS SignedData bytes.
-     * @throws NoSuchAlgorithmException
-     * @throws NoSuchProviderException
-     * @throws InvalidAlgorithmParameterException
-     * @throws CertStoreException
+     * @throws OperatorCreationException
+     * @throws CertificateEncodingException
      * @throws CMSException
      * @throws IOException
      */
-    public static byte[] getSignedAuthPack(PrivateKey privateKey, X509Certificate certificate, AuthPack authPack)
-            throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException,
-            CertStoreException, CMSException, IOException, OperatorCreationException, CertificateEncodingException {
+    public static byte[] getSignedAuthPack(PrivateKey privateKey, X509Certificate certificate,
+                                           AuthPack authPack)
+            throws OperatorCreationException, CertificateEncodingException, CMSException, IOException {
         return getSignedData(privateKey, certificate, authPack.encode(), ID_PKINIT_AUTHDATA);
     }
 
@@ -109,18 +109,14 @@ public class SignedDataEngine {
      * @param certificate
      * @param kdcDhKeyInfo
      * @return The CMS SignedData bytes.
-     * @throws NoSuchAlgorithmException
-     * @throws NoSuchProviderException
-     * @throws InvalidAlgorithmParameterException
-     * @throws CertStoreException
+     * @throws OperatorCreationException
+     * @throws CertificateEncodingException
      * @throws CMSException
      * @throws IOException
      */
     public static byte[] getSignedKdcDhKeyInfo(PrivateKey privateKey, X509Certificate certificate,
                                                KdcDHKeyInfo kdcDhKeyInfo)
-            throws NoSuchAlgorithmException, NoSuchProviderException,
-            InvalidAlgorithmParameterException, CertStoreException, CMSException, IOException,
-            OperatorCreationException, CertificateEncodingException {
+            throws OperatorCreationException, CertificateEncodingException, CMSException, IOException {
         return getSignedData(privateKey, certificate, kdcDhKeyInfo.encode(), ID_PKINIT_DHKEYDATA);
     }
 
@@ -139,37 +135,38 @@ public class SignedDataEngine {
      * @param certificate
      * @param replyKeyPack
      * @return The CMS SignedData bytes.
-     * @throws NoSuchAlgorithmException
-     * @throws NoSuchProviderException
-     * @throws InvalidAlgorithmParameterException
-     * @throws CertStoreException
+     * @throws OperatorCreationException
+     * @throws CertificateEncodingException
      * @throws CMSException
      * @throws IOException
      */
     public static byte[] getSignedReplyKeyPack(PrivateKey privateKey, X509Certificate certificate,
                                                ReplyKeyPack replyKeyPack)
-            throws NoSuchAlgorithmException, NoSuchProviderException,
-            InvalidAlgorithmParameterException, CertStoreException, CMSException, IOException,
-            OperatorCreationException, CertificateEncodingException {
+            throws OperatorCreationException, CertificateEncodingException, CMSException, IOException {
         return getSignedData(privateKey, certificate, replyKeyPack.encode(), ID_PKINIT_RKEYDATA);
     }
 
 
     static byte[] getSignedData(PrivateKey privateKey, X509Certificate certificate, byte[] dataToSign,
-                                String eContentType) throws NoSuchAlgorithmException, NoSuchProviderException,
-            InvalidAlgorithmParameterException, CertStoreException, CMSException, IOException,
-            CertificateEncodingException, OperatorCreationException {
+                                String eContentType) throws IOException, OperatorCreationException,
+            CertificateEncodingException, CMSException {
+
+        if (Security.getProvider("BC") == null) {
+            Security.addProvider(new BouncyCastleProvider());
+        }
+
 
         List certList = new ArrayList();
         certList.add(certificate);
         Store certs = new JcaCertStore(certList);
 
         CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-        ContentSigner contentSigner = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC")
-                .build(privateKey);
-        gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(
-                new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
-                .build(contentSigner, certificate));
+
+        gen.addSignerInfoGenerator(
+                new JcaSimpleSignerInfoGeneratorBuilder()
+                        .setProvider("BC")
+                        .build("SHA1withRSA", privateKey, certificate));
+
         gen.addCertificates(certs);
 
         ASN1ObjectIdentifier asn1ObjectIdentifier = new ASN1ObjectIdentifier(eContentType);
@@ -217,4 +214,26 @@ public class SignedDataEngine {
         }
         return true;
     }
+
+    public static ContentInfo createContentInfo(byte[] data, ObjectIdentifier oid) {
+
+        ContentInfo contentInfo = new ContentInfo(
+                oid,
+                new DerValue(DerValue.tag_OctetString, data));
+        return contentInfo;
+    }
+
+    public static ByteArrayOutputStream cmsSignedDataCreate(AuthPack authPack,
+                                                            X509Certificate certificate) throws IOException {
+
+        ObjectIdentifier oid = new ObjectIdentifier(ID_PKINIT_AUTHDATA);
+        ContentInfo contentInfo = createContentInfo(authPack.encode(), oid);
+
+        X509Certificate[] certificates = {certificate};
+        PKCS7 p7 = new PKCS7(new AlgorithmId[0], contentInfo, certificates, new SignerInfo[0]);
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+        p7.encodeSignedData(bytes);
+        return bytes;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/Util.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/Util.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/Util.java
new file mode 100644
index 0000000..672264a
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/Util.java
@@ -0,0 +1,153 @@
+/**
+ *  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.kerby.kerberos.kerb.client.preauth.pkinit;
+
+public class Util {
+
+    static final String HEX_CHARS_STR = "0123456789ABCDEF";
+    static final char[] HEX_CHARS = HEX_CHARS_STR.toCharArray();
+
+    /**
+     * Convert bytes into format as:
+     * 0x02 02 00 80
+     */
+    public static String bytesToHex(byte[] bytes) {
+        int len = bytes.length * 2;
+        len += bytes.length; // for ' ' appended for each char
+        len += 2; // for '0x' prefix
+        char[] hexChars = new char[len];
+        hexChars[0] = '0';
+        hexChars[1] = 'x';
+        for (int j = 0; j < bytes.length; j++) {
+            int v = bytes[j] & 0xFF;
+            hexChars[j * 3 + 2] = HEX_CHARS[v >>> 4];
+            hexChars[j * 3 + 3] = HEX_CHARS[v & 0x0F];
+            hexChars[j * 3 + 4] = ' ';
+        }
+
+        return new String(hexChars);
+    }
+
+    /**
+     * Convert hex string like follows into byte array
+     * 0x02 02 00 80
+     */
+    public static byte[] hex2bytes(String hexString) {
+        if (hexString == null) {
+            throw new IllegalArgumentException("Invalid hex string to convert : null");
+        }
+        
+        char[] hexStr = hexString.toCharArray();
+
+        if (hexStr.length < 4) {
+            throw new IllegalArgumentException("Invalid hex string to convert : length below 4");
+        }
+        
+        if (hexStr[0] != '0' || (hexStr[1] != 'x') && (hexStr[1] != 'X')) {
+            throw new IllegalArgumentException("Invalid hex string to convert : not starting with '0x'");
+        }
+        
+        byte[] bytes = new byte[(hexStr.length - 1) / 3];
+        int pos = 0; 
+        boolean high = false;
+        boolean prefix = true;
+        
+        for (char c : hexStr) {
+            if (prefix) {
+                if (c == 'x' || c == 'X') {
+                    prefix = false;
+                }
+                
+                continue;
+            }
+            
+            switch (c) {
+                case ' ' :
+                    if (high) {
+                        // We have had only the high part
+                        throw new IllegalArgumentException("Invalid hex string to convert");
+                    }
+                    
+                    // A hex pair has been decoded
+                    pos++;
+                    high = false;
+                    break;
+                    
+                case '0': 
+                case '1': 
+                case '2': 
+                case '3': 
+                case '4':
+                case '5': 
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+                    if (high) {
+                        bytes[pos] += (byte) (c - '0');
+                    } else {
+                        bytes[pos] = (byte) ((c - '0') << 4);
+                    }
+                    
+                    high = !high;
+                    break;
+                    
+                case 'a' :
+                case 'b' :
+                case 'c' :
+                case 'd' :
+                case 'e' :
+                case 'f' :
+                    if (high) {
+                        bytes[pos] += (byte) (c - 'a' + 10);
+                    } else {
+                        bytes[pos] = (byte) ((c - 'a' + 10) << 4);
+                    }
+
+                    high = !high;
+                    break;
+
+                case 'A' :
+                case 'B' :
+                case 'C' :
+                case 'D' :
+                case 'E' :
+                case 'F' :
+                    if (high) {
+                        bytes[pos] += (byte) (c - 'A' + 10);
+                    } else {
+                        bytes[pos] = (byte) ((c - 'A' + 10) << 4);
+                    }
+
+                    high = !high;
+                    break;
+                    
+                default :
+                    throw new IllegalArgumentException("Invalid hex string to convert");
+            }
+        }
+        
+        if (high) {
+            throw new IllegalArgumentException("Invalid hex string to convert");
+        }
+
+        return bytes;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequest.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequest.java
index 75216a8..f6ff7f8 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequest.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequest.java
@@ -89,8 +89,11 @@ public class AsRequest extends KdcRequest {
         PrincipalName clientPrincipal = getKdcRep().getCname();
         String clientRealm = getKdcRep().getCrealm();
         clientPrincipal.setRealm(clientRealm);
-        if (!getKrbOptions().contains(KrbOption.TOKEN_USER_ID_TOKEN)
-            && !clientPrincipal.equals(getClientPrincipal())) {
+
+        if (!(getKrbOptions().contains(KrbOption.USE_PKINIT_ANONYMOUS)
+                && KrbUtil.pricipalCompareIgnoreRealm(clientPrincipal, getClientPrincipal()))
+                && !getKrbOptions().contains(KrbOption.TOKEN_USER_ID_TOKEN)
+                && !clientPrincipal.equals(getClientPrincipal())) {
             throw new KrbException(KrbErrorCode.KDC_ERR_CLIENT_NAME_MISMATCH);
         }
 
@@ -147,4 +150,5 @@ public class AsRequest extends KdcRequest {
 
         return cc;
     }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequestWithCert.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequestWithCert.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequestWithCert.java
index ef2808f..4b7525b 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequestWithCert.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequestWithCert.java
@@ -19,11 +19,19 @@
  */
 package org.apache.kerby.kerberos.kerb.client.request;
 
-import org.apache.kerby.kerberos.kerb.client.KrbContext;
-import org.apache.kerby.kerberos.kerb.client.KrbOption;
 import org.apache.kerby.KOptions;
+import org.apache.kerby.kerberos.kerb.KrbCodec;
 import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbContext;
+import org.apache.kerby.kerberos.kerb.client.KrbOption;
+import org.apache.kerby.kerberos.kerb.spec.kdc.AsReq;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcOption;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcRep;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcReqBody;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaData;
+import org.apache.kerby.kerberos.kerb.spec.pa.PaDataEntry;
 import org.apache.kerby.kerberos.kerb.spec.pa.PaDataType;
+import org.apache.kerby.kerberos.kerb.spec.pa.pkinit.PaPkAsRep;
 
 public class AsRequestWithCert extends AsRequest {
 
@@ -33,11 +41,20 @@ public class AsRequestWithCert extends AsRequest {
         super(context);
 
         setAllowedPreauth(PaDataType.PK_AS_REQ);
+        getKdcOptions().setFlag(KdcOption.REQUEST_ANONYMOUS);
     }
 
     @Override
     public void process() throws KrbException {
-        throw new RuntimeException("To be implemented");
+        KdcReqBody body = makeReqBody();
+        AsReq asReq = new AsReq();
+        asReq.setReqBody(body);
+        setKdcReq(asReq);
+
+        preauth();
+
+        asReq.setPaData(getPreauthContext().getOutputPaData());
+        setKdcReq(asReq);
     }
 
     @Override
@@ -54,4 +71,30 @@ public class AsRequestWithCert extends AsRequest {
         return results;
     }
 
+    @Override
+    public void processResponse(KdcRep kdcRep) throws KrbException  {
+
+        PaData paData = kdcRep.getPaData();
+        for (PaDataEntry paEntry : paData.getElements()) {
+            if (paEntry.getPaDataType() == PaDataType.PK_AS_REP) {
+
+                PaPkAsRep paPkAsRep = KrbCodec.decode(paEntry.getPaDataValue(), PaPkAsRep.class);
+
+                byte[] a = paPkAsRep.getEncKeyPack();
+//                DHRepInfo dhRepInfo =paPkAsRep.getDHRepInfo();
+//                DHNonce nonce = dhRepInfo.getServerDhNonce();
+//                byte[] dhSignedData = dhRepInfo.getDHSignedData();
+//                PKCS7 pkcs7 = null;
+//                try {
+//                   pkcs7 = new PKCS7(dhSignedData);
+//                } catch (ParsingException e) {
+//                    e.printStackTrace();
+//                }
+//                pkcs7.getContentInfo();
+
+            }
+        }
+
+        super.processResponse(kdcRep);
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhKeyAgreementTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhKeyAgreementTest.java b/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhKeyAgreementTest.java
index c3055cf..54b2b5b 100644
--- a/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhKeyAgreementTest.java
+++ b/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/DhKeyAgreementTest.java
@@ -22,7 +22,14 @@ package org.apache.kerby.kerberos.kerb.client.preauth.pkinit;
 
 import junit.framework.TestCase;
 
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.DHPublicKeySpec;
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
 import java.util.Arrays;
 
 
@@ -42,7 +49,6 @@ import java.util.Arrays;
 public class DhKeyAgreementTest extends TestCase {
     private static SecureRandom secureRandom = new SecureRandom();
 
-
     /**
      * Tests Diffie-Hellman using Oakley 1024-bit Modular Exponential (MODP)
      * well-known group 2 [RFC2412].
@@ -53,8 +59,8 @@ public class DhKeyAgreementTest extends TestCase {
         DhClient client = new DhClient();
         DhServer server = new DhServer();
 
-        byte[] clientPubKeyEnc = client.init(DhGroup.MODP_GROUP2);
-        byte[] serverPubKeyEnc = server.initAndDoPhase(clientPubKeyEnc);
+        byte[] clientPubKeyEnc = client.init(DhGroup.MODP_GROUP2).getEncoded();
+        byte[] serverPubKeyEnc = server.initAndDoPhase(clientPubKeyEnc).getEncoded();
 
         server.generateKey(null, null);
 
@@ -90,8 +96,8 @@ public class DhKeyAgreementTest extends TestCase {
         DhClient client = new DhClient();
         DhServer server = new DhServer();
 
-        byte[] clientPubKeyEnc = client.init(DhGroup.MODP_GROUP2);
-        byte[] serverPubKeyEnc = server.initAndDoPhase(clientPubKeyEnc);
+        byte[] clientPubKeyEnc = client.init(DhGroup.MODP_GROUP2).getEncoded();
+        byte[] serverPubKeyEnc = server.initAndDoPhase(clientPubKeyEnc).getEncoded();
 
         server.generateKey(clientDhNonce, serverDhNonce);
 
@@ -106,4 +112,56 @@ public class DhKeyAgreementTest extends TestCase {
 
         assertTrue(Arrays.equals(clearText, recovered));
     }
+
+
+    /**
+     * Tests Diffie-Hellman using Oakley 1024-bit Modular Exponential (MODP)
+     * well-known group 2 [RFC2412].
+     *
+     * @throws Exception
+     */
+    public void testGeneratedDhParams() throws Exception {
+        DhClient client = new DhClient();
+        DhServer server = new DhServer();
+
+        DHPublicKey clientPubKey = client.init(DhGroup.MODP_GROUP14);
+        DHParameterSpec spec = clientPubKey.getParams();
+
+        BigInteger y = clientPubKey.getY();
+        BigInteger p = spec.getP();
+        BigInteger g = spec.getG();
+        DHPublicKeySpec dhPublicKeySpec = new DHPublicKeySpec(y, p, g);
+
+        KeyFactory keyFactory = null;
+        try {
+            keyFactory = KeyFactory.getInstance("DH");
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        }
+        DHPublicKey dhPublicKey = null;
+        try {
+            dhPublicKey = (DHPublicKey) keyFactory.generatePublic(dhPublicKeySpec);
+        } catch (InvalidKeySpecException e) {
+            e.printStackTrace();
+        }
+
+        byte[] serverPubKeyEnc = null;
+        try {
+            serverPubKeyEnc = server.initAndDoPhase(dhPublicKey.getEncoded()).getEncoded();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        server.generateKey(null, null);
+
+        client.doPhase(serverPubKeyEnc);
+
+        client.generateKey(null, null);
+
+        byte[] clearText = "This is just an example".getBytes();
+
+        byte[] cipherText = server.encryptAes(clearText);
+        byte[] recovered = client.decryptAes(cipherText);
+
+        assertTrue(Arrays.equals(clearText, recovered));
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/KrbUtil.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/KrbUtil.java b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/KrbUtil.java
index 0610807..e6dd9db 100644
--- a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/KrbUtil.java
+++ b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/KrbUtil.java
@@ -1,30 +1,36 @@
 /**
- *  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.
- *
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.kerby.kerberos.kerb.common;
 
 import org.apache.kerby.kerberos.kerb.KrbConstant;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.spec.base.NameType;
 import org.apache.kerby.kerberos.kerb.spec.base.PrincipalName;
 
 public class KrbUtil {
 
+    public static final String ANONYMOUS_PRINCIPAL = "ANONYMOUS@WELLKNOWN:ANONYMOUS";
+    /** First component of NT_WELLKNOWN principals */
+    public static final String KRB5_WELLKNOWN_NAMESTR = "WELLKNOWN";
+    public static final String KRB5_ANONYMOUS_PRINCSTR = "ANONYMOUS";
+    public static final String KRB5_ANONYMOUS_REALMSTR = "WELLKNOWN:ANONYMOUS";
+
     /**
      * Construct TGS principal name.
      * @param realm The realm
@@ -45,4 +51,27 @@ public class KrbUtil {
         return new PrincipalName(nameString, NameType.NT_PRINCIPAL);
     }
 
+    public static boolean pricipalCompareIgnoreRealm(PrincipalName princ1, PrincipalName princ2)
+            throws KrbException {
+
+        if (princ1 != null && princ2 != null) {
+            princ1.setRealm(null);
+            princ2.setRealm(null);
+            if (princ1.getName().equals(princ2.getName())) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            throw new KrbException("principal can't be null.");
+        }
+    }
+
+    public static PrincipalName makeAnonymousPrincipal() {
+        PrincipalName principalName = new PrincipalName(KRB5_WELLKNOWN_NAMESTR + "/" + KRB5_ANONYMOUS_PRINCSTR);
+        principalName.setRealm(KRB5_ANONYMOUS_REALMSTR);
+        principalName.setNameType(NameType.NT_PRINCIPAL);
+        return principalName;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/CMSMessageType.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/CMSMessageType.java b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/CMSMessageType.java
new file mode 100644
index 0000000..683b52f
--- /dev/null
+++ b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/CMSMessageType.java
@@ -0,0 +1,59 @@
+/**
+ *  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.kerby.kerberos.kerb.preauth.pkinit;
+
+public enum CMSMessageType {
+    UNKNOWN                  (-1),
+    CMS_SIGN_CLIENT          (0x01),
+    CMS_SIGN_SERVER          (0x03),
+    CMS_ENVEL_SERVER         (0x04);
+
+
+    /** The type value */
+    private int value;
+
+    /**
+     * Create an instance of this class
+     */
+    private CMSMessageType(int value) {
+        this.value = value;
+    }
+
+    /**
+     * @return The associated type value
+     */
+    public int getValue() {
+        return value;
+    }
+
+    /**
+     * Retrieve the UniversalTag associated with a given value
+     * @param value The integer value
+     * @return The associated UniversalTag
+     */
+    public static CMSMessageType fromValue(int value) {
+        switch (value) {
+            case 0x01 : return CMS_SIGN_CLIENT;
+            case 0x03 : return CMS_SIGN_SERVER;
+            case 0x04 : return CMS_ENVEL_SERVER;
+            default : return UNKNOWN;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/CertificateHelper.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/CertificateHelper.java b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/CertificateHelper.java
new file mode 100644
index 0000000..9731907
--- /dev/null
+++ b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/CertificateHelper.java
@@ -0,0 +1,45 @@
+/**
+ *  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.kerby.kerberos.kerb.preauth.pkinit;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+
+import java.io.InputStream;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class CertificateHelper {
+
+    public static List<Certificate> loadCerts(InputStream inputStream) throws KrbException {
+        CertificateFactory certFactory = null;
+        try {
+            certFactory = CertificateFactory.getInstance("X.509");
+            Collection<? extends Certificate> certs = (Collection<? extends Certificate>)
+                    certFactory.generateCertificates(inputStream);
+            return new ArrayList<Certificate>(certs);
+        } catch (CertificateException e) {
+            throw new KrbException("Failed to load certificates", e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitCrypto.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitCrypto.java b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitCrypto.java
new file mode 100644
index 0000000..c74a4de
--- /dev/null
+++ b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitCrypto.java
@@ -0,0 +1,170 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.kerby.kerberos.kerb.preauth.pkinit;
+
+import org.apache.kerby.kerberos.kerb.KrbErrorCode;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.cms.DHParameter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.ParsingException;
+import sun.security.util.ObjectIdentifier;
+
+import javax.crypto.spec.DHParameterSpec;
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+
+public class PkinitCrypto {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PkinitCrypto.class);
+
+    public static KeyPair getKeyPair(DHParameterSpec dhParameterSpec) {
+        String algo = "DH";
+        KeyPairGenerator keyPairGenerator = null;
+        try {
+            keyPairGenerator = KeyPairGenerator.getInstance(algo);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        }
+        if (keyPairGenerator != null) {
+            try {
+                keyPairGenerator.initialize(dhParameterSpec);
+            } catch (InvalidAlgorithmParameterException e) {
+                e.printStackTrace();
+            }
+        }
+        return keyPairGenerator.generateKeyPair();
+    }
+
+    public static PKCS7 verifyCMSSignedData(PkinitPlgCryptoContext cryptoctx, CMSMessageType cmsMsgType,
+                                            byte[] signedData)
+            throws IOException, KrbException {
+
+        ObjectIdentifier oid = pkinitPKCS7Type2OID(cryptoctx, cmsMsgType);
+        if (oid == null) {
+            throw new KrbException("Can't get the right oid ");
+        }
+
+        /* decode received CMS message */
+        PKCS7 pkcs7 = null;
+        try {
+            pkcs7 = new PKCS7(signedData);
+        } catch (ParsingException e) {
+            e.printStackTrace();
+        }
+        if (pkcs7 == null) {
+            LOG.error("failed to decode message");
+            throw new KrbException("failed to decode message");
+        }
+
+        ObjectIdentifier etype = pkcs7.getContentInfo().getContentType();
+
+        if (oid.equals(etype)) {
+            LOG.info("CMS Verification successful");
+        } else {
+            LOG.error("Wrong oid in eContentType");
+            throw new KrbException(KrbErrorCode.KDC_ERR_PREAUTH_FAILED, "Wrong oid in eContentType");
+        }
+
+        return pkcs7;
+    }
+
+    public static boolean isSigned(PKCS7 pkcs7) {
+        /* Not actually signed; anonymous case */
+        if (pkcs7.getSignerInfos().length == 0) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+
+    public static ObjectIdentifier pkinitPKCS7Type2OID(PkinitPlgCryptoContext cryptoctx,
+                                                       CMSMessageType cmsMsgType) throws IOException {
+        switch (cmsMsgType) {
+            case UNKNOWN:
+                return null;
+            case CMS_SIGN_CLIENT:
+                return cryptoctx.getIdPkinitAuthDataOID();
+            case CMS_SIGN_SERVER:
+                return cryptoctx.getIdPkinitDHKeyDataOID();
+            case CMS_ENVEL_SERVER:
+                return cryptoctx.getIdPkinitRkeyDataOID();
+            default:
+                return null;
+        }
+    }
+
+    public static void serverCheckDH(PluginOpts pluginOpts, PkinitPlgCryptoContext cryptoctx,
+                                     DHParameter dhParameter) throws KrbException {
+         /* KDC SHOULD check to see if the key parameters satisfy its policy */
+        int dhPrimeBits = dhParameter.getP().bitLength();
+        if (dhPrimeBits < pluginOpts.dhMinBits) {
+            String errMsg = "client sent dh params with " + dhPrimeBits
+                    + "bits, we require " + pluginOpts.dhMinBits;
+            LOG.error(errMsg);
+            throw new KrbException(KrbErrorCode.KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED, errMsg);
+        }
+        checkDHWellknown(cryptoctx, dhParameter, dhPrimeBits);
+    }
+
+    public static boolean checkDHWellknown(PkinitPlgCryptoContext cryptoctx,
+                                           DHParameter dhParameter, int dhPrimeBits) throws KrbException {
+        boolean valid = false;
+        switch (dhPrimeBits) {
+            case 1024:
+                /* Oakley MODP group 2 */
+            case 2048:
+                /* Oakley MODP group 14 */
+            case 4096:
+               /* Oakley MODP group 16 */
+                valid = pkinitCheckDhParams(cryptoctx.createDHParameterSpec(dhPrimeBits), dhParameter);
+                break;
+            default:
+                break;
+        }
+        return valid;
+    }
+
+    /**
+     * Check parameters against a well-known DH group
+     *
+     * @param dh1 The DHParameterSpec
+     * @param dh2 The DHParameter
+     */
+
+    public static boolean pkinitCheckDhParams(DHParameterSpec dh1, DHParameter dh2) {
+
+        if (!dh1.getP().equals(dh2.getP())) {
+            LOG.error("p is not well-known group dhparameter");
+            return false;
+        }
+        if (!dh1.getG().equals(dh2.getG())) {
+            LOG.error("bad g dhparameter");
+            return false;
+        }
+        LOG.info("Good dhparams", dh1.getP().bitLength());
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitPlgCryptoContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitPlgCryptoContext.java b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitPlgCryptoContext.java
new file mode 100644
index 0000000..f70d081
--- /dev/null
+++ b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitPlgCryptoContext.java
@@ -0,0 +1,141 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.kerby.kerberos.kerb.preauth.pkinit;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import sun.security.util.ObjectIdentifier;
+
+import javax.crypto.spec.DHParameterSpec;
+import java.io.IOException;
+import java.math.BigInteger;
+
+public class PkinitPlgCryptoContext {
+    private static final String ID_PKINIT_AUTHDATA = "1.3.6.1.5.2.3.1";
+    private static final String ID_PKINIT_DHKEYDATA = "1.3.6.1.5.2.3.2";
+    private static final String ID_PKINIT_RKEYDATA = "1.3.6.1.5.2.3.3";
+
+
+    /*
+     * http://www.ietf.org/rfc/rfc2409.txt
+     * This group is assigned id 2.
+     * The prime is 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
+     */
+    public BigInteger getPkinit1024Prime() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1");
+        sb.append("29024E088A67CC74020BBEA63B139B22514A08798E3404DD");
+        sb.append("EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245");
+        sb.append("E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED");
+        sb.append("EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381");
+        sb.append("FFFFFFFFFFFFFFFF");
+
+        return new BigInteger(sb.toString(), 16);
+    }
+
+    /*
+     * http://www.ietf.org/rfc/rfc3526.txt
+     * 2048-bit MODP Group
+     * This group is assigned id 14.
+     * This prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
+     */
+    public BigInteger getPkinit2048Prime() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1");
+        sb.append("29024E088A67CC74020BBEA63B139B22514A08798E3404DD");
+        sb.append("EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245");
+        sb.append("E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED");
+        sb.append("EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D");
+        sb.append("C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F");
+        sb.append("83655D23DCA3AD961C62F356208552BB9ED529077096966D");
+        sb.append("670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B");
+        sb.append("E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9");
+        sb.append("DE2BCBF6955817183995497CEA956AE515D2261898FA0510");
+        sb.append("15728E5A8AACAA68FFFFFFFFFFFFFFFF");
+
+        return new BigInteger(sb.toString(), 16);
+    }
+
+    /*
+     * http://www.ietf.org/rfc/rfc3526.txt
+     * 4096-bit MODP Group
+     * This group is assigned id 16.
+     * This prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }
+     */
+    public BigInteger getPkinit4096Prime() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1");
+        sb.append("29024E088A67CC74020BBEA63B139B22514A08798E3404DD");
+        sb.append("EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245");
+        sb.append("E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED");
+        sb.append("EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D");
+        sb.append("C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F");
+        sb.append("83655D23DCA3AD961C62F356208552BB9ED529077096966D");
+        sb.append("670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B");
+        sb.append("E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9");
+        sb.append("DE2BCBF6955817183995497CEA956AE515D2261898FA0510");
+        sb.append("15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64");
+        sb.append("ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7");
+        sb.append("ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B");
+        sb.append("F12FFA06D98A0864D87602733EC86A64521F2B18177B200C");
+        sb.append("BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31");
+        sb.append("43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7");
+        sb.append("88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA");
+        sb.append("2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6");
+        sb.append("287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED");
+        sb.append("1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9");
+        sb.append("93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199");
+        sb.append("FFFFFFFFFFFFFFFF");
+
+        return new BigInteger(sb.toString(), 16);
+    }
+
+    public DHParameterSpec createDHParameterSpec(int dhSize) throws KrbException {
+        BigInteger g = BigInteger.valueOf(2);
+        BigInteger p = null;
+
+        switch (dhSize) {
+            case 1024:
+                p = getPkinit1024Prime();
+                break;
+            case 2048:
+                p = getPkinit2048Prime();
+                break;
+            case 4096:
+                p = getPkinit4096Prime();
+                break;
+            default:
+                throw new KrbException("Unsupported dh size:" + dhSize);
+        }
+
+        return new DHParameterSpec(p, g);
+    }
+
+
+    public ObjectIdentifier getIdPkinitAuthDataOID() throws IOException {
+        return new ObjectIdentifier(ID_PKINIT_AUTHDATA);
+    }
+
+    public ObjectIdentifier getIdPkinitDHKeyDataOID() throws IOException {
+        return new ObjectIdentifier(ID_PKINIT_DHKEYDATA);
+    }
+
+    public ObjectIdentifier getIdPkinitRkeyDataOID() throws IOException {
+        return new ObjectIdentifier(ID_PKINIT_RKEYDATA);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PluginOpts.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PluginOpts.java b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PluginOpts.java
index 0cc34f2..ae303bf 100644
--- a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PluginOpts.java
+++ b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PluginOpts.java
@@ -35,7 +35,7 @@ public class PluginOpts {
     // allow UPN-SAN instead of pkinit-SAN
     public boolean allowUpn = true;
     // selects DH or RSA based pkinit
-    public boolean usingRsa = true;
+    public boolean usingRsa = false;
     // require CRL for a CA (default is false)
     public boolean requireCrlChecking = false;
     // the size of the Diffie-Hellman key the client will attempt to use.

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/14696718/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/base/KrbFlags.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/base/KrbFlags.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/base/KrbFlags.java
index b84992c..79d3323 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/base/KrbFlags.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/spec/base/KrbFlags.java
@@ -30,7 +30,6 @@ import java.io.IOException;
  -- but no fewer than 32
  */
 public class KrbFlags extends Asn1BitString {
-    private static final int MAX_SIZE = 32;
     private int flags;
 
     public KrbFlags() {
@@ -90,7 +89,8 @@ public class KrbFlags extends Asn1BitString {
     }
 
     private int flagPos(int flag)  {
-        return MAX_SIZE - 1 - flag;
+//        return MAX_SIZE - 1 - flag;
+        return Integer.numberOfTrailingZeros(flag);
     }
 
     private void flags2Value() {