You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by dr...@apache.org on 2015/01/22 01:56:53 UTC

[29/50] [abbrv] directory-kerberos git commit: Many changes with newname

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/test/java/org/apache/kerby/asn1/PersonnelRecord.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/PersonnelRecord.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/PersonnelRecord.java
new file mode 100644
index 0000000..39e08e6
--- /dev/null
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/PersonnelRecord.java
@@ -0,0 +1,208 @@
+/**
+ *  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.asn1;
+
+import org.apache.kerby.asn1.type.*;
+
+/**
+ * Ref. X.690-0207(http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf),
+ * Annex A, A.1 ASN.1 description of the record structure
+ */
+public class PersonnelRecord extends TaggingSet {
+    private static int NAME = 0;
+    private static int TITLE = 1;
+    private static int NUMBER = 2;
+    private static int DATEOFHIRE= 3;
+    private static int NAMEOFSPOUSE = 4;
+    private static int CHILDREN = 5;
+
+    static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
+            new Asn1FieldInfo(NAME, -1, Name.class),
+            new Asn1FieldInfo(TITLE, 0, Asn1VisibleString.class),
+            new Asn1FieldInfo(NUMBER, -1, EmployeeNumber.class),
+            new Asn1FieldInfo(DATEOFHIRE, 1, Date.class),
+            new Asn1FieldInfo(NAMEOFSPOUSE, 2, Name.class),
+            new Asn1FieldInfo(CHILDREN, 3, Children.class, true)
+    };
+
+    public PersonnelRecord() {
+        super(0, fieldInfos, true);
+        setEncodingOption(EncodingOption.IMPLICIT);
+    }
+
+    public void setName(Name name) {
+        setFieldAs(NAME, name);
+    }
+
+    public Name getName() {
+        return getFieldAs(NAME, Name.class);
+    }
+
+    public void setTitle(String title) {
+        setFieldAs(TITLE, new Asn1VisibleString(title));
+    }
+
+    public String getTitle() {
+        return getFieldAsString(TITLE);
+    }
+
+    public void setEmployeeNumber(EmployeeNumber employeeNumber) {
+        setFieldAs(NUMBER, employeeNumber);
+    }
+
+    public EmployeeNumber getEmployeeNumber() {
+        return getFieldAs(NUMBER, EmployeeNumber.class);
+    }
+
+    public void setDateOfHire(Date dateOfHire) {
+        setFieldAs(DATEOFHIRE, dateOfHire);
+    }
+
+    public Date getDateOfHire() {
+        return getFieldAs(DATEOFHIRE, Date.class);
+    }
+
+    public void setNameOfSpouse(Name spouse) {
+        setFieldAs(NAMEOFSPOUSE, spouse);
+    }
+
+    public Name getNameOfSpouse() {
+        return getFieldAs(NAMEOFSPOUSE, Name.class);
+    }
+
+    public void setChildren(Children children) {
+        setFieldAs(CHILDREN, children);
+    }
+
+    public Children getChildren() {
+        return getFieldAs(CHILDREN, Children.class);
+    }
+
+    public static class Children extends Asn1SequenceOf<ChildInformation> {
+        public Children(ChildInformation ... children) {
+            super();
+            for (ChildInformation child : children) {
+                addElement(child);
+            }
+        }
+
+        public Children() {
+            super();
+        }
+    }
+
+    public static class ChildInformation extends Asn1SetType {
+        private static int NAME = 0;
+        private static int DATEOFBIRTH = 1;
+
+        static Asn1FieldInfo[] tags = new Asn1FieldInfo[] {
+                new Asn1FieldInfo(NAME, -1, Name.class),
+                new Asn1FieldInfo(DATEOFBIRTH, 0, Date.class)
+        };
+
+        public ChildInformation() {
+            super(tags);
+        }
+
+        public void setName(Name name) {
+            setFieldAs(NAME, name);
+        }
+
+        public Name getName() {
+            return getFieldAs(NAME, Name.class);
+        }
+
+        public void setDateOfBirth(Date date) {
+            setFieldAs(DATEOFBIRTH, date);
+        }
+
+        public Date getDateOfBirth() {
+            return getFieldAs(DATEOFBIRTH, Date.class);
+        }
+    }
+
+    public static class Name extends TaggingSequence {
+        private static int GIVENNAME = 0;
+        private static int INITIAL = 1;
+        private static int FAMILYNAME = 2;
+
+        static Asn1FieldInfo[] tags = new Asn1FieldInfo[] {
+                new Asn1FieldInfo(GIVENNAME, -1, Asn1VisibleString.class),
+                new Asn1FieldInfo(INITIAL, -1, Asn1VisibleString.class),
+                new Asn1FieldInfo(FAMILYNAME, -1, Asn1VisibleString.class)
+        };
+
+        public Name() {
+            super(1, tags, true);
+            setEncodingOption(EncodingOption.IMPLICIT);
+        }
+
+        public Name(String givenName, String initial, String familyName) {
+            this();
+            setGivenName(givenName);
+            setInitial(initial);
+            setFamilyName(familyName);
+        }
+
+        public void setGivenName(String givenName) {
+            setFieldAs(GIVENNAME, new Asn1VisibleString(givenName));
+        }
+
+        public String getGivenName() {
+            return getFieldAsString(GIVENNAME);
+        }
+
+        public void setInitial(String initial) {
+            setFieldAs(INITIAL, new Asn1VisibleString(initial));
+        }
+
+        public String getInitial() {
+            return getFieldAsString(INITIAL);
+        }
+
+        public void setFamilyName(String familyName) {
+            setFieldAs(FAMILYNAME, new Asn1VisibleString(familyName));
+        }
+
+        public String getFamilyName() {
+            return getFieldAsString(FAMILYNAME);
+        }
+    }
+
+    public static class EmployeeNumber extends Asn1Tagging<Asn1Integer> {
+        public EmployeeNumber(Integer value) {
+            super(2, new Asn1Integer(value), true);
+            setEncodingOption(EncodingOption.IMPLICIT);
+        }
+        public EmployeeNumber() {
+            this(null);
+        }
+    }
+
+    public static class Date extends Asn1Tagging<Asn1VisibleString> {
+        public Date(String value) {
+            super(3, new Asn1VisibleString(value), true);
+            setEncodingOption(EncodingOption.IMPLICIT);
+        }
+        public Date() {
+            this(null);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Boolean.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Boolean.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Boolean.java
new file mode 100644
index 0000000..79e2547
--- /dev/null
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Boolean.java
@@ -0,0 +1,56 @@
+/**
+ *  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.asn1;
+
+import org.apache.kerby.asn1.type.Asn1Boolean;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class TestAsn1Boolean {
+
+    @Test
+    public void testEncoding() {
+        testEncodingWith(true, "0x01 01 FF");
+        testEncodingWith(false, "0x01 01 00");
+    }
+
+    private void testEncodingWith(Boolean value, String expectedEncoding) {
+        byte[] expected = Util.hex2bytes(expectedEncoding);
+        Asn1Boolean aValue = new Asn1Boolean(value);
+        aValue.setEncodingOption(EncodingOption.DER);
+        byte[] encodingBytes = aValue.encode();
+        Assert.assertArrayEquals(expected, encodingBytes);
+    }
+
+    @Test
+    public void testDecoding() throws IOException {
+        testDecodingWith(true, "0x01 01 FF");
+        testDecodingWith(false, "0x01 01 00");
+    }
+
+    private void testDecodingWith(Boolean expectedValue, String content) throws IOException {
+        Asn1Boolean decoded = new Asn1Boolean();
+        decoded.setEncodingOption(EncodingOption.DER);
+        decoded.decode(Util.hex2bytes(content));
+        Assert.assertEquals(expectedValue, decoded.getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Collection.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Collection.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Collection.java
new file mode 100644
index 0000000..1119d7c
--- /dev/null
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Collection.java
@@ -0,0 +1,58 @@
+/**
+ *  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.asn1;
+
+import org.apache.kerby.asn1.type.AbstractAsn1Type;
+import org.apache.kerby.asn1.type.Asn1Boolean;
+import org.apache.kerby.asn1.type.Asn1IA5String;
+import org.apache.kerby.asn1.type.Asn1Sequence;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class TestAsn1Collection {
+    static String TEST_STR = "Jones";
+    static Boolean TEST_BOOL = true;
+    static byte[] EXPECTED_BYTES = new byte[] {(byte) 0x30, (byte) 0x0A,
+            (byte) 0x16, (byte) 0x05, (byte) 0x4A, (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x73,
+            (byte) 0x01, (byte) 0x01, (byte) 0xFF
+    };
+
+    @Test
+    public void testSequenceEncoding() {
+        Asn1Sequence seq = new Asn1Sequence();
+        seq.addItem(new Asn1IA5String(TEST_STR));
+        seq.addItem(new Asn1Boolean(TEST_BOOL));
+
+        Assert.assertArrayEquals(EXPECTED_BYTES, seq.encode());
+    }
+
+    @Test
+    public void testSequenceDecoding() throws IOException {
+        Asn1Sequence seq = new Asn1Sequence();
+        seq.decode(EXPECTED_BYTES);
+        AbstractAsn1Type field = (AbstractAsn1Type) seq.getValue().get(0).getValue();
+        Assert.assertEquals(TEST_STR, field.getValue());
+
+        field = (AbstractAsn1Type) seq.getValue().get(1).getValue();
+        Assert.assertEquals(TEST_BOOL, field.getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Input.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Input.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Input.java
new file mode 100644
index 0000000..9a5b2c5
--- /dev/null
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Input.java
@@ -0,0 +1,35 @@
+/**
+ *  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.asn1;
+
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class TestAsn1Input {
+
+    @Test
+    public void testDecoding() throws IOException {
+        //PersonnelRecord expected = TestData.createSamplePersonnel();
+        byte[] data = TestData.createSammplePersonnelEncodingData();
+        //Asn1InputBuffer ib = new Asn1InputBuffer(data);
+        Asn1Dump.dump(data);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Integer.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Integer.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Integer.java
new file mode 100644
index 0000000..e330da4
--- /dev/null
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Integer.java
@@ -0,0 +1,70 @@
+/**
+ *  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.asn1;
+
+import org.apache.kerby.asn1.type.Asn1Integer;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class TestAsn1Integer {
+
+    @Test
+    public void testEncoding() {
+        testEncodingWith(0, "0x02 01 00");
+        testEncodingWith(1, "0x02 01 01");
+        testEncodingWith(2, "0x02 01 02");
+        testEncodingWith(127, "0x02 01 7F");
+        testEncodingWith(128, "0x02 02 00 80");
+        testEncodingWith(-1, "0x02 01 FF");
+        testEncodingWith(-128, "0x02 01 80");
+        testEncodingWith(-32768, "0x02 02 80 00");
+        testEncodingWith(1234567890, "0x02 04 49 96 02 D2");
+    }
+
+    private void testEncodingWith(int value, String expectedEncoding) {
+        byte[] expected = Util.hex2bytes(expectedEncoding);
+        Asn1Integer aValue = new Asn1Integer(value);
+        aValue.setEncodingOption(EncodingOption.DER);
+        byte[] encodingBytes = aValue.encode();
+        Assert.assertArrayEquals(expected, encodingBytes);
+    }
+
+    @Test
+    public void testDecoding() throws IOException {
+        testDecodingWith(0, "0x02 01 00");
+        testDecodingWith(1, "0x02 01 01");
+        testDecodingWith(2, "0x02 01 02");
+        testDecodingWith(127, "0x02 01 7F");
+        testDecodingWith(128, "0x02 02 00 80");
+        testDecodingWith(-1, "0x02 01 FF");
+        testDecodingWith(-128, "0x02 01 80");
+        testDecodingWith(-32768, "0x02 02 80 00");
+        testDecodingWith(1234567890, "0x02 04 49 96 02 D2");
+    }
+
+    private void testDecodingWith(Integer expectedValue, String content) throws IOException {
+        Asn1Integer decoded = new Asn1Integer();
+        decoded.setEncodingOption(EncodingOption.DER);
+        decoded.decode(Util.hex2bytes(content));
+        Assert.assertEquals(expectedValue, decoded.getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1ObjectIdentifier.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1ObjectIdentifier.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1ObjectIdentifier.java
new file mode 100644
index 0000000..04f8089
--- /dev/null
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1ObjectIdentifier.java
@@ -0,0 +1,64 @@
+/**
+ *  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.asn1;
+
+import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class TestAsn1ObjectIdentifier {
+
+    @Test
+    public void testEncoding() throws Exception {
+        /**
+         * Cryptography for Developers -> ASN.1 UTCTIME Type
+         * Applying this to the MD5 OID, we first transform the dotted decimal form into the
+         * array of words.Thus, 1.2.840.113549.2.5 becomes {42, 840, 113549, 2, 5}, and then further
+         * 404_CRYPTO_02.qxd 10/27/06 3:40 PM Page 36split into seven-bit digits with the proper most significant bits as
+         * {{0x2A}, {0x86, 0x48},{0x86, 0xF7, 0x0D}, {0x02}, {0x05}}.Therefore, the full encoding for MD5 is 0x06 08 2A
+         * 86 48 86 F7 0D 02 05.
+         */
+        testEncodingWith("1.2.840.113549.2.5",
+                "0x06 08 2A 86 48 86 F7 0D 02 05");
+    }
+
+    private void testEncodingWith(String oid, String expectedEncoding) {
+        byte[] expected = Util.hex2bytes(expectedEncoding);
+        Asn1ObjectIdentifier aValue = new Asn1ObjectIdentifier(oid);
+        aValue.setEncodingOption(EncodingOption.DER);
+        byte[] encodingBytes = aValue.encode();
+        Assert.assertArrayEquals(expected, encodingBytes);
+    }
+
+    @Test
+    public void testDecoding() throws Exception {
+        testDecodingWith("1.2.840.113549.2.5",
+                "0x06 08 2A 86 48 86 F7 0D 02 05");
+    }
+
+    private void testDecodingWith(String expectedValue, String content) throws IOException {
+        Asn1ObjectIdentifier decoded = new Asn1ObjectIdentifier();
+        decoded.setEncodingOption(EncodingOption.DER);
+        decoded.decode(Util.hex2bytes(content));
+        Assert.assertEquals(expectedValue, decoded.getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1UtcTime.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1UtcTime.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1UtcTime.java
new file mode 100644
index 0000000..abd991b
--- /dev/null
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1UtcTime.java
@@ -0,0 +1,70 @@
+/**
+ *  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.asn1;
+
+import org.apache.kerby.asn1.type.Asn1UtcTime;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+
+public class TestAsn1UtcTime {
+
+    @Test
+    public void testEncoding() throws Exception {
+        /**
+         * Cryptography for Developers -> ASN.1 UTCTIME Type
+         * the encoding of July 4, 2003 at 11:33 and 28 seconds would be
+         “030704113328Z” and be encoded as 0x17 0D 30 33 30 37 30 34 31 31 33 33 32 38 5A.
+         */
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
+        String dateInString = "2003-07-04 11:33:28";
+        Date date = sdf.parse(dateInString);
+        testEncodingWith(date, "0x17 0D 30 33 30 37 30 34 31 31 33 33 32 38 5A");
+    }
+
+    private void testEncodingWith(Date value, String expectedEncoding) {
+        byte[] expected = Util.hex2bytes(expectedEncoding);
+        Asn1UtcTime aValue = new Asn1UtcTime(value);
+        aValue.setEncodingOption(EncodingOption.DER);
+        byte[] encodingBytes = aValue.encode();
+        Assert.assertArrayEquals(expected, encodingBytes);
+    }
+
+    @Test
+    public void testDecoding() throws Exception {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateInString = "2003-07-04 11:33:28";
+        sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
+        Date date = sdf.parse(dateInString);
+        testDecodingWith(date, "0x17 0D 30 33 30 37 30 34 31 31 33 33 32 38 5A");
+    }
+
+    private void testDecodingWith(Date expectedValue, String content) throws IOException {
+        Asn1UtcTime decoded = new Asn1UtcTime();
+        decoded.setEncodingOption(EncodingOption.DER);
+        decoded.decode(Util.hex2bytes(content));
+        Assert.assertEquals(expectedValue, decoded.getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestData.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestData.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestData.java
new file mode 100644
index 0000000..875288a
--- /dev/null
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestData.java
@@ -0,0 +1,127 @@
+/**
+ *  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.asn1;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+
+public class TestData {
+
+    public static PersonnelRecord createSamplePersonnel() {
+        PersonnelRecord pr = new PersonnelRecord();
+
+        pr.setName(new PersonnelRecord.Name("John", "P", "Smith"));
+
+        pr.setTitle("Director");
+
+        pr.setEmployeeNumber(new PersonnelRecord.EmployeeNumber(51));
+
+        pr.setDateOfHire(new PersonnelRecord.Date("19710917"));
+
+        pr.setNameOfSpouse(new PersonnelRecord.Name("Mary", "T", "Smith"));
+
+        PersonnelRecord.ChildInformation child1 = new PersonnelRecord.ChildInformation();
+        child1.setName(new PersonnelRecord.Name("Ralph", "T", "Smith"));
+        child1.setDateOfBirth(new PersonnelRecord.Date("19571111"));
+
+        PersonnelRecord.ChildInformation child2 = new PersonnelRecord.ChildInformation();
+        child2.setName(new PersonnelRecord.Name("Susan", "B", "Jones"));
+        child2.setDateOfBirth(new PersonnelRecord.Date("19590717"));
+
+        pr.setChildren(new PersonnelRecord.Children(child1, child2));
+
+        return pr;
+    }
+
+    public static byte[] createSammplePersonnelEncodingData() {
+        class BufferOutput {
+            ByteBuffer buffer;
+
+            void put(byte ... bytes) {
+                buffer.put(bytes);
+            }
+
+            void put(String s) {
+                byte[] bytes = s.getBytes(StandardCharsets.US_ASCII);
+                buffer.put(bytes);
+            }
+
+            public byte[] output() {
+                int len = (int) 0x85 + 3;
+                buffer = ByteBuffer.allocate(len);
+
+                // personnel record
+                put((byte) 0x60, (byte) 0x81, (byte) 0x85);
+
+                // -name
+                put((byte) 0x61, (byte) 0x10);
+                put((byte) 0x1A, (byte) 0x04); put("John");
+                put((byte) 0x1A, (byte) 0x01); put("P");
+                put((byte) 0x1A, (byte) 0x05); put("Smith");
+
+                //-title
+                put((byte) 0xA0, (byte) 0x0A);
+                put((byte) 0x1A, (byte) 0x08); put("Director");
+
+                //-employee number
+                put((byte) 0x42, (byte) 0x01, (byte) 0x33);
+
+                //-date of hire
+                put((byte) 0xA1, (byte) 0x0A);
+                put((byte) 0x43, (byte) 0x08); put("19710917");
+
+                //-spouse
+                put((byte) 0xA2, (byte) 0x12);
+                put((byte) 0x61, (byte) 0x10);
+                put((byte) 0x1A, (byte) 0x04); put("Mary");
+                put((byte) 0x1A, (byte) 0x01); put("T");
+                put((byte) 0x1A, (byte) 0x05); put("Smith");
+
+                //-children
+                put((byte) 0xA3, (byte) 0x42);
+                //--child 1
+                put((byte) 0x31, (byte) 0x1F);
+                //---name
+                put((byte) 0x61, (byte) 0x11);
+                put((byte) 0x1A, (byte) 0x05); put("Ralph");
+                put((byte) 0x1A, (byte) 0x01); put("T");
+                put((byte) 0x1A, (byte) 0x05); put("Smith");
+                //-date of birth
+                put((byte) 0xA0, (byte) 0x0A);
+                put((byte) 0x43, (byte) 0x08); put("19571111");
+                //--child 2
+                put((byte) 0x31, (byte) 0x1F);
+                //---name
+                put((byte) 0x61, (byte) 0x11);
+                put((byte) 0x1A, (byte) 0x05); put("Susan");
+                put((byte) 0x1A, (byte) 0x01); put("B");
+                put((byte) 0x1A, (byte) 0x05); put("Jones");
+                //-date of birth
+                put((byte) 0xA0, (byte) 0x0A);
+                put((byte) 0x43, (byte) 0x08); put("19590717");
+
+                return buffer.array();
+            }
+        }
+
+        BufferOutput buffer = new BufferOutput();
+        return buffer.output();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestPersonnelRecord.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestPersonnelRecord.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestPersonnelRecord.java
new file mode 100644
index 0000000..d6c8e6e
--- /dev/null
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestPersonnelRecord.java
@@ -0,0 +1,126 @@
+/**
+ *  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.asn1;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+
+/**
+ * Ref. X.690-0207(http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf),
+ * Annex A, A.1 ASN.1 description of the record structure
+ */
+public class TestPersonnelRecord {
+
+    static boolean verbose = false;
+
+    @Test
+    public void testEncoding() {
+        PersonnelRecord pr = TestData.createSamplePersonnel();
+
+        if (verbose) {
+            System.out.println("Name:");
+            System.out.println(Util.bytesToHex(pr.getName().encode()));
+
+        /*
+        System.out.println("Title:");
+        System.out.println(Util.bytesToHex(pr.getFieldAs(1, Asn1VisibleString.class).encode()));
+
+        System.out.println("EmployeeNumber:");
+        System.out.println(Util.bytesToHex(pr.getFieldAs(2, EmployeeNumber.class).encode()));
+        */
+
+            System.out.println("DateOfHire:");
+            System.out.println(Util.bytesToHex(pr.getDateOfHire().encode()));
+
+            System.out.println("SpouseName:");
+            System.out.println(Util.bytesToHex(pr.getNameOfSpouse().encode()));
+
+            System.out.println("Child1:");
+            System.out.println(Util.bytesToHex(pr.getChildren().getElements().get(0).encode()));
+
+            System.out.println("Child2:");
+            System.out.println(Util.bytesToHex(pr.getChildren().getElements().get(1).encode()));
+
+            System.out.println("Children:");
+            System.out.println(Util.bytesToHex(pr.getChildren().encode()));
+        }
+
+        byte[] data = TestData.createSammplePersonnelEncodingData();
+        byte[] encoded = pr.encode();
+
+        if (verbose) {
+            System.out.println("ExpectedData:");
+            System.out.println(Util.bytesToHex(data));
+
+            System.out.println("Encoded:");
+            System.out.println(Util.bytesToHex(encoded));
+        }
+
+        Assert.assertArrayEquals(data, encoded);
+    }
+
+    @Test
+    public void testDecoding() throws IOException {
+        PersonnelRecord expected = TestData.createSamplePersonnel();
+        byte[] data = TestData.createSammplePersonnelEncodingData();
+        PersonnelRecord decoded = new PersonnelRecord();
+        decoded.decode(data);
+
+        Assert.assertEquals(expected.getName().getGivenName(),
+                decoded.getName().getGivenName());
+        Assert.assertEquals(expected.getName().getInitial(),
+                decoded.getName().getInitial());
+        Assert.assertEquals(expected.getName().getFamilyName(),
+                decoded.getName().getFamilyName());
+
+        Assert.assertEquals(expected.getDateOfHire().getValue().getValue(),
+                decoded.getDateOfHire().getValue().getValue());
+        Assert.assertEquals(expected.getTitle(), decoded.getTitle());
+        Assert.assertEquals(expected.getEmployeeNumber().getValue().getValue(),
+                decoded.getEmployeeNumber().getValue().getValue());
+
+        Assert.assertEquals(expected.getNameOfSpouse().getGivenName(),
+                decoded.getNameOfSpouse().getGivenName());
+        Assert.assertEquals(expected.getNameOfSpouse().getInitial(),
+                decoded.getNameOfSpouse().getInitial());
+        Assert.assertEquals(expected.getNameOfSpouse().getFamilyName(),
+                decoded.getNameOfSpouse().getFamilyName());
+
+        Assert.assertEquals(expected.getChildren().getElements().get(0).getName().getGivenName(),
+                decoded.getChildren().getElements().get(0).getName().getGivenName());
+        Assert.assertEquals(expected.getChildren().getElements().get(0).getName().getInitial(),
+                decoded.getChildren().getElements().get(0).getName().getInitial());
+        Assert.assertEquals(expected.getChildren().getElements().get(0).getName().getFamilyName(),
+                decoded.getChildren().getElements().get(0).getName().getFamilyName());
+        Assert.assertEquals(expected.getChildren().getElements().get(0).getDateOfBirth().getValue().getValue(),
+                decoded.getChildren().getElements().get(0).getDateOfBirth().getValue().getValue());
+
+        Assert.assertEquals(expected.getChildren().getElements().get(1).getName().getGivenName(),
+                decoded.getChildren().getElements().get(1).getName().getGivenName());
+        Assert.assertEquals(expected.getChildren().getElements().get(1).getName().getInitial(),
+                decoded.getChildren().getElements().get(1).getName().getInitial());
+        Assert.assertEquals(expected.getChildren().getElements().get(1).getName().getFamilyName(),
+                decoded.getChildren().getElements().get(1).getName().getFamilyName());
+        Assert.assertEquals(expected.getChildren().getElements().get(1).getDateOfBirth().getValue().getValue(),
+                decoded.getChildren().getElements().get(1).getDateOfBirth().getValue().getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestTaggingEncoding.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestTaggingEncoding.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestTaggingEncoding.java
new file mode 100644
index 0000000..59510f1
--- /dev/null
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestTaggingEncoding.java
@@ -0,0 +1,203 @@
+/**
+ *  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.asn1;
+
+import org.apache.kerby.asn1.type.Asn1Tagging;
+import org.apache.kerby.asn1.type.Asn1VisibleString;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+
+/**
+ Ref. X.690-0207 8.14 Encoding of a tagged value
+ EXAMPLE
+ With ASN.1 type definitions (in an explicit tagging environment) of:
+ Type1 ::= VisibleString
+ Type2 ::= [APPLICATION 3] IMPLICIT Type1
+ Type3 ::= [2] Type2
+ Type4 ::= [APPLICATION 7] IMPLICIT Type3
+ Type5 ::= [2] IMPLICIT Type2
+ a value of:
+ "Jones"
+ is encoded as follows:
+ For Type1:
+ VisibleString Length Contents
+ 1A16 0516 4A6F6E657316
+ For Type2:
+ [Application 3] Length Contents
+ 4316 0516 4A6F6E657316
+ For Type3:
+ [2] Length Contents
+ A216 0716
+ [APPLICATION 3] Length Contents
+ 4316 0516 4A6F6E657316
+ For Type4:
+ [Application 7] Length Contents
+ 6716 0716
+ [APPLICATION 3] Length Contents
+ 4316 0516 4A6F6E657316
+ For Type5:
+ [2] Length Contents
+ 8216 0516 4A6F6E657316
+ */
+
+public class TestTaggingEncoding {
+    static final String TEST_STRING = "Jones";
+    static byte[] TYPE1_EXPECTED_BYTES = new byte[] {(byte) 0x1A, (byte) 0x05, (byte) 0x4A, (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x73};
+    static byte[] TYPE2_EXPECTED_BYTES = new byte[] {(byte) 0x43, (byte) 0x05, (byte) 0x4A, (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x73};
+    static byte[] TYPE3_EXPECTED_BYTES = new byte[] {(byte) 0xA2, (byte) 0x07, (byte) 0x43, (byte) 0x05, (byte) 0x4A, (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x73};
+    static byte[] TYPE4_EXPECTED_BYTES = new byte[] {(byte) 0x67, (byte) 0x07, (byte) 0x43, (byte) 0x05, (byte) 0x4A, (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x73};
+    static byte[] TYPE5_EXPECTED_BYTES = new byte[] {(byte) 0x82, (byte) 0x05, (byte) 0x4A, (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x73};
+
+
+    public static class Type1 extends Asn1VisibleString {
+        public Type1(String value) {
+            super(value);
+        }
+        public Type1() {
+            this(null);
+        }
+    }
+
+    public static class Type2 extends Asn1Tagging<Type1> {
+        public Type2(Type1 value) {
+            super(3, value, true);
+            setEncodingOption(EncodingOption.IMPLICIT);
+        }
+        public Type2() {
+            this(null);
+        }
+    }
+
+    public static class Type3 extends Asn1Tagging<Type2> {
+        public Type3(Type2 value) {
+            super(2, value, false);
+            setEncodingOption(EncodingOption.EXPLICIT);
+        }
+        public Type3() {
+            this(null);
+        }
+    }
+
+    public static class Type4 extends Asn1Tagging<Type3> {
+        public Type4(Type3 value) {
+            super(7, value, true);
+            setEncodingOption(EncodingOption.IMPLICIT);
+        }
+        public Type4() {
+            this(null);
+        }
+    }
+
+    public static class Type5 extends Asn1Tagging<Type2> {
+        public Type5(Type2 value) {
+            super(2, value, false);
+            setEncodingOption(EncodingOption.IMPLICIT);
+        }
+        public Type5() {
+            this(null);
+        }
+    }
+
+    @Test
+    public void testAsn1TaggingEncoding() {
+        Type1 aType1 = new Type1(TEST_STRING);
+        Type2 aType2 = new Type2(aType1);
+        Type3 aType3 = new Type3(aType2);
+        Type4 aType4 = new Type4(aType3);
+        Type5 aType5 = new Type5(aType2);
+
+        Assert.assertArrayEquals(TYPE1_EXPECTED_BYTES, aType1.encode());
+        Assert.assertArrayEquals(TYPE2_EXPECTED_BYTES, aType2.encode());
+        Assert.assertArrayEquals(TYPE3_EXPECTED_BYTES, aType3.encode());
+        Assert.assertArrayEquals(TYPE4_EXPECTED_BYTES, aType4.encode());
+        Assert.assertArrayEquals(TYPE5_EXPECTED_BYTES, aType5.encode());
+    }
+
+    @Test
+    public void testAsn1TaggingDecoding() throws IOException {
+        Type1 aType1 = new Type1();
+        aType1.decode(TYPE1_EXPECTED_BYTES);
+        Assert.assertEquals(TEST_STRING, aType1.getValue());
+
+        Type2 aType2 = new Type2();
+        aType2.decode(TYPE2_EXPECTED_BYTES);
+        Assert.assertEquals(TEST_STRING, aType2.getValue().getValue());
+
+        Type3 aType3 = new Type3();
+        aType3.decode(TYPE3_EXPECTED_BYTES);
+        Assert.assertEquals(TEST_STRING, aType3.getValue().getValue().getValue());
+
+        Type4 aType4 = new Type4();
+        aType4.decode(TYPE4_EXPECTED_BYTES);
+        Assert.assertEquals(TEST_STRING, aType4.getValue().getValue().getValue().getValue());
+
+        Type5 aType5 = new Type5();
+        aType5.decode(TYPE5_EXPECTED_BYTES);
+        Assert.assertEquals(TEST_STRING, aType5.getValue().getValue().getValue());
+    }
+
+    @Test
+    public void testTaggingEncodingOption() {
+        Type1 aType1 = new Type1(TEST_STRING);
+        Type2 aType2 = new Type2(aType1);
+        Type3 aType3 = new Type3(aType2);
+        Type4 aType4 = new Type4(aType3);
+        Type5 aType5 = new Type5(aType2);
+
+        Assert.assertArrayEquals(TYPE1_EXPECTED_BYTES, aType1.encode());
+        Assert.assertArrayEquals(TYPE2_EXPECTED_BYTES,
+                aType1.taggedEncode(TaggingOption.newImplicitAppSpecific(3))); // for Type2
+        Assert.assertArrayEquals(TYPE3_EXPECTED_BYTES,
+                aType2.taggedEncode(TaggingOption.newExplicitContextSpecific(2))); // for Type3
+        Assert.assertArrayEquals(TYPE4_EXPECTED_BYTES,
+                aType3.taggedEncode(TaggingOption.newImplicitAppSpecific(7))); // for Type4
+        Assert.assertArrayEquals(TYPE5_EXPECTED_BYTES,
+                aType2.taggedEncode(TaggingOption.newImplicitContextSpecific(2)));  // for Type5
+    }
+
+    @Test
+    public void testTaggingDecodingOption() throws IOException {
+        Type1 aType1 = new Type1();
+        aType1.decode(TYPE1_EXPECTED_BYTES);
+        Assert.assertEquals(TEST_STRING, aType1.getValue());
+
+        // for Type2
+        aType1 = new Type1();
+        aType1.taggedDecode(TYPE2_EXPECTED_BYTES, TaggingOption.newImplicitAppSpecific(3));
+        Assert.assertEquals(TEST_STRING, aType1.getValue());
+
+        // for Type3
+        Type2 aType2 = new Type2();
+        aType2.taggedDecode(TYPE3_EXPECTED_BYTES, TaggingOption.newExplicitContextSpecific(2));
+        Assert.assertEquals(TEST_STRING, aType2.getValue().getValue());
+
+        // for Type4
+        Type3 aType3 = new Type3();
+        aType3.taggedDecode(TYPE4_EXPECTED_BYTES, TaggingOption.newImplicitAppSpecific(7));
+        Assert.assertEquals(TEST_STRING, aType3.getValue().getValue().getValue());
+
+        // for Type5
+        aType2 = new Type2();
+        aType2.taggedDecode(TYPE5_EXPECTED_BYTES, TaggingOption.newImplicitContextSpecific(2));
+        Assert.assertEquals(TEST_STRING, aType2.getValue().getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/test/java/org/apache/kerby/asn1/Util.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/Util.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/Util.java
new file mode 100644
index 0000000..5f58e1a
--- /dev/null
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/Util.java
@@ -0,0 +1,72 @@
+/**
+ *  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.asn1;
+
+public class Util {
+
+    final static String HEX_CHARS_STR = "0123456789ABCDEF";
+    final static 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) {
+        hexString = hexString.toUpperCase();
+        String hexStr = hexString;
+        if (hexString.startsWith("0X")) {
+            hexStr = hexString.substring(2);
+        }
+        String[] hexParts = hexStr.split(" ");
+
+        byte[] bytes = new byte[hexParts.length];
+        char[] hexPart;
+        for (int i = 0; i < hexParts.length; ++i) {
+            hexPart = hexParts[i].toCharArray();
+            if (hexPart.length != 2) {
+                throw new IllegalArgumentException("Invalid hex string to convert");
+            }
+            bytes[i] = (byte) ((HEX_CHARS_STR.indexOf(hexPart[0]) << 4) + HEX_CHARS_STR.indexOf(hexPart[1]));
+        }
+
+        return bytes;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kdc/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-kdc/pom.xml b/kerby-kdc/pom.xml
new file mode 100644
index 0000000..a353f86
--- /dev/null
+++ b/kerby-kdc/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed 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. See accompanying LICENSE file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.kerby</groupId>
+    <artifactId>kerby-all</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>kerby-KDC</artifactId>
+  <name>Kerby KDC Server</name>
+  <description>Kerby KDC Server</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-config</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-server</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>ldap-identity-backend</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-token</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kdc/src/main/java/org/apache/kerby/kerberos/kdc/server/ApacheKdcServer.java
----------------------------------------------------------------------
diff --git a/kerby-kdc/src/main/java/org/apache/kerby/kerberos/kdc/server/ApacheKdcServer.java b/kerby-kdc/src/main/java/org/apache/kerby/kerberos/kdc/server/ApacheKdcServer.java
new file mode 100644
index 0000000..3cb7ff4
--- /dev/null
+++ b/kerby-kdc/src/main/java/org/apache/kerby/kerberos/kdc/server/ApacheKdcServer.java
@@ -0,0 +1,41 @@
+/**
+ *  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 main.java.org.apache.kerby.kerberos.kdc.server;
+
+import org.apache.kerby.kerberos.kdc.identitybackend.LdapIdentityBackend;
+import org.apache.kerby.kerberos.kerb.identity.IdentityService;
+import org.apache.kerby.kerberos.kerb.server.KdcServer;
+
+public class ApacheKdcServer extends KdcServer {
+
+    public ApacheKdcServer() {
+        super();
+    }
+
+    public void init() {
+        super.init();
+        initIdentityService();
+    }
+
+    protected void initIdentityService() {
+        IdentityService identityService = new LdapIdentityBackend();
+        setIdentityService(identityService);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kdc/src/test/java/org/apache/kerby/kerberos/kdc/server/KdcTest.java
----------------------------------------------------------------------
diff --git a/kerby-kdc/src/test/java/org/apache/kerby/kerberos/kdc/server/KdcTest.java b/kerby-kdc/src/test/java/org/apache/kerby/kerberos/kdc/server/KdcTest.java
new file mode 100644
index 0000000..f028657
--- /dev/null
+++ b/kerby-kdc/src/test/java/org/apache/kerby/kerberos/kdc/server/KdcTest.java
@@ -0,0 +1,70 @@
+/**
+ *  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 test.java.org.apache.kerby.kerberos.kdc.server;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+
+public class KdcTest {
+
+    private String serverHost = "localhost";
+    private short serverPort = 8088;
+
+    private ApacheKdcServer kdcServer;
+
+    @Before
+    public void setUp() throws Exception {
+        kdcServer = new ApacheKdcServer();
+        kdcServer.setKdcHost(serverHost);
+        kdcServer.setKdcTcpPort(serverPort);
+        kdcServer.init();
+        kdcServer.start();
+    }
+
+    @Test
+    public void testKdc() throws IOException, InterruptedException {
+        Thread.sleep(10);
+
+        SocketChannel socketChannel = SocketChannel.open();
+        socketChannel.configureBlocking(true);
+        SocketAddress sa = new InetSocketAddress(serverHost, serverPort);
+        socketChannel.connect(sa);
+
+        String BAD_KRB_MESSAGE = "Hello World!";
+        ByteBuffer writeBuffer = ByteBuffer.allocate(4 + BAD_KRB_MESSAGE.getBytes().length);
+        writeBuffer.putInt(BAD_KRB_MESSAGE.getBytes().length);
+        writeBuffer.put(BAD_KRB_MESSAGE.getBytes());
+        writeBuffer.flip();
+
+        socketChannel.write(writeBuffer);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        kdcServer.stop();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/README
----------------------------------------------------------------------
diff --git a/kerby-kerb/README b/kerby-kerb/README
new file mode 100644
index 0000000..e0a1507
--- /dev/null
+++ b/kerby-kerb/README
@@ -0,0 +1,2 @@
+A Kerberos protocol and standards implementation with least dependencies (only relying on JCE).
+The provided APIs and facilities can be used as embedded.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-client/pom.xml
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/pom.xml b/kerby-kerb/kerb-client/pom.xml
new file mode 100644
index 0000000..c4d1290
--- /dev/null
+++ b/kerby-kerb/kerb-client/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed 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. See accompanying LICENSE file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.kerby</groupId>
+    <artifactId>kerby-kerb</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>kerb-client</artifactId>
+  <name>Kerby-kerb Client</name>
+  <description>Kerby-kerb Client</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-config</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerb-common</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-event</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-pkix</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.kerby</groupId>
+      <artifactId>kerby-token</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/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
new file mode 100644
index 0000000..e3bca5b
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbClient.java
@@ -0,0 +1,321 @@
+/**
+ *  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;
+
+import org.apache.haox.event.Event;
+import org.apache.haox.event.EventHub;
+import org.apache.haox.event.EventWaiter;
+import org.apache.kerby.kerberos.kerb.KrbErrorCode;
+import org.apache.kerby.kerberos.kerb.client.event.KrbClientEvent;
+import org.apache.kerby.kerberos.kerb.client.event.KrbClientEventType;
+import org.apache.kerby.kerberos.kerb.client.request.*;
+import org.apache.kerby.kerberos.kerb.common.KrbErrorUtil;
+import org.apache.kerby.kerberos.kerb.common.KrbStreamingDecoder;
+import org.apache.kerby.kerberos.kerb.KrbErrorException;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.common.KrbError;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+import org.apache.kerby.kerberos.kerb.spec.ticket.ServiceTicket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket;
+import org.haox.token.KerbToken;
+import org.apache.haox.transport.Connector;
+import org.apache.haox.transport.Transport;
+import org.apache.haox.transport.event.TransportEvent;
+import org.apache.haox.transport.event.TransportEventType;
+import org.apache.haox.transport.tcp.TcpConnector;
+
+import java.io.IOException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A krb client API for applications to interact with KDC
+ */
+public class KrbClient {
+
+    private EventHub eventHub;
+    private EventWaiter eventWaiter;
+    private Transport transport;
+
+    private KrbHandler krbHandler;
+    private KrbContext context;
+    private KrbConfig config;
+
+    /**
+     *
+     * @param kdcHost
+     * @param kdcPort
+     */
+    public KrbClient(String kdcHost, short kdcPort) {
+        this(new KrbConfig());
+
+        setKdcHost(kdcHost);
+        setKdcPort(kdcPort);
+    }
+
+    public KrbClient(KrbConfig config) {
+        this.config = config;
+        this.context = new KrbContext();
+        context.init(config);
+    }
+
+    /**
+     * Set KDC realm for ticket request
+     * @param realm
+     */
+    public void setKdcRealm(String realm) {
+        context.setKdcRealm(realm);
+    }
+
+    /**
+     *
+     * @param kdcHost
+     */
+    public void setKdcHost(String kdcHost) {
+        context.setKdcHost(kdcHost);
+    }
+
+    /**
+     *
+     * @param kdcPort
+     */
+    public void setKdcPort(short kdcPort) {
+        context.setKdcPort(kdcPort);
+    }
+
+    /**
+     * Set time out for connection
+     * @param timeout in seconds
+     */
+    public void setTimeout(long timeout) {
+        context.setTimeout(timeout);
+    }
+
+    public void init() {
+        this.krbHandler = new KrbHandler();
+        krbHandler.init(context);
+
+        this.eventHub = new EventHub();
+        eventHub.register(krbHandler);
+
+        Connector connector = new TcpConnector(new KrbStreamingDecoder());
+        eventHub.register(connector);
+
+        eventWaiter = eventHub.waitEvent(
+                TransportEventType.NEW_TRANSPORT,
+                KrbClientEventType.TGT_RESULT,
+                KrbClientEventType.TKT_RESULT
+        );
+
+        eventHub.start();
+
+        connector.connect(context.getKdcHost(), context.getKdcPort());
+        Event event = eventWaiter.waitEvent(TransportEventType.NEW_TRANSPORT);
+        transport = ((TransportEvent) event).getTransport();
+    }
+
+    /**
+     * Attempt to request a TGT and you'll be prompted to input a credential.
+     * Whatever credential requested to provide depends on KDC admin configuration.
+     * @param options
+     * @return
+     * @throws KrbException
+     */
+    public TgtTicket requestTgtTicket(String principal, KrbOptions options) throws KrbException {
+        if (options == null) options = new KrbOptions();
+
+        AsRequest asRequest = new AsRequest(context);
+        asRequest.setKrbOptions(options);
+        return requestTgtTicket(principal, asRequest);
+    }
+
+    /**
+     * Request a TGT with user plain credential
+     * @param principal
+     * @param password
+     * @param options
+     * @return
+     * @throws KrbException
+     */
+    public TgtTicket requestTgtTicket(String principal, String password,
+                                      KrbOptions options) throws KrbException {
+        if (options == null) options = new KrbOptions();
+
+        AsRequest asRequest = new AsRequestWithPasswd(context);
+        options.add(KrbOption.USER_PASSWD, password);
+        asRequest.setKrbOptions(options);
+        return requestTgtTicket(principal, asRequest);
+    }
+
+    /**
+     * Request a TGT with user x509 certificate credential
+     * @param principal
+     * @param certificate
+     * @param privateKey
+     * @param options
+     * @return
+     * @throws KrbException
+     */
+    public TgtTicket requestTgtTicket(String principal, Certificate certificate,
+                                      PrivateKey privateKey, KrbOptions options) throws KrbException {
+        if (options == null) options = new KrbOptions();
+
+        AsRequestWithCert asRequest = new AsRequestWithCert(context);
+        options.add(KrbOption.PKINIT_X509_CERTIFICATE, certificate);
+        options.add(KrbOption.PKINIT_X509_PRIVATE_KEY, privateKey);
+        asRequest.setKrbOptions(options);
+        return requestTgtTicket(principal, asRequest);
+    }
+
+    /**
+     * Request a TGT with using Anonymous PKINIT
+     * @param options
+     * @return
+     * @throws KrbException
+     */
+    public TgtTicket requestTgtTicket(KrbOptions options) throws KrbException {
+        if (options == null) options = new KrbOptions();
+
+        AsRequestWithCert asRequest = new AsRequestWithCert(context);
+        options.add(KrbOption.PKINIT_X509_ANONYMOUS);
+        asRequest.setKrbOptions(options);
+
+        String principal = AsRequestWithCert.ANONYMOUS_PRINCIPAL;
+        return requestTgtTicket(principal, asRequest);
+    }
+
+    /**
+     * Request a TGT with user token credential
+     * @param principal
+     * @param token
+     * @param options
+     * @return
+     * @throws KrbException
+     */
+    public TgtTicket requestTgtTicket(String principal, KerbToken token,
+                                      KrbOptions options) throws KrbException {
+        if (options == null) options = new KrbOptions();
+
+        AsRequestWithToken asRequest = new AsRequestWithToken(context);
+        options.add(KrbOption.TOKEN_USER_ID_TOKEN, token);
+        asRequest.setKrbOptions(options);
+        return requestTgtTicket(principal, asRequest);
+    }
+
+    /**
+     * Request a service ticket targeting for a server with user plain credentials
+     * @param clientPrincipal
+     * @param password
+     * @param serverPrincipal
+     * @param options
+     * @return
+     * @throws KrbException
+     */
+    public ServiceTicket requestServiceTicket(String clientPrincipal, String password,
+                                              String serverPrincipal, KrbOptions options) throws KrbException {
+        if (options == null) options = new KrbOptions();
+
+        TgtTicket tgt = requestTgtTicket(clientPrincipal, password, options);
+        return requestServiceTicket(tgt, serverPrincipal, options);
+    }
+
+    /**
+     * Request a service ticket targeting for a server with an user Access Token
+     * @param clientPrincipal
+     * @param token
+     * @param serverPrincipal
+     * @param options
+     * @return
+     * @throws KrbException
+     */
+    public ServiceTicket requestServiceTicket(String clientPrincipal, KerbToken token,
+                                              String serverPrincipal, KrbOptions options) throws KrbException {
+        if (options == null) options = new KrbOptions();
+
+        TgtTicket tgt = requestTgtTicket(clientPrincipal, token, options);
+        return requestServiceTicket(tgt, serverPrincipal, options);
+    }
+
+    private TgtTicket requestTgtTicket(String clientPrincipal, AsRequest tgtTktReq) throws KrbException {
+        tgtTktReq.setClientPrincipal(new PrincipalName(clientPrincipal));
+        tgtTktReq.setTransport(transport);
+
+        try {
+            return doRequestTgtTicket(tgtTktReq);
+        } catch(KrbErrorException e) {
+            KrbError krbError = e.getKrbError();
+            if (krbError.getErrorCode() == KrbErrorCode.KDC_ERR_PREAUTH_REQUIRED) {
+                try {
+                    tgtTktReq.setEncryptionTypes(KrbErrorUtil.getEtypes(krbError));
+                } catch (IOException ioe) {
+                    throw new KrbException("Failed to decode and get etypes from krbError", ioe);
+                }
+                tgtTktReq.getPreauthContext().setPreauthRequired(true);
+                return requestTgtTicket(clientPrincipal, tgtTktReq);
+            }
+            throw e;
+        }
+    }
+
+    private TgtTicket doRequestTgtTicket(AsRequest tgtTktReq) throws KrbException {
+        eventHub.dispatch(KrbClientEvent.createTgtIntentEvent(tgtTktReq));
+        Event resultEvent = null;
+        try {
+            resultEvent = eventWaiter.waitEvent(KrbClientEventType.TGT_RESULT,
+                    context.getTimeout(), TimeUnit.SECONDS);
+        } catch (TimeoutException e) {
+            throw new KrbException("Network timeout", e);
+        }
+        AsRequest asResponse = (AsRequest) resultEvent.getEventData();
+
+        return asResponse.getTicket();
+    }
+
+    /**
+     * Request a service ticket with a TGT targeting for a server
+     * @param tgt
+     * @param serverPrincipal
+     * @return
+     * @throws KrbException
+     */
+    public ServiceTicket requestServiceTicket(TgtTicket tgt, String serverPrincipal,
+                                              KrbOptions options) throws KrbException {
+        if (options == null) options = new KrbOptions();
+
+        TgsRequest ticketReq = new TgsRequest(context, tgt);
+        ticketReq.setServerPrincipal(new PrincipalName(serverPrincipal));
+        ticketReq.setTransport(transport);
+
+        eventHub.dispatch(KrbClientEvent.createTktIntentEvent(ticketReq));
+        Event resultEvent = null;
+        try {
+            resultEvent = eventWaiter.waitEvent(KrbClientEventType.TKT_RESULT,
+                    context.getTimeout(), TimeUnit.SECONDS);
+        } catch (TimeoutException e) {
+            throw new KrbException("Network timeout", e);
+        }
+        TgsRequest tgsResponse = (TgsRequest) resultEvent.getEventData();
+
+        return tgsResponse.getServiceTicket();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbConfig.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbConfig.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbConfig.java
new file mode 100644
index 0000000..57daf19
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbConfig.java
@@ -0,0 +1,161 @@
+/**
+ *  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;
+
+import org.apache.haox.config.Conf;
+import org.apache.kerby.kerberos.kerb.common.KrbConfHelper;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionType;
+
+import java.util.List;
+
+public class KrbConfig {
+    protected Conf conf;
+
+    public KrbConfig() {
+        this.conf = new Conf();
+    }
+
+    public Conf getConf() {
+        return this.conf;
+    }
+
+    public boolean enableDebug() {
+        return conf.getBoolean(KrbConfigKey.KRB_DEBUG);
+    }
+
+    public String getKdcHost() {
+        return conf.getString(KrbConfigKey.KDC_HOST);
+    }
+
+    public short getKdcPort() {
+        Integer kdcPort = conf.getInt(KrbConfigKey.KDC_PORT);
+        return kdcPort.shortValue();
+    }
+
+    public String getKdcRealm() {
+        return conf.getString(KrbConfigKey.KDC_REALM);
+    }
+
+    public String getKdcDomain() {
+        return conf.getString(KrbConfigKey.KDC_DOMAIN);
+    }
+
+    public boolean isPreauthRequired() {
+        return conf.getBoolean(KrbConfigKey.PREAUTH_REQUIRED);
+    }
+
+    public String getTgsPrincipal() {
+        return conf.getString(KrbConfigKey.TGS_PRINCIPAL);
+    }
+
+    public long getAllowableClockSkew() {
+        return KrbConfHelper.getLongUnderSection(conf, KrbConfigKey.CLOCKSKEW);
+    }
+
+    public boolean isEmptyAddressesAllowed() {
+        return conf.getBoolean(KrbConfigKey.EMPTY_ADDRESSES_ALLOWED);
+    }
+
+    public boolean isForwardableAllowed() {
+        return KrbConfHelper.getBooleanUnderSection(conf, KrbConfigKey.FORWARDABLE);
+    }
+
+    public boolean isPostdatedAllowed() {
+        return conf.getBoolean(KrbConfigKey.POSTDATED_ALLOWED);
+    }
+
+    public boolean isProxiableAllowed() {
+        return KrbConfHelper.getBooleanUnderSection(conf, KrbConfigKey.PROXIABLE);
+    }
+
+    public boolean isRenewableAllowed() {
+        return conf.getBoolean(KrbConfigKey.RENEWABLE_ALLOWED);
+    }
+
+    public long getMaximumRenewableLifetime() {
+        return conf.getLong(KrbConfigKey.MAXIMUM_RENEWABLE_LIFETIME);
+    }
+
+    public long getMaximumTicketLifetime() {
+        return conf.getLong(KrbConfigKey.MAXIMUM_TICKET_LIFETIME);
+    }
+
+    public long getMinimumTicketLifetime() {
+        return conf.getLong(KrbConfigKey.MINIMUM_TICKET_LIFETIME);
+    }
+
+    public List<EncryptionType> getEncryptionTypes() {
+        return KrbConfHelper.getEncTypesUnderSection(conf, KrbConfigKey.PERMITTED_ENCTYPES);
+    }
+
+    public boolean isPaEncTimestampRequired() {
+        return conf.getBoolean(KrbConfigKey.PA_ENC_TIMESTAMP_REQUIRED);
+    }
+
+    public boolean isBodyChecksumVerified() {
+        return conf.getBoolean(KrbConfigKey.VERIFY_BODY_CHECKSUM);
+    }
+
+    public String getDefaultRealm() {
+        return KrbConfHelper.getStringUnderSection(conf, KrbConfigKey.DEFAULT_REALM);
+    }
+
+    public boolean getDnsLookUpKdc() {
+        return KrbConfHelper.getBooleanUnderSection(conf, KrbConfigKey.DNS_LOOKUP_KDC);
+    }
+
+    public boolean getDnsLookUpRealm() {
+        return KrbConfHelper.getBooleanUnderSection(conf, KrbConfigKey.DNS_LOOKUP_REALM);
+    }
+
+    public boolean getAllowWeakCrypto() {
+        return KrbConfHelper.getBooleanUnderSection(conf, KrbConfigKey.ALLOW_WEAK_CRYPTO);
+    }
+
+    public long getTicketLifetime() {
+        return KrbConfHelper.getLongUnderSection(conf, KrbConfigKey.TICKET_LIFETIME);
+    }
+
+    public long getRenewLifetime() {
+        return KrbConfHelper.getLongUnderSection(conf, KrbConfigKey.RENEW_LIFETIME);
+    }
+
+    public List<EncryptionType> getDefaultTgsEnctypes() {
+        return KrbConfHelper.getEncTypesUnderSection(conf, KrbConfigKey.DEFAULT_TGS_ENCTYPES);
+    }
+
+    public List<EncryptionType> getDefaultTktEnctypes() {
+        return KrbConfHelper.getEncTypesUnderSection(conf, KrbConfigKey.DEFAULT_TKT_ENCTYPES);
+    }
+
+    public String getDefaultLoggingLocation() {
+        return KrbConfHelper.getStringUnderSection(conf, KrbConfigKey.DEFAULT);
+    }
+
+    public String getKdcLoggingLocation() {
+        return KrbConfHelper.getStringUnderSection(conf, KrbConfigKey.KDC);
+    }
+
+    public String getAdminLoggingLocation() {
+        return KrbConfHelper.getStringUnderSection(conf, KrbConfigKey.ADMIN_SERVER);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbConfigKey.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbConfigKey.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbConfigKey.java
new file mode 100644
index 0000000..111cc67
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbConfigKey.java
@@ -0,0 +1,100 @@
+/**
+ *  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;
+
+import org.apache.kerby.kerberos.kerb.common.SectionConfigKey;
+
+public enum KrbConfigKey implements SectionConfigKey {
+    KRB_DEBUG(true),
+    KDC_HOST("localhost"),
+    KDC_PORT(8015),
+    KDC_DOMAIN("example.com"),
+    KDC_REALM("EXAMPLE.COM"),
+    TGS_PRINCIPAL("krbtgt@EXAMPLE.COM"),
+    PREAUTH_REQUIRED(true),
+    CLOCKSKEW(5 * 60L, "libdefaults"),
+    EMPTY_ADDRESSES_ALLOWED(true),
+    PA_ENC_TIMESTAMP_REQUIRED(true),
+    MAXIMUM_TICKET_LIFETIME(24 * 3600L),
+    MINIMUM_TICKET_LIFETIME(1 * 3600L),
+    MAXIMUM_RENEWABLE_LIFETIME(48 * 3600L),
+    FORWARDABLE(true, "libdefaults"),
+    POSTDATED_ALLOWED(true),
+    PROXIABLE(true, "libdefaults"),
+    RENEWABLE_ALLOWED(true),
+    VERIFY_BODY_CHECKSUM(true),
+    PERMITTED_ENCTYPES("aes128-cts-hmac-sha1-96", "libdefaults"),
+    DEFAULT_REALM("EXAMPLE.COM", "libdefaults"),
+    DNS_LOOKUP_KDC(false, "libdefaults"),
+    DNS_LOOKUP_REALM(false, "libdefaults"),
+    ALLOW_WEAK_CRYPTO(true, "libdefaults"),
+    TICKET_LIFETIME(24 * 3600L, "libdefaults"),
+    RENEW_LIFETIME(48 * 3600L, "libdefaults"),
+    DEFAULT_TGS_ENCTYPES("aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 " +
+        "des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac " +
+        "camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4",
+        "libdefaults"),
+    DEFAULT_TKT_ENCTYPES("aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 " +
+        "des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac " +
+        "camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4",
+        "libdefaults"),
+
+    //key for logging location
+    DEFAULT(null, "logging"),
+    KDC(null, "logging"),
+    ADMIN_SERVER(null, "logging");
+
+    private Object defaultValue;
+    /**
+     * The name of a section where a config key is contained in MIT Kerberos config file.
+     */
+    private String sectionName;
+
+    private KrbConfigKey() {
+        this.defaultValue = null;
+    }
+
+    private KrbConfigKey(Object defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    private KrbConfigKey(Object defaultValue, String sectionName) {
+        this(defaultValue);
+        this.sectionName = sectionName;
+    }
+
+    /**
+     * Use the propertyKey, we can get the configuration value from Object Conf.
+     */
+    @Override
+    public String getPropertyKey() {
+        return name().toLowerCase();
+    }
+
+    @Override
+    public Object getDefaultValue() {
+        return this.defaultValue;
+    }
+
+    @Override
+    public String getSectionName() {
+        return sectionName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbContext.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbContext.java
new file mode 100644
index 0000000..279c486
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbContext.java
@@ -0,0 +1,97 @@
+/**
+ *  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;
+
+import org.apache.kerby.kerberos.kerb.client.preauth.PreauthHandler;
+import org.apache.kerby.kerberos.kerb.crypto.Nonce;
+
+public class KrbContext {
+
+    private String kdcRealm;
+    private KrbConfig config;
+    private String kdcHost;
+    private short kdcPort;
+    private long timeout = 10L;
+    private PreauthHandler preauthHandler;
+
+    public void init(KrbConfig config) {
+        this.config = config;
+        preauthHandler = new PreauthHandler();
+        preauthHandler.init(this);
+    }
+
+    public String getKdcHost() {
+        if (kdcHost != null) {
+            return kdcHost;
+        }
+        return config.getKdcHost();
+    }
+
+    public void setKdcHost(String kdcHost) {
+        this.kdcHost = kdcHost;
+    }
+
+    public short getKdcPort() {
+        if (kdcPort > 0) {
+            return kdcPort;
+        }
+        return config.getKdcPort();
+    }
+
+    public void setKdcPort(short kdcPort) {
+        this.kdcPort = kdcPort;
+    }
+
+    public void setTimeout(long timeout) {
+        this.timeout = timeout;
+    }
+
+    public long getTimeout() {
+        return this.timeout;
+    }
+
+    public KrbConfig getConfig() {
+        return config;
+    }
+
+    public void setKdcRealm(String realm) {
+        this.kdcRealm = realm;
+    }
+
+    public String getKdcRealm() {
+        if (kdcRealm != null) {
+            return kdcRealm;
+        }
+
+        return config.getKdcRealm();
+    }
+
+    public int generateNonce() {
+        return Nonce.value();
+    }
+
+    public long getTicketValidTime() {
+        return 8 * 60 * 60 * 1000;
+    }
+
+    public PreauthHandler getPreauthHandler() {
+        return preauthHandler;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/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
new file mode 100644
index 0000000..c898d80
--- /dev/null
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java
@@ -0,0 +1,99 @@
+/**
+ *  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;
+
+import org.apache.haox.event.AbstractEventHandler;
+import org.apache.haox.event.Event;
+import org.apache.haox.event.EventType;
+import org.apache.kerby.kerberos.kerb.client.event.KrbClientEvent;
+import org.apache.kerby.kerberos.kerb.client.event.KrbClientEventType;
+import org.apache.kerby.kerberos.kerb.client.preauth.PreauthHandler;
+import org.apache.kerby.kerberos.kerb.client.request.AsRequest;
+import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.client.request.TgsRequest;
+import org.apache.kerby.kerberos.kerb.common.KrbUtil;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.common.KrbMessage;
+import org.apache.kerby.kerberos.kerb.spec.common.KrbMessageType;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcRep;
+import org.apache.kerby.kerberos.kerb.spec.kdc.KdcReq;
+import org.apache.haox.transport.Transport;
+import org.apache.haox.transport.event.MessageEvent;
+import org.apache.haox.transport.event.TransportEventType;
+
+import java.nio.ByteBuffer;
+
+public class KrbHandler extends AbstractEventHandler {
+
+    private KrbContext context;
+    private PreauthHandler preauthHandler;
+
+    public void init(KrbContext context) {
+        this.context = context;
+        preauthHandler = new PreauthHandler();
+        preauthHandler.init(context);
+    }
+
+    @Override
+    public EventType[] getInterestedEvents() {
+        return new EventType[] {
+                TransportEventType.INBOUND_MESSAGE,
+                KrbClientEventType.TGT_INTENT,
+                KrbClientEventType.TKT_INTENT
+        };
+    }
+
+    @Override
+    protected void doHandle(Event event) throws Exception {
+        EventType eventType = event.getEventType();
+
+        if (eventType == KrbClientEventType.TGT_INTENT ||
+                eventType == KrbClientEventType.TKT_INTENT) {
+            KdcRequest kdcRequest = (KdcRequest) event.getEventData();
+            handleKdcRequest(kdcRequest);
+        } else if (event.getEventType() == TransportEventType.INBOUND_MESSAGE) {
+            handleMessage((MessageEvent) event);
+        }
+    }
+
+    protected void handleKdcRequest(KdcRequest kdcRequest) throws KrbException {
+        kdcRequest.process();
+        KdcReq kdcReq = kdcRequest.getKdcReq();
+        Transport transport = kdcRequest.getTransport();
+        transport.setAttachment(kdcRequest);
+        KrbUtil.sendMessage(kdcReq, transport);
+    }
+
+    protected void handleMessage(MessageEvent event) throws Exception {
+        ByteBuffer message = event.getMessage();
+        KrbMessage kdcRep = KrbUtil.decodeMessage(message);
+
+        KrbMessageType messageType = kdcRep.getMsgType();
+        if (messageType == KrbMessageType.AS_REP) {
+            KdcRequest kdcRequest = (KdcRequest) event.getTransport().getAttachment();
+            kdcRequest.processResponse((KdcRep) kdcRep);
+            dispatch(KrbClientEvent.createTgtResultEvent((AsRequest) kdcRequest));
+        } else if (messageType == KrbMessageType.TGS_REP) {
+            KdcRequest kdcRequest = (KdcRequest) event.getTransport().getAttachment();
+            kdcRequest.processResponse((KdcRep) kdcRep);
+            dispatch(KrbClientEvent.createTktResultEvent((TgsRequest) kdcRequest));
+        }
+    }
+}