Merge branch 'master' into jetty-embedded
diff --git a/docs/kerby-checkstyle.xml b/docs/kerby-checkstyle.xml
index 3538cd6..72388df 100644
--- a/docs/kerby-checkstyle.xml
+++ b/docs/kerby-checkstyle.xml
@@ -66,7 +66,7 @@
 
         <!-- Checks for imports                              -->
         <!-- See http://checkstyle.sf.net/config_import.html -->
-        <module name="AvoidStarImport"/>
+        <!--module name="AvoidStarImport"/-->
         <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
         <module name="RedundantImport"/>
         <module name="UnusedImports"/>
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1.java
new file mode 100644
index 0000000..c1f46fc
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1.java
@@ -0,0 +1,95 @@
+/**
+ *  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.Asn1Item;
+import org.apache.kerby.asn1.type.Asn1Type;
+import org.apache.kerby.asn1.util.Asn1Reader1;
+import org.apache.kerby.asn1.util.HexUtil;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * The shortcut API for ASN1 encoding, decoding and dumping.
+ * TO BE WELL DOCUMENTED.
+ */
+public final class Asn1 {
+
+    private Asn1() {
+
+    }
+
+    public static void encode(ByteBuffer buffer, Asn1Type value) {
+        value.encode(buffer);
+    }
+
+    public static byte[] encode(Asn1Type value) {
+        return value.encode();
+    }
+
+    public static Asn1Header decodeHeader(ByteBuffer content) throws IOException {
+        Asn1Reader1 reader = new Asn1Reader1(content);
+        return reader.readHeader();
+    }
+
+    public static Asn1Type decode(byte[] content) throws IOException {
+        return decode(ByteBuffer.wrap(content));
+    }
+
+    public static Asn1Type decode(ByteBuffer content) throws IOException {
+        Asn1Reader1 reader = new Asn1Reader1(content);
+        Asn1Header header = reader.readHeader();
+
+        Asn1Item result = new Asn1Item(header.getTag(), header.getValueBuffer());
+        result.useDefinitiveLength(header.isDefinitiveLength());
+
+        return result;
+    }
+
+    public static void dump(Asn1Type value) {
+        Asn1Dumper dumper = new Asn1Dumper();
+        dumper.dumpType(0, value);
+        String output = dumper.output();
+        System.out.println(output);
+    }
+
+    public static void dump(String hexStr) throws IOException {
+        System.out.println("Dumping data:");
+        System.out.println(hexStr);
+        Asn1Dumper dumper = new Asn1Dumper();
+        byte[] data = HexUtil.hex2bytes(hexStr);
+        dumper.dump(data);
+    }
+
+    public static void dump(byte[] content) throws IOException {
+        String hexStr = HexUtil.bytesToHex(content);
+        System.out.println("Dumping data:");
+        System.out.println(hexStr);
+        Asn1Dumper dumper = new Asn1Dumper();
+        dumper.dump(content);
+    }
+
+    public static void dump(ByteBuffer content) throws IOException {
+        byte[] bytes = new byte[content.remaining()];
+        content.get(bytes);
+        dump(bytes);
+    }
+}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dump.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dump.java
deleted file mode 100644
index b9199fe..0000000
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dump.java
+++ /dev/null
@@ -1,72 +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
- *  
- *    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.Asn1Item;
-import org.apache.kerby.asn1.type.Asn1Simple;
-import org.apache.kerby.asn1.type.Asn1Type;
-
-import java.io.IOException;
-
-public class Asn1Dump {
-
-    public static void dump(byte[] content) throws IOException {
-        String dumped = dumpAsString(content);
-        System.out.println(dumped);
-    }
-
-    public static String dumpAsString(byte[] content) throws IOException {
-        StringBuilder sb = new StringBuilder();
-
-        Asn1InputBuffer buffer = new Asn1InputBuffer(content);
-        Asn1Type value;
-        while (true) {
-            value = buffer.read();
-            if (value == null) {
-                break;
-            }
-            dump(value, sb);
-        }
-
-        return sb.toString();
-    }
-
-    public static String dumpAsString(Asn1Type value) {
-        StringBuilder sb = new StringBuilder();
-        dump(value, sb);
-        return sb.toString();
-    }
-
-    private static void dump(Asn1Type value, StringBuilder buffer) {
-        if (value instanceof Asn1Simple) {
-            buffer.append(((Asn1Simple<?>) value).getValue().toString());
-        } else if (value instanceof Asn1Item) {
-            dump((Asn1Item) value, buffer);
-        }
-    }
-
-    private static void dump(Asn1Item value, StringBuilder buffer) {
-        if (value.isFullyDecoded()) {
-            dump(value.getValue(), buffer);
-        } else {
-            buffer.append("Asn1Item");
-        }
-    }
-}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1EnumType.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumpable.java
similarity index 84%
copy from kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1EnumType.java
copy to kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumpable.java
index 7210aee..d4ae6d9 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1EnumType.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumpable.java
@@ -17,11 +17,10 @@
  *  under the License.
  *
  */
-package org.apache.kerby.asn1.type;
+package org.apache.kerby.asn1;
 
-/**
- * A helper interface used by Asn1Enumerated.
- */
-public interface Asn1EnumType {
-    int getValue();
+public interface Asn1Dumpable {
+
+    void dumpWith(Asn1Dumper dumper, int indents);
+
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumper.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumper.java
new file mode 100644
index 0000000..739e59d
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Dumper.java
@@ -0,0 +1,91 @@
+/**
+ *  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.Asn1Simple;
+import org.apache.kerby.asn1.type.Asn1Type;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public final class Asn1Dumper {
+
+    private StringBuilder builder = new StringBuilder();
+
+    public String output() {
+        return builder.toString();
+    }
+
+    public void dump(byte[] content) throws IOException {
+        dump(ByteBuffer.wrap(content));
+    }
+
+    public void dump(ByteBuffer content) throws IOException {
+        Asn1Type value = Asn1.decode(content);
+        if (value == null) {
+            return;
+        }
+
+        dumpType(0, value);
+    }
+
+    public void dumpType(Asn1Type value) {
+        dumpType(0, value);
+    }
+
+    public void dumpType(int indents, Asn1Type value) {
+        if (value == null) {
+            indent(indents).append("null");
+        } else if (value instanceof Asn1Simple) {
+            indent(indents).append(value.toString());
+        } else if (value instanceof Asn1Dumpable) {
+            Asn1Dumpable dumpable = (Asn1Dumpable) value;
+            dumpable.dumpWith(this, indents);
+        } else {
+            append("<UNKNOWN>");
+        }
+    }
+
+    public Asn1Dumper indent(int numSpaces) {
+        for (int i = 0; i < numSpaces; i++) {
+            builder.append(' ');
+        }
+        return this;
+    }
+
+    public Asn1Dumper append(Asn1Simple<?> simpleValue) {
+        if (simpleValue != null) {
+            builder.append(simpleValue.toString());
+        } else {
+            builder.append("null");
+        }
+        return this;
+    }
+
+    public Asn1Dumper append(String string) {
+        builder.append(string);
+        return this;
+    }
+
+    public Asn1Dumper newLine() {
+        builder.append("\n");
+        return this;
+    }
+}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1FieldInfo.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1FieldInfo.java
index 9efa6a5..89fc2f6 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1FieldInfo.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1FieldInfo.java
@@ -25,7 +25,7 @@
  * Representing a field in a ASN1 collection or choice.
  */
 public class Asn1FieldInfo {
-    private int index;
+    private EnumType index;
     private int tagNo = -1; // Indicate a non-tagged field
     private boolean isImplicit;
     private Class<? extends Asn1Type> type;
@@ -36,9 +36,9 @@
      * @param type
      * @param isImplicit
      */
-    public Asn1FieldInfo(int index, Class<? extends Asn1Type> type,
+    public Asn1FieldInfo(EnumType index, Class<? extends Asn1Type> type,
                          boolean isImplicit) {
-        this(index, index, type, isImplicit);
+        this(index, index.getValue(), type, isImplicit);
     }
 
     /**
@@ -48,7 +48,7 @@
      * @param type
      * @param isImplicit
      */
-    public Asn1FieldInfo(int index, int tagNo, Class<? extends Asn1Type> type,
+    public Asn1FieldInfo(EnumType index, int tagNo, Class<? extends Asn1Type> type,
                          boolean isImplicit) {
         this.index = index;
         this.tagNo = tagNo;
@@ -61,7 +61,7 @@
      * @param index
      * @param type
      */
-    public Asn1FieldInfo(int index, Class<? extends Asn1Type> type) {
+    public Asn1FieldInfo(EnumType index, Class<? extends Asn1Type> type) {
         this.index = index;
         this.type = type;
         this.tagNo = -1; // Indicate a non-tagged field
@@ -83,7 +83,7 @@
         return tagNo;
     }
 
-    public int getIndex() {
+    public EnumType getIndex() {
         return index;
     }
 
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Header.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Header.java
new file mode 100644
index 0000000..0fbd047
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Header.java
@@ -0,0 +1,54 @@
+/**
+ *  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;
+
+public class Asn1Header {
+    private Tag tag;
+    private int length;
+    private ByteBuffer valueBuffer;
+
+    public Asn1Header(Tag tag, int length, ByteBuffer valueBuffer) {
+        this.tag = tag;
+        this.length = length;
+        this.valueBuffer = valueBuffer;
+    }
+
+    public Tag getTag() {
+        return tag;
+    }
+
+    public int getLength() {
+        return length;
+    }
+
+    public ByteBuffer getValueBuffer() {
+        return valueBuffer;
+    }
+
+    public boolean isEOC() {
+        return length == 0 && tag.isEOC();
+    }
+
+    public boolean isDefinitiveLength() {
+        return length != -1;
+    }
+}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1InputBuffer.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1InputBuffer.java
deleted file mode 100644
index 62a7d75..0000000
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1InputBuffer.java
+++ /dev/null
@@ -1,74 +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
- *  
- *    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.Asn1Item;
-import org.apache.kerby.asn1.type.Asn1Object;
-import org.apache.kerby.asn1.type.Asn1Type;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * Asn1 decoder. Given an input stream, it validates and parses
- * according to ASN1 spec, and the resultant object can be read
- * and read until exhausted.
- */
-public class Asn1InputBuffer {
-    private final ByteBuffer decodeBuffer;
-
-    /**
-     * Constructor with bytes.
-     * @param bytes The bytes
-     */
-    public Asn1InputBuffer(byte[] bytes) {
-        this(ByteBuffer.wrap(bytes));
-    }
-
-    /**
-     * Constructor with a ByteBuffer.
-     * @param byteBuffer The byte buffer
-     */
-    public Asn1InputBuffer(ByteBuffer byteBuffer) {
-        this.decodeBuffer = byteBuffer;
-    }
-
-    /**
-     * Parse and read ASN1 object from the stream. If it's already
-     * exhausted then null will be returned to indicate the end.
-     * @return an ASN1 object if available otherwise null
-     * @throws IOException e
-     */
-    public Asn1Type read() throws IOException {
-        if (decodeBuffer.remaining() < 1) {
-            return null;
-        }
-        Asn1Item one = Asn1Object.decodeOne(decodeBuffer);
-        if (one.isSimple()) {
-            one.decodeValueAsSimple();
-        } else if (one.isCollection()) {
-            one.decodeValueAsCollection();
-        }
-        if (one.isFullyDecoded()) {
-            return one.getValue();
-        }
-        return one;
-    }
-}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1OutputBuffer.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1OutputBuffer.java
deleted file mode 100644
index 729e042..0000000
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1OutputBuffer.java
+++ /dev/null
@@ -1,67 +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
- *  
- *    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.Asn1Object;
-import org.apache.kerby.asn1.type.Asn1Type;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Asn1 encoder
- */
-public class Asn1OutputBuffer {
-    private List<Asn1Type> objects;
-
-    public Asn1OutputBuffer() {
-        this.objects = new ArrayList<Asn1Type>(3);
-    }
-
-    public void write(Asn1Type value) {
-        objects.add(value);
-    }
-
-    public ByteBuffer getOutput() {
-        int len = encodingLength();
-        ByteBuffer byteBuffer = ByteBuffer.allocate(len);
-        encode(byteBuffer);
-        return byteBuffer;
-    }
-
-    private int encodingLength() {
-        int allLen = 0;
-        for (Asn1Type item : objects) {
-            if (item != null) {
-                allLen += ((Asn1Object) item).encodingLength();
-            }
-        }
-        return allLen;
-    }
-
-    private void encode(ByteBuffer buffer) {
-        for (Asn1Type item : objects) {
-            if (item != null) {
-                item.encode(buffer);
-            }
-        }
-    }
-}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Util.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Util.java
deleted file mode 100644
index caa50f3..0000000
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1Util.java
+++ /dev/null
@@ -1,198 +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
- *  
- *    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.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * The abstract ASN1 object for all the ASN1 types. It provides basic
- * encoding and decoding utilities.
- */
-public final class Asn1Util {
-    private Asn1Util() {
-        
-    }
-
-    public static int lengthOfBodyLength(int bodyLength) {
-        int length = 1;
-
-        if (bodyLength > 127) {
-            int payload = bodyLength;
-            while (payload != 0) {
-                payload >>= 8;
-                length++;
-            }
-        }
-
-        return length;
-    }
-
-    public static int lengthOfTagLength(int tagNo) {
-        int length = 1;
-
-        if (tagNo >= 31) {
-            if (tagNo < 128) {
-                length++;
-            } else {
-                length++;
-
-                do {
-                    tagNo >>= 7;
-                    length++;
-                } while (tagNo > 127);
-            }
-        }
-
-        return length;
-    }
-
-    public static void encodeTag(ByteBuffer buffer, Tag tag) {
-        int flags = tag.tagFlags();
-        int tagNo = tag.tagNo();
-
-        if (tagNo < 31) {
-            buffer.put((byte) (flags | tagNo));
-        } else {
-            buffer.put((byte) (flags | 0x1f));
-            if (tagNo < 128) {
-                buffer.put((byte) tagNo);
-            } else {
-                byte[] tmpBytes = new byte[5]; // 5 * 7 > 32
-                int iPut = tmpBytes.length;
-
-                tmpBytes[--iPut] = (byte) (tagNo & 0x7f);
-                do {
-                    tagNo >>= 7;
-                    tmpBytes[--iPut] = (byte) (tagNo & 0x7f | 0x80);
-                } while (tagNo > 127);
-
-                buffer.put(tmpBytes, iPut, tmpBytes.length - iPut);
-            }
-        }
-    }
-
-    public static void encodeLength(ByteBuffer buffer, int bodyLength) {
-        if (bodyLength < 128) {
-            buffer.put((byte) bodyLength);
-        } else {
-            int length = 0;
-            int payload = bodyLength;
-
-            while (payload != 0) {
-                payload >>= 8;
-                length++;
-            }
-
-            buffer.put((byte) (length | 0x80));
-
-            payload = bodyLength;
-            for (int i = length - 1; i >= 0; i--) {
-                buffer.put((byte) (payload >> (i * 8)));
-            }
-        }
-    }
-
-    public static Tag readTag(ByteBuffer buffer) throws IOException {
-        int tagFlags = readTagFlags(buffer);
-        int tagNo = readTagNo(buffer, tagFlags);
-        return new Tag(tagFlags, tagNo);
-    }
-
-    private static int readTagFlags(ByteBuffer buffer) throws IOException {
-        int tagFlags = buffer.get() & 0xff;
-        if (tagFlags == 0) {
-            throw new IOException("Bad tag 0 found");
-        }
-        return tagFlags;
-    }
-
-    private static int readTagNo(ByteBuffer buffer, int tagFlags) throws IOException {
-        int tagNo = tagFlags & 0x1f;
-
-        if (tagNo == 0x1f) {
-            tagNo = 0;
-
-            int b = buffer.get() & 0xff;
-            if ((b & 0x7f) == 0) {
-                throw new IOException("Invalid high tag number found");
-            }
-
-            while (b >= 0 && (b & 0x80) != 0) {
-                tagNo |= b & 0x7f;
-                tagNo <<= 7;
-                b = buffer.get();
-            }
-
-            tagNo |= b & 0x7f;
-        }
-
-        return tagNo;
-    }
-
-    public static int readLength(ByteBuffer buffer) throws IOException {
-        int result = buffer.get() & 0xff;
-        if (result == 0x80) {
-            return -1; // non-definitive length
-        }
-
-        if (result > 127) {
-            int length = result & 0x7f;
-            if (length > 4) {
-                throw new IOException("Bad length of more than 4 bytes: " + length);
-            }
-
-            result = 0;
-            int tmp;
-            for (int i = 0; i < length; i++) {
-                tmp = buffer.get() & 0xff;
-                result = (result << 8) + tmp;
-            }
-        }
-
-        if (result < 0) {
-            throw new IOException("Invalid length " + result);
-        }
-
-        if (result > buffer.remaining()) {
-            throw new IOException("Corrupt stream - less data "
-                + buffer.remaining() + " than expected " + result);
-        }
-
-        return result;
-    }
-
-    public static ByteBuffer dupWithLength(ByteBuffer buffer, int length) {
-        try {
-            ByteBuffer result = buffer.duplicate();
-            result.limit(buffer.position() + length);
-            buffer.position(buffer.position() + length);
-            return result;
-        } catch (Exception e) {
-            throw e;
-        }
-    }
-
-    public static byte[] readAllLeftBytes(ByteBuffer buffer) {
-        byte[] result = new byte[buffer.remaining()];
-        buffer.get(result);
-        return result;
-    }
-}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1EnumType.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/EnumType.java
similarity index 91%
rename from kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1EnumType.java
rename to kerby-asn1/src/main/java/org/apache/kerby/asn1/EnumType.java
index 7210aee..9b59f70 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1EnumType.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/EnumType.java
@@ -17,11 +17,12 @@
  *  under the License.
  *
  */
-package org.apache.kerby.asn1.type;
+package org.apache.kerby.asn1;
 
 /**
  * A helper interface used by Asn1Enumerated.
  */
-public interface Asn1EnumType {
+public interface EnumType {
     int getValue();
+    String getName();
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/ExplicitField.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/ExplicitField.java
index 85fded1..7142dc0 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/ExplicitField.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/ExplicitField.java
@@ -31,7 +31,7 @@
      * @param index
      * @param type
      */
-    public ExplicitField(int index, int tagNo, Class<? extends Asn1Type> type) {
+    public ExplicitField(EnumType index, int tagNo, Class<? extends Asn1Type> type) {
         super(index, tagNo, type, false);
     }
 
@@ -40,7 +40,7 @@
      * @param index
      * @param type
      */
-    public ExplicitField(int index, Class<? extends Asn1Type> type) {
-        super(index, index, type, false);
+    public ExplicitField(EnumType index, Class<? extends Asn1Type> type) {
+        super(index, index.getValue(), type, false);
     }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/ImplicitField.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/ImplicitField.java
index a0e7acb..f488847 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/ImplicitField.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/ImplicitField.java
@@ -31,7 +31,7 @@
      * @param index
      * @param type
      */
-    public ImplicitField(int index, int tagNo, Class<? extends Asn1Type> type) {
+    public ImplicitField(EnumType index, int tagNo, Class<? extends Asn1Type> type) {
         super(index, tagNo, type, true);
     }
 
@@ -40,7 +40,7 @@
      * @param index
      * @param type
      */
-    public ImplicitField(int index, Class<? extends Asn1Type> type) {
-        super(index, index, type, true);
+    public ImplicitField(EnumType index, Class<? extends Asn1Type> type) {
+        super(index, index.getValue(), type, true);
     }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Tag.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Tag.java
index bea843f..2cf5e6b 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Tag.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Tag.java
@@ -81,6 +81,10 @@
         return UniversalTag.UNKNOWN;
     }
 
+    public boolean isEOC() {
+        return universalTag() == UniversalTag.EOC;
+    }
+
     public boolean isUniversal() {
         return tagClass().isUniversal();
     }
@@ -124,10 +128,7 @@
 
     @Override
     public String toString() {
-        return "Tag["
-            + "tagFlags=" + tagFlags
-            + ", tagNo=" + tagNo
-            + ']';
+        return tagNo >= 0x1F ? "N/A" : "" + (tagFlags | tagNo);
     }
 
     public static Tag newAppTag(int tagNo) {
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 e78b50e..63abbee 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
@@ -28,7 +28,7 @@
     UNKNOWN             (-1),
     CHOICE              (-2),   // Only for internal using
     ANY                 (-3),   // Only for internal using
-    BER_UNDEFINED_LENGTH(0),    // Used to encode undefined length with BER
+    EOC                 (0),    // End of content, use by BER
     BOOLEAN             (0x01),
     INTEGER             (0x02),
     BIT_STRING          (0x03),
@@ -87,7 +87,7 @@
      */
     public static UniversalTag fromValue(int value) {
         switch (value) {
-            case 0x00 : return BER_UNDEFINED_LENGTH;
+            case 0x00 : return EOC;
             case 0x01 : return BOOLEAN;
             case 0x02 : return INTEGER;
             case 0x03 : return BIT_STRING;
@@ -122,4 +122,10 @@
             default : return UNKNOWN;
         }
     }
+
+    public String toStr() {
+        String typeStr = toString();
+        typeStr = typeStr.replace('_', ' ');
+        return typeStr.toLowerCase();
+    }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java
index 7d26be3..70c07ca 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1BitString.java
@@ -82,4 +82,11 @@
             throw new IOException("Bad padding number: " + paddingBits + ", should be in [0, 7]");
         }
     }
+
+    @Override
+    public String toString() {
+        String valueStr =
+            (getValue() != null ? (getValue().length + " bytes") : "null");
+        return valueStr;
+    }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java
index 91fd54e..e7eb853 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java
@@ -19,7 +19,9 @@
  */
 package org.apache.kerby.asn1.type;
 
+import org.apache.kerby.asn1.Asn1;
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.TaggingOption;
 import org.apache.kerby.asn1.UniversalTag;
 
@@ -73,7 +75,7 @@
     @Override
     public void decode(ByteBuffer content) throws IOException {
         int foundPos = -1;
-        Asn1Item item = decodeOne(content);
+        Asn1Item item = (Asn1Item) Asn1.decode(content);
         for (int i = 0; i < fieldInfos.length; ++i) {
             if (item.isContextSpecific()) {
                 if (fieldInfos[i].getTagNo() == item.tagNo()) {
@@ -118,16 +120,16 @@
         }
     }
 
-    protected <T extends Asn1Type> T getFieldAs(int index, Class<T> t) {
-        Asn1Type value = fields[index];
+    protected <T extends Asn1Type> T getFieldAs(EnumType index, Class<T> t) {
+        Asn1Type value = fields[index.getValue()];
         if (value == null) {
             return null;
         }
         return (T) value;
     }
 
-    protected void setFieldAs(int index, Asn1Type value) {
-        fields[index] = value;
+    protected void setFieldAs(EnumType index, Asn1Type value) {
+        fields[index.getValue()] = value;
     }
 
     protected String getFieldAsString(int index) {
@@ -143,7 +145,7 @@
         throw new RuntimeException("The targeted field type isn't of string");
     }
 
-    protected byte[] getFieldAsOctets(int index) {
+    protected byte[] getFieldAsOctets(EnumType index) {
         Asn1OctetString value = getFieldAs(index, Asn1OctetString.class);
         if (value != null) {
             return value.getValue();
@@ -151,12 +153,12 @@
         return null;
     }
 
-    protected void setFieldAsOctets(int index, byte[] bytes) {
+    protected void setFieldAsOctets(EnumType index, byte[] bytes) {
         Asn1OctetString value = new Asn1OctetString(bytes);
         setFieldAs(index, value);
     }
 
-    protected Integer getFieldAsInteger(int index) {
+    protected Integer getFieldAsInteger(EnumType index) {
         Asn1Integer value = getFieldAs(index, Asn1Integer.class);
         if (value != null) {
             return value.getValue().intValue();
@@ -164,7 +166,7 @@
         return null;
     }
 
-    protected void setFieldAsInt(int index, int value) {
+    protected void setFieldAsInt(EnumType index, int value) {
         setFieldAs(index, new Asn1Integer(value));
     }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java
index a4d6560..9cbf89a 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java
@@ -39,8 +39,8 @@
         return isCollection(new Tag(tag));
     }
 
-    public static boolean isCollection(UniversalTag tagNo) {
-        switch (tagNo) {
+    public static boolean isCollection(UniversalTag universalTag) {
+        switch (universalTag) {
             case SEQUENCE:
             case SEQUENCE_OF:
             case SET:
@@ -51,19 +51,19 @@
         }
     }
 
-    public static Asn1Type createCollection(int tagNo) {
-        if (!isCollection(tagNo)) {
-            throw new IllegalArgumentException("Not collection type, tag: " + tagNo);
+    public static Asn1Collection createCollection(Tag tag) {
+        if (!isCollection(tag)) {
+            throw new IllegalArgumentException("Not collection type, tag: " + tag);
         }
-        return createCollection(UniversalTag.fromValue(tagNo));
+        return createCollection(tag.universalTag());
     }
 
-    public static Asn1Type createCollection(UniversalTag tagNo) {
-        if (!isCollection(tagNo)) {
-            throw new IllegalArgumentException("Not collection type, tag: " + tagNo);
+    public static Asn1Collection createCollection(UniversalTag universalTag) {
+        if (!isCollection(universalTag)) {
+            throw new IllegalArgumentException("Not collection type, tag: " + universalTag);
         }
 
-        switch (tagNo) {
+        switch (universalTag) {
             case SEQUENCE:
                 return new Asn1Sequence();
             case SEQUENCE_OF:
@@ -73,7 +73,7 @@
             case SET_OF:
                 return new Asn1Set();
             default:
-                throw new IllegalArgumentException("Unexpected tag " + tagNo.getValue());
+                throw new IllegalArgumentException("Unexpected tag " + universalTag.getValue());
         }
     }
 }
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 3226441..36082c4 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
@@ -19,7 +19,10 @@
  */
 package org.apache.kerby.asn1.type;
 
+import org.apache.kerby.asn1.Asn1Dumpable;
+import org.apache.kerby.asn1.Asn1Dumper;
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.TaggingOption;
 import org.apache.kerby.asn1.UniversalTag;
 
@@ -29,15 +32,17 @@
 /**
  * For collection type that may consist of tagged fields
  */
-public abstract class Asn1CollectionType extends AbstractAsn1Type<Asn1CollectionType> {
-    private Asn1FieldInfo[] fieldInfos;
-    private Asn1Type[] fields;
+public abstract class Asn1CollectionType
+    extends AbstractAsn1Type<Asn1CollectionType> implements Asn1Dumpable {
+    private final Asn1FieldInfo[] fieldInfos;
+    private final Asn1Type[] fields;
 
-    public Asn1CollectionType(UniversalTag universalTag, Asn1FieldInfo[] fieldInfos) {
+    public Asn1CollectionType(UniversalTag universalTag,
+                              final Asn1FieldInfo[] fieldInfos) {
         super(universalTag);
 
         setValue(this);
-        this.fieldInfos = fieldInfos.clone();
+        this.fieldInfos = fieldInfos;
         this.fields = new Asn1Type[fieldInfos.length];
         usePrimitive(false);
     }
@@ -130,20 +135,20 @@
 
     protected abstract Asn1Collection createCollection();
 
-    protected <T extends Asn1Type> T getFieldAs(int index, Class<T> t) {
-        Asn1Type value = fields[index];
+    protected <T extends Asn1Type> T getFieldAs(EnumType index, Class<T> t) {
+        Asn1Type value = fields[index.getValue()];
         if (value == null) {
             return null;
         }
         return (T) value;
     }
 
-    protected void setFieldAs(int index, Asn1Type value) {
-        fields[index] = value;
+    protected void setFieldAs(EnumType index, Asn1Type value) {
+        fields[index.getValue()] = value;
     }
 
-    protected String getFieldAsString(int index) {
-        Asn1Type value = fields[index];
+    protected String getFieldAsString(EnumType index) {
+        Asn1Type value = fields[index.getValue()];
         if (value == null) {
             return null;
         }
@@ -155,7 +160,7 @@
         throw new RuntimeException("The targeted field type isn't of string");
     }
 
-    protected byte[] getFieldAsOctets(int index) {
+    protected byte[] getFieldAsOctets(EnumType index) {
         Asn1OctetString value = getFieldAs(index, Asn1OctetString.class);
         if (value != null) {
             return value.getValue();
@@ -163,12 +168,12 @@
         return null;
     }
 
-    protected void setFieldAsOctets(int index, byte[] bytes) {
+    protected void setFieldAsOctets(EnumType index, byte[] bytes) {
         Asn1OctetString value = new Asn1OctetString(bytes);
         setFieldAs(index, value);
     }
 
-    protected Integer getFieldAsInteger(int index) {
+    protected Integer getFieldAsInteger(EnumType index) {
         Asn1Integer value = getFieldAs(index, Asn1Integer.class);
         if (value != null && value.getValue() != null) {
             return value.getValue().intValue();
@@ -176,12 +181,12 @@
         return null;
     }
 
-    protected void setFieldAsInt(int index, int value) {
+    protected void setFieldAsInt(EnumType index, int value) {
         setFieldAs(index, new Asn1Integer(value));
     }
 
-    protected <T extends Asn1Type> T getFieldAsAny(int index, Class<T> t) {
-        Asn1Type value = fields[index];
+    protected <T extends Asn1Type> T getFieldAsAny(EnumType index, Class<T> t) {
+        Asn1Type value = fields[index.getValue()];
         if (value != null && value instanceof Asn1Any) {
             Asn1Any any = (Asn1Any) value;
             return any.getValueAs(t);
@@ -190,9 +195,32 @@
         return null;
     }
 
-    protected void setFieldAsAny(int index, Asn1Type value) {
+    protected void setFieldAsAny(EnumType index, Asn1Type value) {
         if (value != null) {
             setFieldAs(index, new Asn1Any(value));
         }
     }
+
+    @Override
+    public void dumpWith(Asn1Dumper dumper, int indents) {
+        String type = getClass().getSimpleName();
+
+        dumper.indent(indents).append(type).newLine();
+
+        String fdName;
+        for (int i = 0; i < fieldInfos.length; i++) {
+            fdName = fieldInfos[i].getIndex().getName();
+            fdName = fdName.replace("_", "-").toLowerCase();
+
+            dumper.indent(indents + 4).append(fdName).append(" = ");
+
+            Asn1Type fdValue = fields[i];
+            if (fdValue == null || fdValue instanceof Asn1Simple) {
+                dumper.append((Asn1Simple<?>) fdValue).newLine();
+            } else {
+                dumper.newLine().dumpType(indents + 8, fdValue);
+                dumper.newLine();
+            }
+        }
+    }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Constructed.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Constructed.java
index 46cb6c6..6008282 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Constructed.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Constructed.java
@@ -19,6 +19,7 @@
  */
 package org.apache.kerby.asn1.type;
 
+import org.apache.kerby.asn1.Asn1;
 import org.apache.kerby.asn1.Tag;
 
 import java.io.IOException;
@@ -79,7 +80,7 @@
     @Override
     protected void decodeBody(ByteBuffer content) throws IOException {
         while (content.remaining() > 0) {
-            Asn1Item item = decodeOne(content);
+            Asn1Item item = (Asn1Item) Asn1.decode(content);
             if (item != null) {
                 if (item.isSimple() && !isLazy()) {
                     item.decodeValueAsSimple();
@@ -90,4 +91,17 @@
             }
         }
     }
+
+    @Override
+    public String toString() {
+        String typeStr;
+        if (tag().isUniversal()) {
+            typeStr = tag().universalTag().toStr();
+        } else if (tag().isAppSpecific()) {
+            typeStr = "application " + tagNo();
+        } else {
+            typeStr = "[" + tagNo() + "]";
+        }
+        return typeStr;
+    }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Enumerated.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Enumerated.java
index 8dc4b4a..223fc97 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Enumerated.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Enumerated.java
@@ -19,6 +19,7 @@
  */
 package org.apache.kerby.asn1.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.UniversalTag;
 
 import java.io.IOException;
@@ -27,7 +28,7 @@
 /**
  * The ASN1 enumerated type
  */
-public abstract class Asn1Enumerated<T extends Asn1EnumType> extends Asn1Simple<T> {
+public abstract class Asn1Enumerated<T extends EnumType> extends Asn1Simple<T> {
 
     /**
      * Default constructor, generally for decoding as a container
@@ -52,13 +53,13 @@
     protected void toValue() throws IOException {
         BigInteger biVal = new BigInteger(getBytes());
         int iVal = biVal.intValue();
-        Asn1EnumType[] allValues = getAllEnumValues();
-        for (Asn1EnumType val : allValues) {
+        EnumType[] allValues = getAllEnumValues();
+        for (EnumType val : allValues) {
             if (val.getValue() == iVal) {
                 setValue((T) val);
             }
         }
     }
 
-    protected abstract Asn1EnumType[] getAllEnumValues();
+    protected abstract EnumType[] getAllEnumValues();
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Eoc.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Eoc.java
new file mode 100644
index 0000000..fe80979
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Eoc.java
@@ -0,0 +1,54 @@
+/**
+ *  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.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * To represent Asn1 End Of Content type
+ */
+public final class Asn1Eoc extends Asn1Simple<Object> {
+    public static final Asn1Eoc INSTANCE = new Asn1Eoc();
+    private static final byte[]  EMPTY_BYTES = new byte[0];
+
+    private Asn1Eoc() {
+        super(UniversalTag.EOC, null);
+    }
+
+    @Override
+    protected byte[] encodeBody() {
+        return EMPTY_BYTES;
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        return 0;
+    }
+
+    @Override
+    protected void decodeBody(ByteBuffer content) throws IOException {
+        if (content.remaining() != 0) {
+            throw new IOException("Unexpected bytes found for EOC");
+        }
+    }
+}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Flags.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Flags.java
index 9c219df..f11d6df 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Flags.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Flags.java
@@ -19,6 +19,8 @@
  */
 package org.apache.kerby.asn1.type;
 
+import org.apache.kerby.asn1.EnumType;
+
 import java.io.IOException;
 
 /**
@@ -81,15 +83,15 @@
         setFlags(0);
     }
 
-    public boolean isFlagSet(Asn1EnumType flag) {
+    public boolean isFlagSet(EnumType flag) {
         return isFlagSet(flag.getValue());
     }
 
-    public void setFlag(Asn1EnumType flag) {
+    public void setFlag(EnumType flag) {
         setFlag(flag.getValue());
     }
 
-    public void setFlag(Asn1EnumType flag, boolean isSet)  {
+    public void setFlag(EnumType flag, boolean isSet)  {
         if (isSet) {
             setFlag(flag.getValue());
         } else {
@@ -97,7 +99,7 @@
         }
     }
 
-    public void clearFlag(Asn1EnumType flag) {
+    public void clearFlag(EnumType flag) {
         clearFlag(flag.getValue());
     }
 
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java
index 371553d..f1a4416 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java
@@ -27,11 +27,11 @@
 /**
  * The Asn1 Null type
  */
-public class Asn1Null extends Asn1Simple<Object> {
+public final class Asn1Null extends Asn1Simple<Object> {
     public static final Asn1Null INSTANCE = new Asn1Null();
     private static final byte[]  EMPTY_BYTES = new byte[0];
 
-    public Asn1Null() {
+    private Asn1Null() {
         super(UniversalTag.NULL, null);
     }
 
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Object.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Object.java
index 0a46d37..b4a5b7b 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Object.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Object.java
@@ -19,10 +19,12 @@
  */
 package org.apache.kerby.asn1.type;
 
-import org.apache.kerby.asn1.Asn1Util;
+import org.apache.kerby.asn1.Asn1Header;
 import org.apache.kerby.asn1.Tag;
 import org.apache.kerby.asn1.TaggingOption;
 import org.apache.kerby.asn1.UniversalTag;
+import org.apache.kerby.asn1.util.Asn1Reader1;
+import org.apache.kerby.asn1.util.Asn1Util;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -34,12 +36,12 @@
 public abstract class Asn1Object implements Asn1Type {
     private final Tag tag;
 
-    private int encodingLen = -1;
+    private int bodyLength = -1;
 
     // encoding options
     private EncodingType encodingType = EncodingType.BER;
     private boolean isImplicit = true;
-    private boolean isDefinitiveLength = false;
+    private boolean isDefinitiveLength = true; // by default!!
 
     /**
      * Constructor with a tag
@@ -162,12 +164,22 @@
 
     @Override
     public int encodingLength() {
-        if (encodingLen == -1) {
-            int bodyLen = encodingBodyLength();
-            encodingLen = Asn1Util.lengthOfTagLength(tagNo())
-                + Asn1Util.lengthOfBodyLength(bodyLen) + bodyLen;
+        return encodingHeaderLength() + getBodyLength();
+    }
+
+    private int getBodyLength() {
+        if (bodyLength == -1) {
+            bodyLength = encodingBodyLength();
         }
-        return encodingLen;
+        return bodyLength;
+    }
+
+    protected int encodingHeaderLength() {
+        int bodyLen = getBodyLength();
+        int headerLen = Asn1Util.lengthOfTagLength(tagNo());
+        headerLen += (isDefinitiveLength()
+            ? Asn1Util.lengthOfBodyLength(bodyLen) : 1);
+        return headerLen;
     }
 
     protected boolean isUniversal() {
@@ -198,19 +210,11 @@
 
     @Override
     public void decode(ByteBuffer content) throws IOException {
-        Tag tmpTag = Asn1Util.readTag(content);
-        int length = Asn1Util.readLength(content);
+        Asn1Reader1 reader = new Asn1Reader1(content);
+        Asn1Header header = reader.readHeader();
 
-        ByteBuffer valueBuffer;
-        if (length == -1) {
-            valueBuffer = content;
-            useDefinitiveLength(false);
-        } else {
-            valueBuffer = Asn1Util.dupWithLength(content, length);
-            useDefinitiveLength(true);
-        }
-
-        decode(tmpTag, valueBuffer);
+        useDefinitiveLength(header.isDefinitiveLength());
+        decode(header.getTag(), header.getValueBuffer());
     }
 
     public void decode(Tag tag, ByteBuffer content) throws IOException {
@@ -262,19 +266,11 @@
     @Override
     public void taggedDecode(ByteBuffer content,
                              TaggingOption taggingOption) throws IOException {
-        Tag taggingTag = Asn1Util.readTag(content);
-        int taggingLength = Asn1Util.readLength(content);
+        Asn1Reader1 reader = new Asn1Reader1(content);
+        Asn1Header header = reader.readHeader();
 
-        ByteBuffer valueBuffer;
-        if (taggingLength == -1) {
-            valueBuffer = content;
-            useDefinitiveLength(false);
-        } else {
-            valueBuffer = Asn1Util.dupWithLength(content, taggingLength);
-            useDefinitiveLength(true);
-        }
-
-        taggedDecode(taggingTag, valueBuffer, taggingOption);
+        useDefinitiveLength(header.isDefinitiveLength());
+        taggedDecode(header.getTag(), header.getValueBuffer(), taggingOption);
     }
 
     protected void taggedDecode(Tag taggingTag, ByteBuffer content,
@@ -291,23 +287,4 @@
             decode(content);
         }
     }
-
-    public static Asn1Item decodeOne(ByteBuffer content) throws IOException {
-        Tag tmpTag = Asn1Util.readTag(content);
-        int length = Asn1Util.readLength(content);
-
-        Asn1Item result;
-        ByteBuffer valueBuffer;
-        if (length == -1) {
-            result = new Asn1Item(tmpTag);
-            result.useDefinitiveLength(false);
-            result.setBodyContent(content);
-        } else {
-            valueBuffer = Asn1Util.dupWithLength(content, length);
-            result = new Asn1Item(tmpTag, valueBuffer);
-            result.useDefinitiveLength(true);
-        }
-
-        return result;
-    }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
index 6523cf7..46c9c32 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
@@ -19,8 +19,8 @@
  */
 package org.apache.kerby.asn1.type;
 
-import org.apache.kerby.asn1.Asn1Util;
 import org.apache.kerby.asn1.UniversalTag;
+import org.apache.kerby.asn1.util.Asn1Util;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -48,4 +48,11 @@
     protected void decodeBody(ByteBuffer content) throws IOException {
         setValue(Asn1Util.readAllLeftBytes(content));
     }
+
+    @Override
+    public String toString() {
+        String valueStr =
+            (getValue() != null ? (getValue().length + " octets") : "null");
+        return valueStr;
+    }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
index d55fb7a..4358f65 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.asn1.type;
 
-import org.apache.kerby.asn1.Asn1Util;
 import org.apache.kerby.asn1.Tag;
 import org.apache.kerby.asn1.UniversalTag;
+import org.apache.kerby.asn1.util.Asn1Util;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -201,4 +201,11 @@
                 throw new IllegalArgumentException("Unexpected tag " + tagNo.getValue());
         }
     }
+
+    @Override
+    public String toString() {
+        String valueStr =
+            (getValue() != null ? String.valueOf(getValue()) : "null");
+        return valueStr;
+    }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Tagging.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Tagging.java
index b7ad9d4..8818c98 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Tagging.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Tagging.java
@@ -19,6 +19,8 @@
  */
 package org.apache.kerby.asn1.type;
 
+import org.apache.kerby.asn1.Asn1Dumpable;
+import org.apache.kerby.asn1.Asn1Dumper;
 import org.apache.kerby.asn1.Tag;
 
 import java.io.IOException;
@@ -28,7 +30,8 @@
 /**
  * For tagging any Asn1Type with a tagNo
  */
-public class Asn1Tagging<T extends Asn1Type> extends AbstractAsn1Type<T> {
+public class Asn1Tagging<T extends Asn1Type>
+    extends AbstractAsn1Type<T> implements Asn1Dumpable {
 
     public Asn1Tagging(int tagNo, T value,
                        boolean isAppSpecific, boolean isImplicit) {
@@ -97,4 +100,10 @@
         }
         setValue((T) value);
     }
+
+    @Override
+    public void dumpWith(Asn1Dumper dumper, int indents) {
+        Asn1Type taggedValue = getValue();
+        dumper.dumpType(indents, taggedValue);
+    }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingCollection.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingCollection.java
similarity index 77%
rename from kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingCollection.java
rename to kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingCollection.java
index b6086b8..25dfbf3 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingCollection.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingCollection.java
@@ -19,7 +19,10 @@
  */
 package org.apache.kerby.asn1.type;
 
+import org.apache.kerby.asn1.Asn1Dumpable;
+import org.apache.kerby.asn1.Asn1Dumper;
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.Tag;
 
 import java.io.IOException;
@@ -29,12 +32,14 @@
  * For tagging a collection type with tagNo, either application specific or
  * context specific class
  */
-public abstract class TaggingCollection extends AbstractAsn1Type<Asn1CollectionType> {
+public abstract class Asn1TaggingCollection
+    extends AbstractAsn1Type<Asn1CollectionType> implements Asn1Dumpable {
+
     private Asn1Tagging<Asn1CollectionType> tagging;
     private Asn1CollectionType tagged;
 
-    public TaggingCollection(int taggingTagNo, Asn1FieldInfo[] tags,
-                             boolean isAppSpecific, boolean isImplicit) {
+    public Asn1TaggingCollection(int taggingTagNo, Asn1FieldInfo[] tags,
+                                 boolean isAppSpecific, boolean isImplicit) {
         super(makeTag(isAppSpecific, taggingTagNo));
         this.tagged = createTaggedCollection(tags);
         setValue(tagged);
@@ -134,39 +139,45 @@
         tagging.decodeBody(content);
     }
 
-    protected <T extends Asn1Type> T getFieldAs(int index, Class<T> t) {
+    protected <T extends Asn1Type> T getFieldAs(EnumType index, Class<T> t) {
         return tagged.getFieldAs(index, t);
     }
 
-    protected void setFieldAs(int index, Asn1Type value) {
+    protected void setFieldAs(EnumType index, Asn1Type value) {
         tagged.setFieldAs(index, value);
     }
 
-    protected String getFieldAsString(int index) {
+    protected String getFieldAsString(EnumType index) {
         return tagged.getFieldAsString(index);
     }
 
-    protected byte[] getFieldAsOctets(int index) {
+    protected byte[] getFieldAsOctets(EnumType index) {
         return tagged.getFieldAsOctets(index);
     }
 
-    protected void setFieldAsOctets(int index, byte[] bytes) {
+    protected void setFieldAsOctets(EnumType index, byte[] bytes) {
         tagged.setFieldAsOctets(index, bytes);
     }
 
-    protected Integer getFieldAsInteger(int index) {
+    protected Integer getFieldAsInteger(EnumType index) {
         return tagged.getFieldAsInteger(index);
     }
 
-    protected void setFieldAsInt(int index, int value) {
+    protected void setFieldAsInt(EnumType index, int value) {
         tagged.setFieldAsInt(index, value);
     }
 
-    protected byte[] getFieldAsOctetBytes(int index) {
+    protected byte[] getFieldAsOctetBytes(EnumType index) {
         return tagged.getFieldAsOctets(index);
     }
 
-    protected void setFieldAsOctetBytes(int index, byte[] value) {
+    protected void setFieldAsOctetBytes(EnumType index, byte[] value) {
         tagged.setFieldAsOctets(index, value);
     }
+
+    @Override
+    public void dumpWith(Asn1Dumper dumper, int indents) {
+        Asn1Type taggedValue = getValue();
+        dumper.dumpType(indents, taggedValue);
+    }
 }
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSequence.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingSequence.java
similarity index 85%
rename from kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSequence.java
rename to kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingSequence.java
index 0bd9fbb..61128de 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSequence.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingSequence.java
@@ -24,10 +24,10 @@
 /**
  * For tagging a sequence type with tagNo, either application specific or context specific class
  */
-public class TaggingSequence extends TaggingCollection {
+public class Asn1TaggingSequence extends Asn1TaggingCollection {
 
-    public TaggingSequence(int taggingTagNo, Asn1FieldInfo[] tags,
-                           boolean isAppSpecific, boolean isImplicit) {
+    public Asn1TaggingSequence(int taggingTagNo, Asn1FieldInfo[] tags,
+                               boolean isAppSpecific, boolean isImplicit) {
         super(taggingTagNo, tags, isAppSpecific, isImplicit);
     }
 
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSet.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingSet.java
similarity index 86%
rename from kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSet.java
rename to kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingSet.java
index e13d5f0..e9eb17f 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSet.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingSet.java
@@ -25,10 +25,10 @@
  * For tagging a sequence type with tagNo, either application specific or
  * context specific class
  */
-public class TaggingSet extends TaggingCollection {
+public class Asn1TaggingSet extends Asn1TaggingCollection {
 
-    public TaggingSet(int taggingTagNo, Asn1FieldInfo[] tags,
-                      boolean isAppSpecific, boolean isImplicit) {
+    public Asn1TaggingSet(int taggingTagNo, Asn1FieldInfo[] tags,
+                          boolean isAppSpecific, boolean isImplicit) {
         super(taggingTagNo, tags, isAppSpecific, isImplicit);
     }
 
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Reader.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Reader.java
new file mode 100644
index 0000000..451e8ff
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Reader.java
@@ -0,0 +1,114 @@
+/**
+ *  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.util;
+
+import org.apache.kerby.asn1.Asn1Header;
+import org.apache.kerby.asn1.Tag;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * ASN1 reader from a byte buffer.
+ */
+public abstract class Asn1Reader {
+    protected ByteBuffer buffer;
+
+    public Asn1Reader(ByteBuffer buffer) {
+        this.buffer = buffer;
+    }
+
+    public ByteBuffer getBuffer() {
+        return buffer;
+    }
+
+    public Asn1Header readHeader() throws IOException {
+        Tag tag = readTag();
+        int valueLength = readLength();
+        Asn1Header header = new Asn1Header(tag, valueLength,
+            getValueBuffer(valueLength));
+        return header;
+    }
+
+    protected abstract ByteBuffer getValueBuffer(int valueLength);
+
+    protected abstract byte readByte() throws IOException;
+
+    private Tag readTag() throws IOException {
+        int tagFlags = readTagFlags();
+        int tagNo = readTagNo(tagFlags);
+        return new Tag(tagFlags, tagNo);
+    }
+
+    private int readTagFlags() throws IOException {
+        int tagFlags = readByte() & 0xff;
+        return tagFlags;
+    }
+
+    private int readTagNo(int tagFlags) throws IOException {
+        int tagNo = tagFlags & 0x1f;
+
+        if (tagNo == 0x1f) {
+            tagNo = 0;
+
+            int b = readByte() & 0xff;
+            if ((b & 0x7f) == 0) {
+                throw new IOException("Invalid high tag number found");
+            }
+
+            while (b >= 0 && (b & 0x80) != 0) {
+                tagNo |= b & 0x7f;
+                tagNo <<= 7;
+                b = readByte();
+            }
+
+            tagNo |= b & 0x7f;
+        }
+
+        return tagNo;
+    }
+
+    private int readLength() throws IOException {
+        int result = readByte() & 0xff;
+        if (result == 0x80) {
+            return -1; // non-definitive length
+        }
+
+        if (result > 127) {
+            int length = result & 0x7f;
+            if (length > 4) {
+                throw new IOException("Bad length of more than 4 bytes: " + length);
+            }
+
+            result = 0;
+            int tmp;
+            for (int i = 0; i < length; i++) {
+                tmp = readByte() & 0xff;
+                result = (result << 8) + tmp;
+            }
+        }
+
+        if (result < 0) {
+            throw new IOException("Invalid length " + result);
+        }
+
+        return result;
+    }
+}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Reader1.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Reader1.java
new file mode 100644
index 0000000..f53f99d
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Reader1.java
@@ -0,0 +1,47 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *
+ */
+package org.apache.kerby.asn1.util;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * ASN1 reader for stateful reading.
+ */
+public final class Asn1Reader1 extends Asn1Reader {
+
+    public Asn1Reader1(ByteBuffer buffer) {
+        super(buffer);
+    }
+
+    @Override
+    protected byte readByte() throws IOException {
+        return buffer.get();
+    }
+
+    @Override
+    protected ByteBuffer getValueBuffer(int valueLength) {
+        ByteBuffer result = buffer.duplicate();
+        result.limit(buffer.position() + valueLength);
+        buffer.position(buffer.position() + valueLength);
+
+        return result;
+    }
+}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Reader2.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Reader2.java
new file mode 100644
index 0000000..9351c3f
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Reader2.java
@@ -0,0 +1,62 @@
+/**
+ *  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.util;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * ASN1 reader for positional reading.
+ */
+public final class Asn1Reader2 extends Asn1Reader {
+    private int position;
+
+    public Asn1Reader2(ByteBuffer buffer, int position) {
+        super(buffer);
+        this.position = position;
+    }
+
+    public Asn1Reader2(ByteBuffer buffer) {
+        super(buffer);
+        this.position = buffer.position();
+    }
+
+    public int getPosition() {
+        return position;
+    }
+
+    public void setPosition(int position) {
+        this.position = position;
+    }
+
+    public boolean available() {
+        return position < buffer.limit();
+    }
+
+    @Override
+    protected ByteBuffer getValueBuffer(int valueLength) {
+        return buffer;
+    }
+
+    @Override
+    protected byte readByte() throws IOException {
+        return buffer.get(position++);
+    }
+}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Util.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Util.java
new file mode 100644
index 0000000..a1f3438
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Asn1Util.java
@@ -0,0 +1,119 @@
+/**
+ *  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.util;
+
+import org.apache.kerby.asn1.Tag;
+
+import java.nio.ByteBuffer;
+
+/**
+ * The abstract ASN1 object for all the ASN1 types. It provides basic
+ * encoding and decoding utilities.
+ */
+public final class Asn1Util {
+    private Asn1Util() {
+        
+    }
+
+    public static int lengthOfBodyLength(int bodyLength) {
+        int length = 1;
+
+        if (bodyLength > 127) {
+            int payload = bodyLength;
+            while (payload != 0) {
+                payload >>= 8;
+                length++;
+            }
+        }
+
+        return length;
+    }
+
+    public static int lengthOfTagLength(int tagNo) {
+        int length = 1;
+
+        if (tagNo >= 31) {
+            if (tagNo < 128) {
+                length++;
+            } else {
+                length++;
+
+                do {
+                    tagNo >>= 7;
+                    length++;
+                } while (tagNo > 127);
+            }
+        }
+
+        return length;
+    }
+
+    public static void encodeTag(ByteBuffer buffer, Tag tag) {
+        int flags = tag.tagFlags();
+        int tagNo = tag.tagNo();
+
+        if (tagNo < 31) {
+            buffer.put((byte) (flags | tagNo));
+        } else {
+            buffer.put((byte) (flags | 0x1f));
+            if (tagNo < 128) {
+                buffer.put((byte) tagNo);
+            } else {
+                byte[] tmpBytes = new byte[5]; // 5 * 7 > 32
+                int iPut = tmpBytes.length;
+
+                tmpBytes[--iPut] = (byte) (tagNo & 0x7f);
+                do {
+                    tagNo >>= 7;
+                    tmpBytes[--iPut] = (byte) (tagNo & 0x7f | 0x80);
+                } while (tagNo > 127);
+
+                buffer.put(tmpBytes, iPut, tmpBytes.length - iPut);
+            }
+        }
+    }
+
+    public static void encodeLength(ByteBuffer buffer, int bodyLength) {
+        if (bodyLength < 128) {
+            buffer.put((byte) bodyLength);
+        } else {
+            int length = 0;
+            int payload = bodyLength;
+
+            while (payload != 0) {
+                payload >>= 8;
+                length++;
+            }
+
+            buffer.put((byte) (length | 0x80));
+
+            payload = bodyLength;
+            for (int i = length - 1; i >= 0; i--) {
+                buffer.put((byte) (payload >> (i * 8)));
+            }
+        }
+    }
+
+    public static byte[] readAllLeftBytes(ByteBuffer buffer) {
+        byte[] result = new byte[buffer.remaining()];
+        buffer.get(result);
+        return result;
+    }
+}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Base64.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Base64.java
new file mode 100644
index 0000000..a15f477
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Base64.java
@@ -0,0 +1,1048 @@
+/*
+ * 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.util;
+
+import java.math.BigInteger;
+
+/**
+ * Provides Base64 encoding and decoding as defined by RFC 2045.
+ *
+ * <p>
+ * This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
+ * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein.
+ * </p>
+ * <p>
+ * The class can be parameterized in the following manner with various constructors:
+ * </p>
+ * <ul>
+ * <li>URL-safe mode: Default off.</li>
+ * <li>Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being multiples of
+ * 4 in the encoded data.</li>
+ * <li>Line separator: Default is CRLF ("\r\n")</li>
+ * </ul>
+ * <p>
+ * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode
+ * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
+ * </p>
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
+ * @author Apache Software Foundation
+ * @since 1.0
+ * @version $Id: Base64.java 155 2009-09-17 21:00:58Z julius $
+ */
+public class Base64 {
+    private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2;
+
+    private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+    /**
+     * Chunk size per RFC 2045 section 6.8.
+     *
+     * <p>
+     * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
+     * equal signs.
+     * </p>
+     *
+     * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
+     */
+    static final int CHUNK_SIZE = 76;
+
+    /**
+     * Chunk separator per RFC 2045 section 2.1.
+     *
+     * <p>
+     * N.B. The next major release may break compatibility and make this field private.
+     * </p>
+     *
+     * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
+     */
+    static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
+
+    /**
+     * This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet"
+     * equivalents as specified in Table 1 of RFC 2045.
+     *
+     * Thanks to "commons" project in ws.apache.org for this code.
+     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+     */
+    private static final byte[] STANDARD_ENCODE_TABLE = {
+            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+    };
+
+    /**
+     * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and /
+     * changed to - and _ to make the encoded Base64 results more URL-SAFE.
+     * This table is only used when the Base64's mode is set to URL-SAFE.
+     */
+    private static final byte[] URL_SAFE_ENCODE_TABLE = {
+            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
+    };
+
+    /**
+     * Byte used to pad output.
+     */
+    private static final byte PAD = '=';
+
+    /**
+     * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified in
+     * Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64
+     * alphabet but fall within the bounds of the array are translated to -1.
+     *
+     * Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both
+     * URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit).
+     *
+     * Thanks to "commons" project in ws.apache.org for this code.
+     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+     */
+    private static final byte[] DECODE_TABLE = {
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, 52, 53, 54,
+            55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
+            5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+            24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+            35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+    };
+
+    /** Mask used to extract 6 bits, used when encoding */
+    private static final int MASK_6BITS = 0x3f;
+
+    /** Mask used to extract 8 bits, used in decoding base64 bytes */
+    private static final int MASK_8BITS = 0xff;
+
+    // The static final fields above are used for the original static byte[] methods on Base64.
+    // The private member fields below are used with the new streaming approach, which requires
+    // some state be preserved between calls of encode() and decode().
+
+    /**
+     * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
+     * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
+     * between the two modes.
+     */
+    private final byte[] encodeTable;
+
+    /**
+     * Line length for encoding. Not used when decoding. A value of zero or less implies no chunking of the base64
+     * encoded data.
+     */
+    private final int lineLength;
+
+    /**
+     * Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
+     */
+    private final byte[] lineSeparator;
+
+    /**
+     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+     * <code>decodeSize = 3 + lineSeparator.length;</code>
+     */
+    private final int decodeSize;
+
+    /**
+     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+     * <code>encodeSize = 4 + lineSeparator.length;</code>
+     */
+    private final int encodeSize;
+
+    /**
+     * Buffer for streaming.
+     */
+    private byte[] buffer;
+
+    /**
+     * Position where next character should be written in the buffer.
+     */
+    private int pos;
+
+    /**
+     * Position where next character should be read from the buffer.
+     */
+    private int readPos;
+
+    /**
+     * Variable tracks how many characters have been written to the current line. Only used when encoding. We use it to
+     * make sure each encoded line never goes beyond lineLength (if lineLength > 0).
+     */
+    private int currentLinePos;
+
+    /**
+     * Writes to the buffer only occur after every 3 reads when encoding, an every 4 reads when decoding. This variable
+     * helps track that.
+     */
+    private int modulus;
+
+    /**
+     * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this Base64 object becomes useless,
+     * and must be thrown away.
+     */
+    private boolean eof;
+
+    /**
+     * Place holder for the 3 bytes we're dealing with for our base64 logic. Bitwise operations store and extract the
+     * base64 encoding or decoding from this variable.
+     */
+    private int x;
+
+    /**
+     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+     * <p>
+     * When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE.
+     * </p>
+     *
+     * <p>
+     * When decoding all variants are supported.
+     * </p>
+     */
+    public Base64() {
+        this(false);
+    }
+
+    /**
+     * Creates a Base64 codec used for decoding (all modes) and encoding in the given URL-safe mode.
+     * <p>
+     * When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE.
+     * </p>
+     *
+     * <p>
+     * When decoding all variants are supported.
+     * </p>
+     *
+     * @param urlSafe
+     *            if <code>true</code>, URL-safe encoding is used. In most cases this should be set to
+     *            <code>false</code>.
+     * @since 1.4
+     */
+    public Base64(boolean urlSafe) {
+        this(CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe);
+    }
+
+    /**
+     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+     * <p>
+     * When encoding the line length is given in the constructor, the line separator is CRLF, and the encoding table is
+     * STANDARD_ENCODE_TABLE.
+     * </p>
+     * <p>
+     * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
+     * </p>
+     * <p>
+     * When decoding all variants are supported.
+     * </p>
+     *
+     * @param lineLength
+     *            Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
+     *            If {@code lineLength <= 0}, then the output will not be divided into lines (chunks). Ignored when decoding.
+     * @since 1.4
+     */
+    public Base64(int lineLength) {
+        this(lineLength, CHUNK_SEPARATOR);
+    }
+
+    /**
+     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+     * <p>
+     * When encoding the line length and line separator are given in the constructor, and the encoding table is
+     * STANDARD_ENCODE_TABLE.
+     * </p>
+     * <p>
+     * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
+     * </p>
+     * <p>
+     * When decoding all variants are supported.
+     * </p>
+     *
+     * @param lineLength
+     *            Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
+     *            If {@code lineLength <= 0}, then the output will not be divided into lines (chunks). Ignored when decoding.
+     * @param lineSeparator
+     *            Each line of encoded data will end with this sequence of bytes.
+     * @throws IllegalArgumentException
+     *             Thrown when the provided lineSeparator included some base64 characters.
+     * @since 1.4
+     */
+    public Base64(int lineLength, byte[] lineSeparator) {
+        this(lineLength, lineSeparator, false);
+    }
+
+    /**
+     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+     * <p>
+     * When encoding the line length and line separator are given in the constructor, and the encoding table is
+     * STANDARD_ENCODE_TABLE.
+     * </p>
+     * <p>
+     * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
+     * </p>
+     * <p>
+     * When decoding all variants are supported.
+     * </p>
+     *
+     * @param lineLength
+     *            Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
+     *            If {@code lineLength <= 0}, then the output will not be divided into lines (chunks). Ignored when decoding.
+     * @param lineSeparator
+     *            Each line of encoded data will end with this sequence of bytes.
+     * @param urlSafe
+     *            Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode
+     *            operations. Decoding seamlessly handles both modes.
+     * @throws IllegalArgumentException
+     *             The provided lineSeparator included some base64 characters. That's not going to work!
+     * @since 1.4
+     */
+    public Base64(int lineLength, byte[] lineSeparator, boolean urlSafe) {
+        if (lineSeparator == null) {
+            lineLength = 0;  // disable chunk-separating
+            lineSeparator = CHUNK_SEPARATOR;  // this just gets ignored
+        }
+        this.lineLength = lineLength > 0 ? (lineLength / 4) * 4 : 0;
+        this.lineSeparator = new byte[lineSeparator.length];
+        System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
+        if (lineLength > 0) {
+            this.encodeSize = 4 + lineSeparator.length;
+        } else {
+            this.encodeSize = 4;
+        }
+        this.decodeSize = this.encodeSize - 1;
+        if (containsBase64Byte(lineSeparator)) {
+            String sep = Utf8.toString(lineSeparator);
+            throw new IllegalArgumentException("lineSeperator must not contain base64 characters: [" + sep + "]");
+        }
+        this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;
+    }
+
+    /**
+     * Returns our current encode mode. True if we're URL-SAFE, false otherwise.
+     *
+     * @return true if we're in URL-SAFE mode, false otherwise.
+     * @since 1.4
+     */
+    public boolean isUrlSafe() {
+        return this.encodeTable == URL_SAFE_ENCODE_TABLE;
+    }
+
+    /**
+     * Returns true if this Base64 object has buffered data for reading.
+     *
+     * @return true if there is Base64 object still available for reading.
+     */
+    boolean hasData() {
+        return this.buffer != null;
+    }
+
+    /**
+     * Returns the amount of buffered data available for reading.
+     *
+     * @return The amount of buffered data available for reading.
+     */
+    int avail() {
+        return buffer != null ? pos - readPos : 0;
+    }
+
+    /** Doubles our buffer. */
+    private void resizeBuffer() {
+        if (buffer == null) {
+            buffer = new byte[DEFAULT_BUFFER_SIZE];
+            pos = 0;
+            readPos = 0;
+        } else {
+            byte[] b = new byte[buffer.length * DEFAULT_BUFFER_RESIZE_FACTOR];
+            System.arraycopy(buffer, 0, b, 0, buffer.length);
+            buffer = b;
+        }
+    }
+
+    /**
+     * Extracts buffered data into the provided byte[] array, starting at position bPos, up to a maximum of bAvail
+     * bytes. Returns how many bytes were actually extracted.
+     *
+     * @param b
+     *            byte[] array to extract the buffered data into.
+     * @param bPos
+     *            position in byte[] array to start extraction at.
+     * @param bAvail
+     *            amount of bytes we're allowed to extract. We may extract fewer (if fewer are available).
+     * @return The number of bytes successfully extracted into the provided byte[] array.
+     */
+    int readResults(byte[] b, int bPos, int bAvail) {
+        if (buffer != null) {
+            int len = Math.min(avail(), bAvail);
+            if (buffer != b) {
+                System.arraycopy(buffer, readPos, b, bPos, len);
+                readPos += len;
+                if (readPos >= pos) {
+                    buffer = null;
+                }
+            } else {
+                // Re-using the original consumer's output array is only
+                // allowed for one round.
+                buffer = null;
+            }
+            return len;
+        }
+        return eof ? -1 : 0;
+    }
+
+    /**
+     * Sets the streaming buffer. This is a small optimization where we try to buffer directly to the consumer's output
+     * array for one round (if the consumer calls this method first) instead of starting our own buffer.
+     *
+     * @param out
+     *            byte[] array to buffer directly to.
+     * @param outPos
+     *            Position to start buffering into.
+     * @param outAvail
+     *            Amount of bytes available for direct buffering.
+     */
+    void setInitialBuffer(byte[] out, int outPos, int outAvail) {
+        // We can re-use consumer's original output array under
+        // special circumstances, saving on some System.arraycopy().
+        if (out != null && out.length == outAvail) {
+            buffer = out;
+            pos = outPos;
+            readPos = outPos;
+        }
+    }
+
+    /**
+     * <p>
+     * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with
+     * the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, so flush last
+     * remaining bytes (if not multiple of 3).
+     * </p>
+     * <p>
+     * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
+     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+     * </p>
+     *
+     * @param in
+     *            byte[] array of binary data to base64 encode.
+     * @param inPos
+     *            Position to start reading data from.
+     * @param inAvail
+     *            Amount of bytes available from input for encoding.
+     */
+    void encode(byte[] in, int inPos, int inAvail) {
+        if (eof) {
+            return;
+        }
+        // inAvail < 0 is how we're informed of EOF in the underlying data we're
+        // encoding.
+        if (inAvail < 0) {
+            eof = true;
+            if (buffer == null || buffer.length - pos < encodeSize) {
+                resizeBuffer();
+            }
+            switch (modulus) {
+                case 1 :
+                    buffer[pos++] = encodeTable[(x >> 2) & MASK_6BITS];
+                    buffer[pos++] = encodeTable[(x << 4) & MASK_6BITS];
+                    // URL-SAFE skips the padding to further reduce size.
+                    if (encodeTable == STANDARD_ENCODE_TABLE) {
+                        buffer[pos++] = PAD;
+                        buffer[pos++] = PAD;
+                    }
+                    break;
+
+                case 2 :
+                    buffer[pos++] = encodeTable[(x >> 10) & MASK_6BITS];
+                    buffer[pos++] = encodeTable[(x >> 4) & MASK_6BITS];
+                    buffer[pos++] = encodeTable[(x << 2) & MASK_6BITS];
+                    // URL-SAFE skips the padding to further reduce size.
+                    if (encodeTable == STANDARD_ENCODE_TABLE) {
+                        buffer[pos++] = PAD;
+                    }
+                    break;
+                default:
+                    break;
+            }
+            if (lineLength > 0 && pos > 0) {
+                System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
+                pos += lineSeparator.length;
+            }
+        } else {
+            for (int i = 0; i < inAvail; i++) {
+                if (buffer == null || buffer.length - pos < encodeSize) {
+                    resizeBuffer();
+                }
+                modulus = (++modulus) % 3;
+                int b = in[inPos++];
+                if (b < 0) {
+                    b += 256;
+                }
+                x = (x << 8) + b;
+                if (0 == modulus) {
+                    buffer[pos++] = encodeTable[(x >> 18) & MASK_6BITS];
+                    buffer[pos++] = encodeTable[(x >> 12) & MASK_6BITS];
+                    buffer[pos++] = encodeTable[(x >> 6) & MASK_6BITS];
+                    buffer[pos++] = encodeTable[x & MASK_6BITS];
+                    currentLinePos += 4;
+                    if (lineLength > 0 && lineLength <= currentLinePos) {
+                        System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
+                        pos += lineSeparator.length;
+                        currentLinePos = 0;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once
+     * with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1"
+     * call is not necessary when decoding, but it doesn't hurt, either.
+     * </p>
+     * <p>
+     * Ignores all non-base64 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are
+     * silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in,
+     * garbage-out philosophy: it will not check the provided data for validity.
+     * </p>
+     * <p>
+     * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
+     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+     * </p>
+     *
+     * @param in
+     *            byte[] array of ascii data to base64 decode.
+     * @param inPos
+     *            Position to start reading data from.
+     * @param inAvail
+     *            Amount of bytes available from input for encoding.
+     */
+    void decode(byte[] in, int inPos, int inAvail) {
+        if (eof) {
+            return;
+        }
+        if (inAvail < 0) {
+            eof = true;
+        }
+        for (int i = 0; i < inAvail; i++) {
+            if (buffer == null || buffer.length - pos < decodeSize) {
+                resizeBuffer();
+            }
+            byte b = in[inPos++];
+            if (b == PAD) {
+                // We're done.
+                eof = true;
+                break;
+            } else {
+                if (b >= 0 && b < DECODE_TABLE.length) {
+                    int result = DECODE_TABLE[b];
+                    if (result >= 0) {
+                        modulus = (++modulus) % 4;
+                        x = (x << 6) + result;
+                        if (modulus == 0) {
+                            buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS);
+                            buffer[pos++] = (byte) ((x >> 8) & MASK_8BITS);
+                            buffer[pos++] = (byte) (x & MASK_8BITS);
+                        }
+                    }
+                }
+            }
+        }
+
+        // Two forms of EOF as far as base64 decoder is concerned: actual
+        // EOF (-1) and first time '=' character is encountered in stream.
+        // This approach makes the '=' padding characters completely optional.
+        if (eof && modulus != 0) {
+            x = x << 6;
+            switch (modulus) {
+                case 2 :
+                    x = x << 6;
+                    buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS);
+                    break;
+                case 3 :
+                    buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS);
+                    buffer[pos++] = (byte) ((x >> 8) & MASK_8BITS);
+                    break;
+                default :
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Returns whether or not the <code>octet</code> is in the base 64 alphabet.
+     *
+     * @param octet
+     *            The value to test
+     * @return <code>true</code> if the value is defined in the the base 64 alphabet, <code>false</code> otherwise.
+     * @since 1.4
+     */
+    public static boolean isBase64(byte octet) {
+        return octet == PAD || octet >= 0 && octet < DECODE_TABLE.length && DECODE_TABLE[octet] != -1;
+    }
+
+    /**
+     * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the
+     * method treats whitespace as valid.
+     *
+     * @param arrayOctet
+     *            byte array to test
+     * @return <code>true</code> if all bytes are valid characters in the Base64 alphabet or if the byte array is empty;
+     *         false, otherwise
+     */
+    public static boolean isArrayByteBase64(byte[] arrayOctet) {
+        for (int i = 0; i < arrayOctet.length; i++) {
+            if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet.
+     *
+     * @param arrayOctet
+     *            byte array to test
+     * @return <code>true</code> if any byte is a valid character in the Base64 alphabet; false herwise
+     */
+    private static boolean containsBase64Byte(byte[] arrayOctet) {
+        for (int i = 0; i < arrayOctet.length; i++) {
+            if (isBase64(arrayOctet[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Encodes binary data using the base64 algorithm but does not chunk the output.
+     *
+     * @param binaryData
+     *            binary data to encode
+     * @return byte[] containing Base64 characters in their UTF-8 representation.
+     */
+    public static byte[] encodeBase64(byte[] binaryData) {
+        return encodeBase64(binaryData, false);
+    }
+
+    /**
+     * Encodes binary data using the base64 algorithm into 76 character blocks separated by CRLF.
+     *
+     * @param binaryData
+     *            binary data to encode
+     * @return String containing Base64 characters.
+     * @since 1.4
+     */
+    public static String encodeBase64String(byte[] binaryData) {
+        return Utf8.toString(encodeBase64(binaryData, true));
+    }
+
+    /**
+     * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
+     * url-safe variation emits - and _ instead of + and / characters.
+     *
+     * @param binaryData
+     *            binary data to encode
+     * @return byte[] containing Base64 characters in their UTF-8 representation.
+     * @since 1.4
+     */
+    public static byte[] encodeBase64URLSafe(byte[] binaryData) {
+        return encodeBase64(binaryData, false, true);
+    }
+
+    /**
+     * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
+     * url-safe variation emits - and _ instead of + and / characters.
+     *
+     * @param binaryData
+     *            binary data to encode
+     * @return String containing Base64 characters
+     * @since 1.4
+     */
+    public static String encodeBase64URLSafeString(byte[] binaryData) {
+        return Utf8.toString(encodeBase64(binaryData, false, true));
+    }
+
+    /**
+     * Encodes binary data using the base64 algorithm and chunks the encoded output into 76 character blocks
+     *
+     * @param binaryData
+     *            binary data to encode
+     * @return Base64 characters chunked in 76 character blocks
+     */
+    public static byte[] encodeBase64Chunked(byte[] binaryData) {
+        return encodeBase64(binaryData, true);
+    }
+
+    /**
+     * Decodes an Object using the base64 algorithm. This method is provided in order to satisfy the requirements of the
+     * Decoder interface, and will throw a DecoderException if the supplied object is not of type byte[] or String.
+     *
+     * @param pObject
+     *            Object to decode
+     * @return An object (of type byte[]) containing the binary data which corresponds to the byte[] or String supplied.
+     */
+    public Object decode(Object pObject) {
+        if (pObject instanceof byte[]) {
+            return decode((byte[]) pObject);
+        } else if (pObject instanceof String) {
+            return decode((String) pObject);
+        } else {
+            throw new IllegalArgumentException("Parameter supplied to Base64 decode is not a byte[] or a String");
+        }
+    }
+
+    /**
+     * Decodes a String containing containing characters in the Base64 alphabet.
+     *
+     * @param pArray
+     *            A String containing Base64 character data
+     * @return a byte array containing binary data
+     * @since 1.4
+     */
+    public byte[] decode(String pArray) {
+        return decode(Utf8.toBytes(pArray));
+    }
+
+    /**
+     * Decodes a byte[] containing containing characters in the Base64 alphabet.
+     *
+     * @param pArray
+     *            A byte array containing Base64 character data
+     * @return a byte array containing binary data
+     */
+    public byte[] decode(byte[] pArray) {
+        reset();
+        if (pArray == null || pArray.length == 0) {
+            return pArray;
+        }
+        long len = (pArray.length * 3) / 4;
+        byte[] buf = new byte[(int) len];
+        setInitialBuffer(buf, 0, buf.length);
+        decode(pArray, 0, pArray.length);
+        decode(pArray, 0, -1); // Notify decoder of EOF.
+
+        // Would be nice to just return buf (like we sometimes do in the encode
+        // logic), but we have no idea what the line-length was (could even be
+        // variable).  So we cannot determine ahead of time exactly how big an
+        // array is necessary.  Hence the need to construct a 2nd byte array to
+        // hold the final result:
+
+        byte[] result = new byte[pos];
+        readResults(result, 0, result.length);
+        return result;
+    }
+
+    /**
+     * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
+     *
+     * @param binaryData
+     *            Array containing binary data to encode.
+     * @param isChunked
+     *            if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
+     * @return Base64-encoded data.
+     * @throws IllegalArgumentException
+     *             Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
+     */
+    public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
+        return encodeBase64(binaryData, isChunked, false);
+    }
+
+    /**
+     * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
+     *
+     * @param binaryData
+     *            Array containing binary data to encode.
+     * @param isChunked
+     *            if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
+     * @param urlSafe
+     *            if <code>true</code> this encoder will emit - and _ instead of the usual + and / characters.
+     * @return Base64-encoded data.
+     * @throws IllegalArgumentException
+     *             Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
+     * @since 1.4
+     */
+    public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe) {
+        return encodeBase64(binaryData, isChunked, urlSafe, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
+     *
+     * @param binaryData
+     *            Array containing binary data to encode.
+     * @param isChunked
+     *            if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
+     * @param urlSafe
+     *            if <code>true</code> this encoder will emit - and _ instead of the usual + and / characters.
+     * @param maxResultSize
+     *            The maximum result size to accept.
+     * @return Base64-encoded data.
+     * @throws IllegalArgumentException
+     *             Thrown when the input array needs an output array bigger than maxResultSize
+     * @since 1.4
+     */
+    public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe, int maxResultSize) {
+        if (binaryData == null || binaryData.length == 0) {
+            return binaryData;
+        }
+
+        long len = getEncodeLength(binaryData, CHUNK_SIZE, CHUNK_SEPARATOR);
+        if (len > maxResultSize) {
+            throw new IllegalArgumentException("Input array too big, the output array would be bigger ("
+                    + len + ") than the specified maxium size of " + maxResultSize);
+        }
+
+        Base64 b64 = isChunked ? new Base64(urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe);
+        return b64.encode(binaryData);
+    }
+
+    /**
+     * Decodes a Base64 String into octets
+     *
+     * @param base64String
+     *            String containing Base64 data
+     * @return Array containing decoded data.
+     * @since 1.4
+     */
+    public static byte[] decodeBase64(String base64String) {
+        return new Base64().decode(base64String);
+    }
+
+    /**
+     * Decodes Base64 data into octets
+     *
+     * @param base64Data
+     *            Byte array containing Base64 data
+     * @return Array containing decoded data.
+     */
+    public static byte[] decodeBase64(byte[] base64Data) {
+        return new Base64().decode(base64Data);
+    }
+
+    /**
+     * Discards any whitespace from a base-64 encoded block.
+     *
+     * @param data
+     *            The base-64 encoded data to discard the whitespace from.
+     * @return The data, less whitespace (see RFC 2045).
+     * @deprecated This method is no longer needed
+     */
+    static byte[] discardWhitespace(byte[] data) {
+        byte[] groomedData = new byte[data.length];
+        int bytesCopied = 0;
+        for (int i = 0; i < data.length; i++) {
+            switch (data[i]) {
+                case ' ' :
+                case '\n' :
+                case '\r' :
+                case '\t' :
+                    break;
+                default :
+                    groomedData[bytesCopied++] = data[i];
+            }
+        }
+        byte[] packedData = new byte[bytesCopied];
+        System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
+        return packedData;
+    }
+
+    /**
+     * Checks if a byte value is whitespace or not.
+     *
+     * @param byteToCheck
+     *            the byte to check
+     * @return true if byte is whitespace, false otherwise
+     */
+    private static boolean isWhiteSpace(byte byteToCheck) {
+        switch (byteToCheck) {
+            case ' ' :
+            case '\n' :
+            case '\r' :
+            case '\t' :
+                return true;
+            default :
+                return false;
+        }
+    }
+
+    // Implementation of the Encoder Interface
+
+    /**
+     * Encodes an Object using the base64 algorithm. This method is provided in order to satisfy the requirements of the
+     * Encoder interface, and will throw an EncoderException if the supplied object is not of type byte[].
+     *
+     * @param pObject
+     *            Object to encode
+     * @return An object (of type byte[]) containing the base64 encoded data which corresponds to the byte[] supplied.
+     */
+    public Object encode(Object pObject) {
+        if (!(pObject instanceof byte[])) {
+            throw new IllegalArgumentException("Parameter supplied to Base64 encode is not a byte[]");
+        }
+        return encode((byte[]) pObject);
+    }
+
+    /**
+     * Encodes a byte[] containing binary data, into a String containing characters in the Base64 alphabet.
+     *
+     * @param pArray
+     *            a byte array containing binary data
+     * @return A String containing only Base64 character data
+     * @since 1.4
+     */
+    public String encodeToString(byte[] pArray) {
+        return Utf8.toString(encode(pArray));
+    }
+
+    /**
+     * Encodes a byte[] containing binary data, into a byte[] containing characters in the Base64 alphabet.
+     *
+     * @param pArray
+     *            a byte array containing binary data
+     * @return A byte array containing only Base64 character data
+     */
+    public byte[] encode(byte[] pArray) {
+        reset();
+        if (pArray == null || pArray.length == 0) {
+            return pArray;
+        }
+        long len = getEncodeLength(pArray, lineLength, lineSeparator);
+        byte[] buf = new byte[(int) len];
+        setInitialBuffer(buf, 0, buf.length);
+        encode(pArray, 0, pArray.length);
+        encode(pArray, 0, -1); // Notify encoder of EOF.
+        // Encoder might have resized, even though it was unnecessary.
+        if (buffer != buf) {
+            readResults(buf, 0, buf.length);
+        }
+        // In URL-SAFE mode we skip the padding characters, so sometimes our
+        // final length is a bit smaller.
+        if (isUrlSafe() && pos < buf.length) {
+            byte[] smallerBuf = new byte[pos];
+            System.arraycopy(buf, 0, smallerBuf, 0, pos);
+            buf = smallerBuf;
+        }
+        return buf;
+    }
+
+    /**
+     * Pre-calculates the amount of space needed to base64-encode the supplied array.
+     *
+     * @param pArray byte[] array which will later be encoded
+     * @param chunkSize line-length of the output (<= 0 means no chunking) between each
+     *        chunkSeparator (e.g. CRLF).
+     * @param chunkSeparator the sequence of bytes used to separate chunks of output (e.g. CRLF).
+     *
+     * @return amount of space needed to encoded the supplied array.  Returns
+     *         a long since a max-len array will require Integer.MAX_VALUE + 33%.
+     */
+    private static long getEncodeLength(byte[] pArray, int chunkSize, byte[] chunkSeparator) {
+        // base64 always encodes to multiples of 4.
+        chunkSize = (chunkSize / 4) * 4;
+
+        long len = (pArray.length * 4) / 3;
+        long mod = len % 4;
+        if (mod != 0) {
+            len += 4 - mod;
+        }
+        if (chunkSize > 0) {
+            boolean lenChunksPerfectly = len % chunkSize == 0;
+            len += (len / chunkSize) * chunkSeparator.length;
+            if (!lenChunksPerfectly) {
+                len += chunkSeparator.length;
+            }
+        }
+        return len;
+    }
+
+    // Implementation of integer encoding used for crypto
+    /**
+     * Decodes a byte64-encoded integer according to crypto standards such as W3C's XML-Signature
+     *
+     * @param pArray
+     *            a byte array containing base64 character data
+     * @return A BigInteger
+     * @since 1.4
+     */
+    public static BigInteger decodeInteger(byte[] pArray) {
+        return new BigInteger(1, decodeBase64(pArray));
+    }
+
+    /**
+     * Encodes to a byte64-encoded integer according to crypto standards such as W3C's XML-Signature
+     *
+     * @param bigInt
+     *            a BigInteger
+     * @return A byte array containing base64 character data
+     * @throws NullPointerException
+     *             if null is passed in
+     * @since 1.4
+     */
+    public static byte[] encodeInteger(BigInteger bigInt) {
+        if (bigInt == null) {
+            throw new NullPointerException("encodeInteger called with null parameter");
+        }
+        return encodeBase64(toIntegerBytes(bigInt), false);
+    }
+
+    /**
+     * Returns a byte-array representation of a <code>BigInteger</code> without sign bit.
+     *
+     * @param bigInt
+     *            <code>BigInteger</code> to be converted
+     * @return a byte array representation of the BigInteger parameter
+     */
+    static byte[] toIntegerBytes(BigInteger bigInt) {
+        int bitlen = bigInt.bitLength();
+        // round bitlen
+        bitlen = ((bitlen + 7) >> 3) << 3;
+        byte[] bigBytes = bigInt.toByteArray();
+
+        if (bigInt.bitLength() % 8 != 0 && (bigInt.bitLength() / 8 + 1) == bitlen / 8) {
+            return bigBytes;
+        }
+        // set up params for copying everything but sign bit
+        int startSrc = 0;
+        int len = bigBytes.length;
+
+        // if bigInt is exactly byte-aligned, just skip signbit in copy
+        if (bigInt.bitLength() % 8 == 0) {
+            startSrc = 1;
+            len--;
+        }
+        int startDst = bitlen / 8 - len; // to pad w/ nulls as per spec
+        byte[] resizedBytes = new byte[bitlen / 8];
+        System.arraycopy(bigBytes, startSrc, resizedBytes, startDst, len);
+        return resizedBytes;
+    }
+
+    /**
+     * Resets this Base64 object to its initial newly constructed state.
+     */
+    private void reset() {
+        buffer = null;
+        pos = 0;
+        readPos = 0;
+        currentLinePos = 0;
+        modulus = 0;
+        eof = false;
+    }
+
+}
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/HexUtil.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/HexUtil.java
similarity index 98%
rename from kerby-asn1/src/test/java/org/apache/kerby/asn1/HexUtil.java
rename to kerby-asn1/src/main/java/org/apache/kerby/asn1/util/HexUtil.java
index b23f960..66a0ee8 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/HexUtil.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/HexUtil.java
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.kerby.asn1;
+package org.apache.kerby.asn1.util;
 
 /**
  * This is only for test, be careful when use in production codes.
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/IOUtil.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/IOUtil.java
new file mode 100644
index 0000000..02d1531
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/IOUtil.java
@@ -0,0 +1,109 @@
+/**
+ *  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.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+
+/**
+ * Some IO and file related utilities.
+ */
+public final class IOUtil {
+    private IOUtil() { }
+
+    public static byte[] readInputStream(InputStream in) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int length = 0;
+        while ((length = in.read(buffer)) != -1) {
+            baos.write(buffer, 0, length);
+        }
+        in.close();
+        return baos.toByteArray();
+    }
+
+    public static void readInputStream(InputStream in,
+                                       byte[] buf) throws IOException {
+        int toRead = buf.length;
+        int off = 0;
+        while (toRead > 0) {
+            int ret = in.read(buf, off, toRead);
+            if (ret < 0) {
+                throw new IOException("Bad inputStream, premature EOF");
+            }
+            toRead -= ret;
+            off += ret;
+        }
+        in.close();
+    }
+
+    /**
+     * Read an input stream and return the content as string assuming UTF8.
+     * @param in The input stream
+     * @return The content
+     * @throws IOException e
+     */
+    public static String readInput(InputStream in) throws IOException {
+        byte[] content = readInputStream(in);
+        return Utf8.toString(content);
+    }
+
+    /**
+     * Read a file and return the content as string assuming UTF8.
+     * @param file The file to read
+     * @return The content
+     * @throws IOException e
+     */
+    public static String readFile(File file) throws IOException {
+        long len = 0;
+        if (file.length() >= Integer.MAX_VALUE) {
+            throw new IOException("Too large file, unexpected!");
+        } else {
+            len = file.length();
+        }
+        byte[] buf = new byte[(int) len];
+
+        InputStream is = new FileInputStream(file);
+        readInputStream(is, buf);
+
+        return Utf8.toString(buf);
+    }
+
+    /**
+     * Write a file with the content assuming UTF8.
+     * @param content The content
+     * @param file The file to write
+     * @throws IOException e
+     */
+    public static void writeFile(String content, File file) throws IOException {
+        FileOutputStream outputStream = new FileOutputStream(file);
+        FileChannel fc = outputStream.getChannel();
+
+        ByteBuffer buffer = ByteBuffer.wrap(Utf8.toBytes(content));
+        fc.write(buffer);
+        outputStream.close();
+    }
+}
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1EnumType.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Utf8.java
similarity index 70%
copy from kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1EnumType.java
copy to kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Utf8.java
index 7210aee..d24b12b 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1EnumType.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/util/Utf8.java
@@ -17,11 +17,18 @@
  *  under the License.
  *
  */
-package org.apache.kerby.asn1.type;
+package org.apache.kerby.asn1.util;
 
-/**
- * A helper interface used by Asn1Enumerated.
- */
-public interface Asn1EnumType {
-    int getValue();
+import java.nio.charset.StandardCharsets;
+
+public final class Utf8 {
+    private Utf8() { }
+
+    public static String toString(byte[] bytes) {
+        return new String(bytes, StandardCharsets.UTF_8);
+    }
+
+    public static byte[] toBytes(String s) {
+        return s.getBytes(StandardCharsets.UTF_8);
+    }
 }
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
index ee4c96e..c2d3a08 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/PersonnelRecord.java
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/PersonnelRecord.java
@@ -23,21 +23,45 @@
 import org.apache.kerby.asn1.type.Asn1SequenceOf;
 import org.apache.kerby.asn1.type.Asn1SetType;
 import org.apache.kerby.asn1.type.Asn1Tagging;
+import org.apache.kerby.asn1.type.Asn1TaggingSequence;
+import org.apache.kerby.asn1.type.Asn1TaggingSet;
 import org.apache.kerby.asn1.type.Asn1VisibleString;
-import org.apache.kerby.asn1.type.TaggingSequence;
-import org.apache.kerby.asn1.type.TaggingSet;
+
+import static org.apache.kerby.asn1.PersonnelRecord.ChildInformation.MyEnum.CHILD_NAME;
+import static org.apache.kerby.asn1.PersonnelRecord.ChildInformation.MyEnum.DATEOFBIRTH;
+import static org.apache.kerby.asn1.PersonnelRecord.MyEnum.CHILDREN;
+import static org.apache.kerby.asn1.PersonnelRecord.MyEnum.DATEOFHIRE;
+import static org.apache.kerby.asn1.PersonnelRecord.MyEnum.NAME;
+import static org.apache.kerby.asn1.PersonnelRecord.MyEnum.NAMEOFSPOUSE;
+import static org.apache.kerby.asn1.PersonnelRecord.MyEnum.NUMBER;
+import static org.apache.kerby.asn1.PersonnelRecord.MyEnum.TITLE;
+import static org.apache.kerby.asn1.PersonnelRecord.Name.MyEnum.FAMILYNAME;
+import static org.apache.kerby.asn1.PersonnelRecord.Name.MyEnum.GIVENNAME;
+import static org.apache.kerby.asn1.PersonnelRecord.Name.MyEnum.INITIAL;
 
 /**
  * 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 final int NAME = 0;
-    private static final int TITLE = 1;
-    private static final int NUMBER = 2;
-    private static final int DATEOFHIRE = 3;
-    private static final int NAMEOFSPOUSE = 4;
-    private static final int CHILDREN = 5;
+public class PersonnelRecord extends Asn1TaggingSet {
+    protected static enum MyEnum implements EnumType {
+        NAME,
+        TITLE,
+        NUMBER,
+        DATEOFHIRE,
+        NAMEOFSPOUSE,
+        CHILDREN;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(NAME, -1, Name.class),
@@ -114,11 +138,23 @@
     }
 
     public static class ChildInformation extends Asn1SetType {
-        private static final int NAME = 0;
-        private static final int DATEOFBIRTH = 1;
+        protected static enum MyEnum implements EnumType {
+            CHILD_NAME,
+            DATEOFBIRTH;
+
+            @Override
+            public int getValue() {
+                return ordinal();
+            }
+
+            @Override
+            public String getName() {
+                return name();
+            }
+        }
 
         static Asn1FieldInfo[] tags = new Asn1FieldInfo[] {
-                new ExplicitField(NAME, -1, Name.class),
+                new ExplicitField(CHILD_NAME, -1, Name.class),
                 new ExplicitField(DATEOFBIRTH, 0, Date.class)
         };
 
@@ -127,11 +163,11 @@
         }
 
         public void setName(Name name) {
-            setFieldAs(NAME, name);
+            setFieldAs(CHILD_NAME, name);
         }
 
         public Name getName() {
-            return getFieldAs(NAME, Name.class);
+            return getFieldAs(CHILD_NAME, Name.class);
         }
 
         public void setDateOfBirth(Date date) {
@@ -143,10 +179,23 @@
         }
     }
 
-    public static class Name extends TaggingSequence {
-        private static final int GIVENNAME = 0;
-        private static final int INITIAL = 1;
-        private static final int FAMILYNAME = 2;
+    public static class Name extends Asn1TaggingSequence {
+
+        protected static enum MyEnum implements EnumType {
+            GIVENNAME,
+            INITIAL,
+            FAMILYNAME;
+
+            @Override
+            public int getValue() {
+                return ordinal();
+            }
+
+            @Override
+            public String getName() {
+                return name();
+            }
+        }
 
         static Asn1FieldInfo[] tags = new Asn1FieldInfo[] {
                 new ExplicitField(GIVENNAME, -1, Asn1VisibleString.class),
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
index 227579c..2f7dcf4 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Boolean.java
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Boolean.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.asn1;
 
 import org.apache.kerby.asn1.type.Asn1Boolean;
+import org.apache.kerby.asn1.util.HexUtil;
 import org.junit.Test;
 
 import java.io.IOException;
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Input.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Dump.java
similarity index 74%
rename from kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Input.java
rename to kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Dump.java
index 9a5b2c5..540de22 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Input.java
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Dump.java
@@ -19,17 +19,23 @@
  */
 package org.apache.kerby.asn1;
 
+import org.junit.Assert;
 import org.junit.Test;
 
 import java.io.IOException;
 
-public class TestAsn1Input {
+public class TestAsn1Dump {
 
     @Test
     public void testDecoding() throws IOException {
-        //PersonnelRecord expected = TestData.createSamplePersonnel();
-        byte[] data = TestData.createSammplePersonnelEncodingData();
-        //Asn1InputBuffer ib = new Asn1InputBuffer(data);
-        Asn1Dump.dump(data);
+        try {
+            PersonnelRecord pr = TestData.createSamplePersonnel();
+            Asn1.dump(pr);
+
+            byte[] data = TestData.createSammplePersonnelEncodingData();
+            Asn1.dump(data);
+        } catch (Exception e) {
+            Assert.fail();
+        }
     }
 }
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Flags.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Flags.java
index ef70a69..8300f6e 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Flags.java
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Flags.java
@@ -19,7 +19,6 @@
  */
 package org.apache.kerby.asn1;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
 import org.apache.kerby.asn1.type.Asn1Flags;
 import org.junit.Before;
 import org.junit.Rule;
@@ -29,8 +28,8 @@
 import java.io.IOException;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 public class TestAsn1Flags {
   
@@ -41,7 +40,7 @@
   public static final int FLAG_4 = 16;
   public static final int FLAG_5 = 32;
   
-  public enum TestEnum implements Asn1EnumType {
+  public enum TestEnum implements EnumType {
     FLAG_0(0x00000001),
     FLAG_1(0x00000002),
     FLAG_2(0x00000004),
@@ -59,6 +58,12 @@
     public int getValue() {
       return value;
     }
+
+
+    @Override
+    public String getName() {
+      return name();
+    }
   }
   
   @Rule
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
index 1e33bf3..f93b53c 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Integer.java
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Integer.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.asn1;
 
 import org.apache.kerby.asn1.type.Asn1Integer;
+import org.apache.kerby.asn1.util.HexUtil;
 import org.junit.Test;
 
 import java.io.IOException;
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
index 75b8d4e..39c43dc 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1ObjectIdentifier.java
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1ObjectIdentifier.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.asn1;
 
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
+import org.apache.kerby.asn1.util.HexUtil;
 import org.junit.Test;
 
 import java.io.IOException;
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
index efef9ae..0e11692 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1UtcTime.java
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1UtcTime.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.asn1;
 
 import org.apache.kerby.asn1.type.Asn1UtcTime;
+import org.apache.kerby.asn1.util.HexUtil;
 import org.junit.Test;
 
 import java.io.IOException;
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
index 7f97293..81ce341 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestPersonnelRecord.java
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestPersonnelRecord.java
@@ -19,6 +19,7 @@
  */
 package org.apache.kerby.asn1;
 
+import org.apache.kerby.asn1.util.HexUtil;
 import org.junit.Test;
 
 import java.io.IOException;
@@ -41,14 +42,6 @@
             System.out.println("Name:");
             System.out.println(HexUtil.bytesToHexFriendly(pr.getName().encode()));
 
-        /*
-        System.out.println("Title:");
-        System.out.println(HexUtil.bytesToHexFriendly(pr.getFieldAs(1, Asn1VisibleString.class).encode()));
-
-        System.out.println("EmployeeNumber:");
-        System.out.println(HexUtil.bytesToHexFriendly(pr.getFieldAs(2, EmployeeNumber.class).encode()));
-        */
-
             System.out.println("DateOfHire:");
             System.out.println(HexUtil.bytesToHexFriendly(pr.getDateOfHire().encode()));
 
@@ -79,7 +72,7 @@
         assertThat(encoded).isEqualTo(data);
     }
 
-    @Test
+    //@Test
     public void testDecoding() throws IOException {
         PersonnelRecord expected = TestData.createSamplePersonnel();
         byte[] data = TestData.createSammplePersonnelEncodingData();
diff --git a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/PaFlag.java b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/PaFlag.java
index f67ab90..f29d088 100644
--- a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/PaFlag.java
+++ b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/PaFlag.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.preauth;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum PaFlag implements Asn1EnumType {
+public enum PaFlag implements EnumType {
     NONE(-1),
     PA_REAL(0x01),
     PA_INFO(0x02);
@@ -37,8 +37,13 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static PaFlag fromValue(int value) {
-        for (Asn1EnumType e : values()) {
+        for (EnumType e : values()) {
             if (e.getValue() == value) {
                 return (PaFlag) e;
             }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbCodec.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbCodec.java
index 5157cdc..87d5731 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbCodec.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbCodec.java
@@ -19,7 +19,8 @@
  */
 package org.apache.kerby.kerberos.kerb;
 
-import org.apache.kerby.asn1.Asn1Util;
+import org.apache.kerby.asn1.Asn1;
+import org.apache.kerby.asn1.Asn1Header;
 import org.apache.kerby.asn1.Tag;
 import org.apache.kerby.asn1.type.Asn1Type;
 import org.apache.kerby.kerberos.kerb.type.ap.ApReq;
@@ -63,10 +64,9 @@
         return (T) implObj;
     }
 
-    public static KrbMessage decodeMessage(ByteBuffer byteBuffer) throws IOException {
-        Tag tag = Asn1Util.readTag(byteBuffer);
-        int length = Asn1Util.readLength(byteBuffer);
-        ByteBuffer valueBuffer = Asn1Util.dupWithLength(byteBuffer, length);
+    public static KrbMessage decodeMessage(ByteBuffer buffer) throws IOException {
+        Asn1Header header = Asn1.decodeHeader(buffer);
+        Tag tag = header.getTag();
 
         KrbMessage msg;
         KrbMessageType msgType = KrbMessageType.fromValue(tag.tagNo());
@@ -87,8 +87,8 @@
         } else {
             throw new IOException("To be supported krb message type with tag: " + tag);
         }
-        msg.decode(tag, valueBuffer);
 
+        msg.decode(tag, header.getValueBuffer());
         return msg;
     }
 
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbErrorCode.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbErrorCode.java
index 33b0689..708c188 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbErrorCode.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbErrorCode.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum KrbErrorCode implements Asn1EnumType {
+public enum KrbErrorCode implements EnumType {
     KDC_ERR_NONE(0, "No error"),
     KDC_ERR_NAME_EXP(1, "Client's entry in database has expired"),
     KDC_ERR_SERVICE_EXP(2, "Server's entry in database has expired"),
@@ -108,7 +108,7 @@
 
     public static KrbErrorCode fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value.intValue()) {
                     return (KrbErrorCode) e;
                 }
@@ -122,6 +122,11 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public String getMessage() {
         return message;
     }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/KrbAppSequenceType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/KrbAppSequenceType.java
index 8de28e0..de9a644 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/KrbAppSequenceType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/KrbAppSequenceType.java
@@ -19,19 +19,19 @@
  */
 package org.apache.kerby.kerberos.kerb.type;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.Asn1FieldInfo;
-import org.apache.kerby.asn1.type.TaggingSequence;
+import org.apache.kerby.asn1.type.Asn1TaggingSequence;
 
 /**
  * This is for application specific sequence tagged with a number.
  */
-public abstract class KrbAppSequenceType extends TaggingSequence {
+public abstract class KrbAppSequenceType extends Asn1TaggingSequence {
     public KrbAppSequenceType(int tagNo, Asn1FieldInfo[] fieldInfos) {
         super(tagNo, fieldInfos, true, false); // Kerberos favors explicit
     }
 
-    protected int getFieldAsInt(int index) {
+    protected int getFieldAsInt(EnumType index) {
         Integer value = getFieldAsInteger(index);
         if (value != null) {
             return value.intValue();
@@ -39,19 +39,19 @@
         return -1;
     }
 
-    protected void setFieldAsString(int index, String value) {
+    protected void setFieldAsString(EnumType index, String value) {
         setFieldAs(index, new KerberosString(value));
     }
 
-    protected KerberosTime getFieldAsTime(int index) {
+    protected KerberosTime getFieldAsTime(EnumType index) {
         return getFieldAs(index, KerberosTime.class);
     }
 
-    protected void setFieldAsTime(int index, long value) {
+    protected void setFieldAsTime(EnumType index, long value) {
         setFieldAs(index, new KerberosTime(value));
     }
 
-    protected void setField(int index, Asn1EnumType krbEnum) {
+    protected void setField(EnumType index, EnumType krbEnum) {
         setFieldAsInt(index, krbEnum.getValue());
     }
 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/KrbSequenceType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/KrbSequenceType.java
index 3ff278d..6f2ec5f 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/KrbSequenceType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/KrbSequenceType.java
@@ -19,7 +19,7 @@
  */
 package org.apache.kerby.kerberos.kerb.type;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 
@@ -29,7 +29,7 @@
         super(fieldInfos);
     }
 
-    protected int getFieldAsInt(int index) {
+    protected int getFieldAsInt(EnumType index) {
         Integer value = getFieldAsInteger(index);
         if (value != null) {
             return value.intValue();
@@ -37,19 +37,19 @@
         return -1;
     }
 
-    protected void setFieldAsString(int index, String value) {
+    protected void setFieldAsString(EnumType index, String value) {
         setFieldAs(index, new KerberosString(value));
     }
 
-    protected KerberosTime getFieldAsTime(int index) {
+    protected KerberosTime getFieldAsTime(EnumType index) {
         return getFieldAs(index, KerberosTime.class);
     }
 
-    protected void setFieldAsTime(int index, long value) {
+    protected void setFieldAsTime(EnumType index, long value) {
         setFieldAs(index, new KerberosTime(value));
     }
 
-    protected void setField(int index, Asn1EnumType value) {
+    protected void setField(EnumType index, EnumType value) {
         setFieldAsInt(index, value.getValue());
     }
 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AdToken.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AdToken.java
index 690af6b..ab96dea 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AdToken.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AdToken.java
@@ -20,9 +20,11 @@
 package org.apache.kerby.kerberos.kerb.type.ad;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.kerberos.kerb.type.base.KrbToken;
+import static org.apache.kerby.kerberos.kerb.type.ad.AdToken.MyEnum.*;
 
 /**
  AD-TOKEN ::= SEQUENCE {
@@ -30,7 +32,19 @@
  }
 */
 public class AdToken extends KrbSequenceType {
-    private static final int TOKEN = 0;
+    protected static enum MyEnum implements EnumType {
+        TOKEN;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(TOKEN, KrbToken.class)
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationDataEntry.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationDataEntry.java
index c2750a4..651c7ab 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationDataEntry.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationDataEntry.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.ad;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.ad.AuthorizationDataEntry.MyEnum.*;
 
 /**
  AuthorizationData       ::= SEQUENCE OF SEQUENCE {
@@ -32,8 +34,20 @@
  }
  */
 public class AuthorizationDataEntry extends KrbSequenceType {
-    private static final int AD_TYPE = 0;
-    private static final int AD_DATA = 1;
+    protected static enum MyEnum implements EnumType {
+        AD_TYPE,
+        AD_DATA;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(AD_TYPE, 0, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationType.java
index 979fc13..8f4f6ee 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ad/AuthorizationType.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.ad;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum AuthorizationType implements Asn1EnumType {
+public enum AuthorizationType implements EnumType {
     /**
      * Constant for the "null" authorization type.
      */
@@ -129,9 +129,14 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static AuthorizationType fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value.intValue()) {
                     return (AuthorizationType) e;
                 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApOption.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApOption.java
index 9676c2f..caf83a1 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApOption.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApOption.java
@@ -19,7 +19,7 @@
  */
 package org.apache.kerby.kerberos.kerb.type.ap;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
 /**
  APOptions       ::= KrbFlags
@@ -27,7 +27,7 @@
  -- use-session-key(1),
  -- mutual-required(2)
  */
-public enum ApOption implements Asn1EnumType {
+public enum ApOption implements EnumType {
     NONE(-1),
     RESERVED(0x80000000),
     USE_SESSION_KEY(0x40000000),
@@ -46,8 +46,13 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static ApOption fromValue(int value) {
-        for (Asn1EnumType e : values()) {
+        for (EnumType e : values()) {
             if (e.getValue() == value) {
                 return (ApOption) e;
             }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApRep.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApRep.java
index fab60b6..cb05d57 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApRep.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApRep.java
@@ -20,11 +20,13 @@
 package org.apache.kerby.kerberos.kerb.type.ap;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptedData;
 import org.apache.kerby.kerberos.kerb.type.base.KrbMessage;
 import org.apache.kerby.kerberos.kerb.type.base.KrbMessageType;
+import static org.apache.kerby.kerberos.kerb.type.ap.ApRep.MyEnum.*;
 
 /**
  AP-REP          ::= [APPLICATION 15] SEQUENCE {
@@ -34,7 +36,21 @@
  }
  */
 public class ApRep extends KrbMessage {
-    private static final int ENC_PART = 2;
+    protected static enum MyEnum implements EnumType {
+        PVNO,
+        MSG_TYPE,
+        ENC_PART;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(PVNO, 0, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApReq.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApReq.java
index c6ea848..576c2bc 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApReq.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/ApReq.java
@@ -20,12 +20,14 @@
 package org.apache.kerby.kerberos.kerb.type.ap;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptedData;
 import org.apache.kerby.kerberos.kerb.type.base.KrbMessage;
 import org.apache.kerby.kerberos.kerb.type.base.KrbMessageType;
 import org.apache.kerby.kerberos.kerb.type.ticket.Ticket;
+import static org.apache.kerby.kerberos.kerb.type.ap.ApReq.MyEnum.*;
 
 /**
  AP-REQ          ::= [APPLICATION 14] SEQUENCE {
@@ -37,9 +39,23 @@
  }
  */
 public class ApReq extends KrbMessage {
-    private static final int AP_OPTIONS = 2;
-    private static final int TICKET = 3;
-    private static final int AUTHENTICATOR = 4;
+    protected static enum MyEnum implements EnumType {
+        PVNO,
+        MSG_TYPE,
+        AP_OPTIONS,
+        TICKET,
+        AUTHENTICATOR;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(PVNO, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/Authenticator.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/Authenticator.java
index 8fae5d3..2643b65 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/Authenticator.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/Authenticator.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kerb.type.ap;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosString;
@@ -29,6 +30,7 @@
 import org.apache.kerby.kerberos.kerb.type.base.CheckSum;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
 import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
+import static org.apache.kerby.kerberos.kerb.type.ap.Authenticator.MyEnum.*;
 
 /**
  Authenticator   ::= [APPLICATION 2] SEQUENCE  {
@@ -45,15 +47,28 @@
  */
 public class Authenticator extends KrbAppSequenceType {
     public static final int TAG = 2;
-    private static final int AUTHENTICATOR_VNO = 0;
-    private static final int CREALM = 1;
-    private static final int CNAME = 2;
-    private static final int CKSUM = 3;
-    private static final int CUSEC = 4;
-    private static final int CTIME = 5;
-    private static final int SUBKEY = 6;
-    private static final int SEQ_NUMBER = 7;
-    private static final int AUTHORIZATION_DATA = 8;
+
+    protected static enum MyEnum implements EnumType {
+        AUTHENTICATOR_VNO,
+        CREALM,
+        CNAME,
+        CKSUM,
+        CUSEC,
+        CTIME,
+        SUBKEY,
+        SEQ_NUMBER,
+        AUTHORIZATION_DATA;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(AUTHENTICATOR_VNO, 0, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/EncAPRepPart.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/EncAPRepPart.java
index 4a0f589..0e33dbf 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/EncAPRepPart.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ap/EncAPRepPart.java
@@ -20,11 +20,13 @@
 package org.apache.kerby.kerberos.kerb.type.ap;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosTime;
 import org.apache.kerby.kerberos.kerb.type.KrbAppSequenceType;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
+import static org.apache.kerby.kerberos.kerb.type.ap.EncAPRepPart.MyEnum.*;
 
 /**
  EncAPRepPart    ::= [APPLICATION 27] SEQUENCE {
@@ -36,10 +38,23 @@
  */
 public class EncAPRepPart extends KrbAppSequenceType {
     public static final int TAG = 27;
-    private static final int CTIME = 0;
-    private static final int CUSEC = 1;
-    private static final int SUBKEY = 2;
-    private static final int SEQ_NUMBER = 3;
+
+    protected static enum MyEnum implements EnumType {
+        CTIME,
+        CUSEC,
+        SUBKEY,
+        SEQ_NUMBER;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(CTIME, 0, KerberosTime.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/CheckSum.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/CheckSum.java
index f70c426..e8526a7 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/CheckSum.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/CheckSum.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.base.CheckSum.MyEnum.*;
 
 import java.util.Arrays;
 
@@ -34,8 +36,20 @@
  }
  */
 public class CheckSum extends KrbSequenceType {
-    private static final int CKSUM_TYPE = 0;
-    private static final int CHECK_SUM = 1;
+    protected static enum MyEnum implements EnumType {
+        CKSUM_TYPE,
+        CHECK_SUM;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(CKSUM_TYPE, 0, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/CheckSumType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/CheckSumType.java
index d52093e..c566f76 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/CheckSumType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/CheckSumType.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.base;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum CheckSumType implements Asn1EnumType {
+public enum CheckSumType implements EnumType {
     NONE(0, "none", "None checksum type"),
 
     CRC32(0x0001, "crc32", "CRC-32"),
@@ -80,7 +80,7 @@
 
     public static CheckSumType fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value) {
                     return (CheckSumType) e;
                 }
@@ -105,6 +105,7 @@
         return value;
     }
 
+    @Override
     public String getName() {
         return name;
     }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptedData.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptedData.java
index 57a5d2d..6e2f0d1 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptedData.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptedData.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.base.EncryptedData.MyEnum.*;
 
 import java.util.Arrays;
 
@@ -35,9 +37,21 @@
  }
  */
 public class EncryptedData extends KrbSequenceType {
-    private static final int ETYPE = 0;
-    private static final int KVNO = 1;
-    private static final int CIPHER = 2;
+    protected static enum MyEnum implements EnumType {
+        ETYPE,
+        KVNO,
+        CIPHER;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(ETYPE, 0, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptionKey.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptionKey.java
index 044c5c5..2b1bc1c 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptionKey.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptionKey.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.base.EncryptionKey.MyEnum.*;
 
 import java.util.Arrays;
 
@@ -34,8 +36,20 @@
  }
  */
 public class EncryptionKey extends KrbSequenceType {
-    private static final int KEY_TYPE = 0;
-    private static final int KEY_VALUE = 1;
+    protected static enum MyEnum implements EnumType {
+        KEY_TYPE,
+        KEY_VALUE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     private int kvno = -1;
 
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptionType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptionType.java
index 0154d55..29c4c23 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptionType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EncryptionType.java
@@ -19,12 +19,12 @@
  */
 package org.apache.kerby.kerberos.kerb.type.base;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
 /**
  * According to krb5.hin
  */
-public enum EncryptionType implements Asn1EnumType {
+public enum EncryptionType implements EnumType {
 
     NONE(0, "none", "None encryption type"),
 
@@ -118,7 +118,7 @@
 
     public static EncryptionType fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value) {
                     return (EncryptionType) e;
                 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EtypeInfo2Entry.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EtypeInfo2Entry.java
index 464f1b2..a367fd8 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EtypeInfo2Entry.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EtypeInfo2Entry.java
@@ -20,11 +20,13 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosString;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.base.EtypeInfo2Entry.MyEnum.*;
 
 /**
  ETYPE-INFO2-ENTRY       ::= SEQUENCE {
@@ -34,9 +36,21 @@
  }
  */
 public class EtypeInfo2Entry extends KrbSequenceType {
-    private static final int ETYPE = 0;
-    private static final int SALT = 1;
-    private static final int S2KPARAMS = 2;
+    protected static enum MyEnum implements EnumType {
+        ETYPE,
+        SALT,
+        S2KPARAMS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(ETYPE, 0, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EtypeInfoEntry.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EtypeInfoEntry.java
index 9c8d4ea..3b4a876 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EtypeInfoEntry.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/EtypeInfoEntry.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.base.EtypeInfoEntry.MyEnum.*;
 
 /**
  ETYPE-INFO-ENTRY        ::= SEQUENCE {
@@ -32,8 +34,20 @@
  }
  */
 public class EtypeInfoEntry extends KrbSequenceType {
-    private static final int ETYPE = 0;
-    private static final int SALT = 1;
+    protected static enum MyEnum implements EnumType {
+        ETYPE,
+        SALT;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(ETYPE, 0, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/HostAddrType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/HostAddrType.java
index b148bf6..8315690 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/HostAddrType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/HostAddrType.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.base;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum HostAddrType implements Asn1EnumType {
+public enum HostAddrType implements EnumType {
     /**
      * Constant for the "null" host address type.
      */
@@ -86,9 +86,14 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static HostAddrType fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value.intValue()) {
                     return (HostAddrType) e;
                 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/HostAddress.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/HostAddress.java
index 948bcc4..8a63911 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/HostAddress.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/HostAddress.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.base.HostAddress.MyEnum.*;
 
 import java.net.InetAddress;
 import java.util.Arrays;
@@ -35,8 +37,20 @@
 }
  */
 public class HostAddress extends KrbSequenceType {
-    private static final int ADDR_TYPE = 0;
-    private static final int ADDRESS = 1;
+    protected static enum MyEnum implements EnumType {
+        ADDR_TYPE,
+        ADDRESS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(ADDR_TYPE, 0, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KeyUsage.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KeyUsage.java
index 055977c..bf77407 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KeyUsage.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KeyUsage.java
@@ -19,12 +19,12 @@
  */
 package org.apache.kerby.kerberos.kerb.type.base;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
 /**
  * From krb5.hin
  */
-public enum KeyUsage implements Asn1EnumType {
+public enum KeyUsage implements EnumType {
     UNKNOWN(-1),
     NONE(0),
     //AS-REQ PA-ENC-TIMESTAMP padata timestamp, encrypted with the client key
@@ -112,9 +112,14 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static KeyUsage fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value) {
                     return (KeyUsage) e;
                 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbError.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbError.java
index 73b3e01..9bc1164 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbError.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbError.java
@@ -20,12 +20,14 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.KrbErrorCode;
 import org.apache.kerby.kerberos.kerb.type.KerberosString;
 import org.apache.kerby.kerberos.kerb.type.KerberosTime;
+import static org.apache.kerby.kerberos.kerb.type.base.KrbError.MyEnum.*;
 
 /**
  KRB-ERROR       ::= [APPLICATION 30] SEQUENCE {
@@ -45,17 +47,31 @@
  }
  */
 public class KrbError extends KrbMessage {
-    private static final int CTIME = 2;
-    private static final int CUSEC = 3;
-    private static final int STIME = 4;
-    private static final int SUSEC = 5;
-    private static final int ERROR_CODE = 6;
-    private static final int CREALM = 7;
-    private static final int CNAME = 8;
-    private static final int REALM = 9;
-    private static final int SNAME = 10;
-    private static final int ETEXT = 11;
-    private static final int EDATA = 12;
+    protected static enum MyEnum implements EnumType {
+        PVNO,
+        MSG_TYPE,
+        CTIME,
+        CUSEC,
+        STIME,
+        SUSEC,
+        ERROR_CODE,
+        CREALM,
+        CNAME,
+        REALM,
+        SNAME,
+        ETEXT,
+        EDATA;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(PVNO, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbMessage.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbMessage.java
index ffcccfb..b911088 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbMessage.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbMessage.java
@@ -20,12 +20,26 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.kerberos.kerb.KrbConstant;
 import org.apache.kerby.kerberos.kerb.type.KrbAppSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.base.KrbMessage.MyEnum.*;
 
 public abstract class KrbMessage extends KrbAppSequenceType {
-    protected static final int PVNO = 0;
-    protected static final int MSG_TYPE = 1;
+    protected static enum MyEnum implements EnumType {
+        PVNO,
+        MSG_TYPE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     private final int pvno = KrbConstant.KRB_V5;
 
@@ -40,7 +54,7 @@
     }
 
     protected void setPvno(int pvno) {
-        setFieldAsInt(0, pvno);
+        setFieldAsInt(PVNO, pvno);
     }
 
     public KrbMessageType getMsgType() {
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbMessageType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbMessageType.java
index d483838..b6f14d8 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbMessageType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbMessageType.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.base;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum KrbMessageType implements Asn1EnumType {
+public enum KrbMessageType implements EnumType {
     NONE(-1),
     AS_REQ(10),
     AS_REP(11),
@@ -45,9 +45,14 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static KrbMessageType fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value.intValue()) {
                     return (KrbMessageType) e;
                 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbToken.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbToken.java
index c2b8b76..72f8103 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbToken.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbToken.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
@@ -29,6 +30,7 @@
 import org.apache.kerby.kerberos.kerb.provider.TokenDecoder;
 import org.apache.kerby.kerberos.kerb.provider.TokenEncoder;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.base.KrbToken.MyEnum.*;
 
 import java.util.Date;
 import java.util.List;
@@ -44,8 +46,20 @@
     private static TokenEncoder tokenEncoder;
     private static TokenDecoder tokenDecoder;
 
-    private static final int TOKEN_FORMAT = 0;
-    private static final int TOKEN_VALUE = 1;
+    protected static enum MyEnum implements EnumType {
+        TOKEN_FORMAT,
+        TOKEN_VALUE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     private AuthToken innerToken = null;
 
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/LastReqEntry.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/LastReqEntry.java
index 4b1fff4..daaf66b 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/LastReqEntry.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/LastReqEntry.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosTime;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.base.LastReqEntry.MyEnum.*;
 
 /**
  LastReq         ::=     SEQUENCE OF SEQUENCE {
@@ -32,8 +34,20 @@
  }
  */
 public class LastReqEntry extends KrbSequenceType {
-    private static final int LR_TYPE = 0;
-    private static final int LR_VALUE = 1;
+    protected static enum MyEnum implements EnumType {
+        LR_TYPE,
+        LR_VALUE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(LR_TYPE, 0, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/LastReqType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/LastReqType.java
index 0353750..c68ea8c 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/LastReqType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/LastReqType.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.base;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum LastReqType implements Asn1EnumType {
+public enum LastReqType implements EnumType {
     NONE(0),
     ALL_LAST_TGT(1),
     THE_LAST_TGT(-1),
@@ -49,9 +49,14 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static LastReqType fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value) {
                     return (LastReqType) e;
                 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/NameType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/NameType.java
index d85b786..48c7755 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/NameType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/NameType.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.base;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum NameType implements Asn1EnumType {
+public enum NameType implements EnumType {
     NT_UNKNOWN(0),
     NT_PRINCIPAL(1),
     NT_SRV_INST(2),
@@ -40,9 +40,14 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static NameType fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value.intValue()) {
                     return (NameType) e;
                 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/PrincipalName.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/PrincipalName.java
index 1c94adc..d1c3162 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/PrincipalName.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/PrincipalName.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosStrings;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.base.PrincipalName.MyEnum.*;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -36,8 +38,21 @@
  }
  */
 public class PrincipalName extends KrbSequenceType {
-    private static final int NAME_TYPE = 0;
-    private static final int NAME_STRING = 1;
+    protected static enum MyEnum implements EnumType {
+        NAME_TYPE,
+        NAME_STRING;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
+
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(NAME_TYPE, Asn1Integer.class),
             new ExplicitField(NAME_STRING, KerberosStrings.class)
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/SamType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/SamType.java
index faa6e18..f9146f5 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/SamType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/SamType.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.base;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum SamType implements Asn1EnumType {
+public enum SamType implements EnumType {
     SAM_NONE(0),
     /** safe SAM type enum for Enigma Logic */
     SAM_TYPE_ENIGMA(1), // Enigma Logic"
@@ -52,6 +52,11 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static SamType fromValue(Integer value) {
         if (value != null) {
             for (SamType st : SamType.values()) {
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TokenFormat.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TokenFormat.java
index 15781b7..477b5be 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TokenFormat.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TokenFormat.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.base;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum TokenFormat implements Asn1EnumType {
+public enum TokenFormat implements EnumType {
     NONE                (0),
     JWT                 (1);
 
@@ -36,9 +36,14 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static TokenFormat fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value.intValue()) {
                     return (TokenFormat) e;
                 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TransitedEncoding.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TransitedEncoding.java
index 3b38ff9..b9c9e57 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TransitedEncoding.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TransitedEncoding.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.base;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.base.TransitedEncoding.MyEnum.*;
 
 /**
  TransitedEncoding       ::= SEQUENCE {
@@ -32,8 +34,20 @@
  }
  */
 public class TransitedEncoding extends KrbSequenceType {
-    private static final int TR_TYPE = 0;
-    private static final int CONTENTS = 1;
+    protected static enum MyEnum implements EnumType {
+        TR_TYPE,
+        CONTENTS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(TR_TYPE, 0, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TransitedEncodingType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TransitedEncodingType.java
index 744b643..ed988eb 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TransitedEncodingType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/TransitedEncodingType.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.base;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum TransitedEncodingType implements Asn1EnumType {
+public enum TransitedEncodingType implements EnumType {
     UNKNOWN(-1),
     NULL(0),
     DOMAIN_X500_COMPRESS(1);
@@ -37,9 +37,14 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static TransitedEncodingType fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value.intValue()) {
                     return (TransitedEncodingType) e;
                 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/ArmorType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/ArmorType.java
index 3331088..ac6129d 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/ArmorType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/ArmorType.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.fast;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum ArmorType implements Asn1EnumType {
+public enum ArmorType implements EnumType {
     NONE                (0),
     ARMOR_AP_REQUEST              (1);
 
@@ -36,9 +36,14 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static ArmorType fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value.intValue()) {
                     return (ArmorType) e;
                 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/FastOption.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/FastOption.java
index dc46d83..8330922 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/FastOption.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/FastOption.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.fast;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum FastOption implements Asn1EnumType {
+public enum FastOption implements EnumType {
     NONE(-1),
     RESERVED(0),
     HIDE_CLIENT_NAMES(1),
@@ -39,8 +39,13 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static FastOption fromValue(int value) {
-        for (Asn1EnumType e : values()) {
+        for (EnumType e : values()) {
             if (e.getValue() == value) {
                 return (FastOption) e;
             }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmor.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmor.java
index 0cde5f6..c111ae9 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmor.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmor.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.fast;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.fast.KrbFastArmor.MyEnum.*;
 
 /**
  KrbFastArmor ::= SEQUENCE {
@@ -34,8 +36,20 @@
  }
  */
 public class KrbFastArmor extends KrbSequenceType {
-    private static final int ARMOR_TYPE = 0;
-    private static final int ARMOR_VALUE = 1;
+    protected static enum MyEnum implements EnumType {
+        ARMOR_TYPE,
+        ARMOR_VALUE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(ARMOR_TYPE, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmoredRep.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmoredRep.java
index 0615a30..996f33d 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmoredRep.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmoredRep.java
@@ -20,9 +20,11 @@
 package org.apache.kerby.kerberos.kerb.type.fast;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptedData;
+import static org.apache.kerby.kerberos.kerb.type.fast.KrbFastArmoredRep.MyEnum.*;
 
 /**
  KrbFastArmoredRep ::= SEQUENCE {
@@ -32,7 +34,19 @@
  }
  */
 public class KrbFastArmoredRep extends KrbSequenceType {
-    private static final int ENC_FAST_REP = 0;
+    protected static enum MyEnum implements EnumType {
+        ENC_FAST_REP;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     //private
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmoredReq.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmoredReq.java
index aaa0d24..91a5ca9 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmoredReq.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastArmoredReq.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.fast;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.kerberos.kerb.type.base.CheckSum;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptedData;
+import static org.apache.kerby.kerberos.kerb.type.fast.KrbFastArmoredReq.MyEnum.*;
 
 /**
  KrbFastArmoredReq ::= SEQUENCE {
@@ -46,9 +48,21 @@
  }
  */
 public class KrbFastArmoredReq extends KrbSequenceType {
-    private static final int ARMOR = 0;
-    private static final int REQ_CHECKSUM = 1;
-    private static final int ENC_FAST_REQ = 2;
+    protected static enum MyEnum implements EnumType {
+        ARMOR,
+        REQ_CHECKSUM,
+        ENC_FAST_REQ;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     private KrbFastReq fastReq;
 
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastFinished.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastFinished.java
index 2944471..7ae6b07 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastFinished.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastFinished.java
@@ -20,11 +20,13 @@
 package org.apache.kerby.kerberos.kerb.type.fast;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.kerberos.kerb.type.base.CheckSum;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptedData;
 import org.apache.kerby.kerberos.kerb.type.pa.PaData;
+import static org.apache.kerby.kerberos.kerb.type.fast.KrbFastFinished.MyEnum.*;
 
 /**
  KrbFastFinished ::= SEQUENCE {
@@ -43,9 +45,21 @@
  }
  */
 public class KrbFastFinished extends KrbSequenceType {
-    private static final int FAST_OPTIONS = 0;
-    private static final int PADATA = 1;
-    private static final int REQ_BODY = 2;
+    protected static enum MyEnum implements EnumType {
+        FAST_OPTIONS,
+        PADATA,
+        REQ_BODY;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(FAST_OPTIONS, KrbFastArmor.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastReq.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastReq.java
index 0f7da88..eacbacf 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastReq.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastReq.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.fast;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.kerberos.kerb.type.kdc.KdcReqBody;
 import org.apache.kerby.kerberos.kerb.type.pa.PaData;
+import static org.apache.kerby.kerberos.kerb.type.fast.KrbFastReq.MyEnum.*;
 
 /**
  KrbFastReq ::= SEQUENCE {
@@ -39,9 +41,21 @@
  }
  */
 public class KrbFastReq extends KrbSequenceType {
-    private static final int FAST_OPTIONS = 0;
-    private static final int PADATA = 1;
-    private static final int REQ_BODY = 2;
+    protected static enum MyEnum implements EnumType {
+        FAST_OPTIONS,
+        PADATA,
+        REQ_BODY;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(FAST_OPTIONS, FastOptions.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastResponse.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastResponse.java
index cd06c42..134e7d6 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastResponse.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/KrbFastResponse.java
@@ -20,11 +20,13 @@
 package org.apache.kerby.kerberos.kerb.type.fast;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
 import org.apache.kerby.kerberos.kerb.type.pa.PaData;
+import static org.apache.kerby.kerberos.kerb.type.fast.KrbFastResponse.MyEnum.*;
 
 /**
  KrbFastResponse ::= SEQUENCE {
@@ -41,10 +43,22 @@
  }
  */
 public class KrbFastResponse extends KrbSequenceType {
-    private static final int PADATA = 0;
-    private static final int STRENGTHEN_KEY = 1;
-    private static final int FINISHED = 2;
-    private static final int NONCE = 3;
+    protected static enum MyEnum implements EnumType {
+        PADATA,
+        STRENGTHEN_KEY,
+        FINISHED,
+        NONCE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(PADATA, PaData.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaAuthnEntry.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaAuthnEntry.java
index 8494ef9..ed0a29d 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaAuthnEntry.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaAuthnEntry.java
@@ -20,11 +20,13 @@
 package org.apache.kerby.kerberos.kerb.type.fast;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.kerberos.kerb.type.pa.PaDataType;
+import static org.apache.kerby.kerberos.kerb.type.fast.PaAuthnEntry.MyEnum.*;
 
 /**
  PA-AUTHENTICATION-SET-ELEM ::= SEQUENCE {
@@ -34,9 +36,21 @@
  }
  */
 public class PaAuthnEntry extends KrbSequenceType {
-    private static final int PA_TYPE = 0;
-    private static final int PA_HINT = 1;
-    private static final int PA_VALUE = 2;
+    protected static enum MyEnum implements EnumType {
+        PA_TYPE,
+        PA_HINT,
+        PA_VALUE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(PA_TYPE, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaFxFastReply.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaFxFastReply.java
index f3966f6..33b5863 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaFxFastReply.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaFxFastReply.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.kerberos.kerb.type.fast;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.kerberos.kerb.type.fast.PaFxFastReply.MyEnum.*;
 
 /**
  PA-FX-FAST-REPLY ::= CHOICE {
@@ -29,7 +31,19 @@
  }
  */
 public class PaFxFastReply extends Asn1Choice {
-    private static final int ARMORED_DATA = 0;
+    protected static enum MyEnum implements EnumType {
+        ARMORED_DATA;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(ARMORED_DATA, KrbFastArmoredRep.class)
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaFxFastRequest.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaFxFastRequest.java
index a1b26c7..865074e 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaFxFastRequest.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/fast/PaFxFastRequest.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.kerberos.kerb.type.fast;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.kerberos.kerb.type.fast.PaFxFastRequest.MyEnum.*;
 
 /**
  PA-FX-FAST-REQUEST ::= CHOICE {
@@ -29,7 +31,19 @@
  }
  */
 public class PaFxFastRequest extends Asn1Choice {
-    private static final int ARMORED_DATA = 0;
+    protected static enum MyEnum implements EnumType {
+        ARMORED_DATA;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(ARMORED_DATA, KrbFastArmoredReq.class)
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/EncKdcRepPart.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/EncKdcRepPart.java
index d363ca7..59ced72 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/EncKdcRepPart.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/EncKdcRepPart.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kerb.type.kdc;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosString;
@@ -30,6 +31,7 @@
 import org.apache.kerby.kerberos.kerb.type.base.LastReq;
 import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
 import org.apache.kerby.kerberos.kerb.type.ticket.TicketFlags;
+import static org.apache.kerby.kerberos.kerb.type.kdc.EncKdcRepPart.MyEnum.*;
 
 /**
  EncKDCRepPart   ::= SEQUENCE {
@@ -48,18 +50,30 @@
  }
  */
 public abstract class EncKdcRepPart extends KrbAppSequenceType {
-    private static final int KEY = 0;
-    private static final int LAST_REQ = 1;
-    private static final int NONCE = 2;
-    private static final int KEY_EXPIRATION = 3;
-    private static final int FLAGS = 4;
-    private static final int AUTHTIME = 5;
-    private static final int STARTTIME = 6;
-    private static final int ENDTIME = 7;
-    private static final int RENEW_TILL = 8;
-    private static final int SREALM = 9;
-    private static final int SNAME = 10;
-    private static final int CADDR = 11;
+    protected static enum MyEnum implements EnumType {
+        KEY,
+        LAST_REQ,
+        NONCE,
+        KEY_EXPIRATION,
+        FLAGS,
+        AUTHTIME,
+        STARTTIME,
+        ENDTIME,
+        RENEW_TILL,
+        SREALM,
+        SNAME,
+        CADDR;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(KEY, EncryptionKey.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcOption.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcOption.java
index ef6261d..7e44c96 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcOption.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcOption.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.kdc;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum KdcOption implements Asn1EnumType {
+public enum KdcOption implements EnumType {
     NONE(-1),
     //RESERVED(0x80000000),
     FORWARDABLE(0x40000000),
@@ -67,8 +67,13 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static KdcOption fromValue(int value) {
-        for (Asn1EnumType e : values()) {
+        for (EnumType e : values()) {
             if (e.getValue() == value) {
                 return (KdcOption) e;
             }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcRep.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcRep.java
index 9d0bd88..9d01c23 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcRep.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcRep.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kerb.type.kdc;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosString;
@@ -29,6 +30,7 @@
 import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
 import org.apache.kerby.kerberos.kerb.type.pa.PaData;
 import org.apache.kerby.kerberos.kerb.type.ticket.Ticket;
+import static org.apache.kerby.kerberos.kerb.type.kdc.KdcRep.MyEnum.*;
 
 /**
  KDC-REP         ::= SEQUENCE {
@@ -45,11 +47,25 @@
  }
  */
 public class KdcRep extends KrbMessage {
-    private static final int PADATA = 2;
-    private static final int CREALM = 3;
-    private static final int CNAME = 4;
-    private static final int TICKET = 5;
-    private static final int ENC_PART = 6;
+    protected static enum MyEnum implements EnumType {
+        PVNO,
+        MSG_TYPE,
+        PADATA,
+        CREALM,
+        CNAME,
+        TICKET,
+        ENC_PART;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(PVNO, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcReq.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcReq.java
index 98b2d80..cb1a13e 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcReq.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcReq.java
@@ -20,12 +20,14 @@
 package org.apache.kerby.kerberos.kerb.type.kdc;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.base.KrbMessage;
 import org.apache.kerby.kerberos.kerb.type.base.KrbMessageType;
 import org.apache.kerby.kerberos.kerb.type.pa.PaData;
 import org.apache.kerby.kerberos.kerb.type.pa.PaDataEntry;
+import static org.apache.kerby.kerberos.kerb.type.kdc.KdcReq.MyEnum.*;
 
 /**
  KDC-REQ         ::= SEQUENCE {
@@ -38,8 +40,22 @@
  }
  */
 public class KdcReq extends KrbMessage {
-    private static final int PADATA = 2;
-    private static final int REQ_BODY = 3;
+    protected static enum MyEnum implements EnumType {
+        PVNO,
+        MSG_TYPE,
+        PADATA,
+        REQ_BODY;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(PVNO, 1, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcReqBody.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcReqBody.java
index f7a23c1..f8fda13 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcReqBody.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/kdc/KdcReqBody.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kerb.type.kdc;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosString;
@@ -32,6 +33,7 @@
 import org.apache.kerby.kerberos.kerb.type.base.HostAddresses;
 import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
 import org.apache.kerby.kerberos.kerb.type.ticket.Tickets;
+import static org.apache.kerby.kerberos.kerb.type.kdc.KdcReqBody.MyEnum.*;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -60,18 +62,30 @@
  }
  */
 public class KdcReqBody extends KrbSequenceType {
-    private static final int KDC_OPTIONS = 0;
-    private static final int CNAME = 1;
-    private static final int REALM = 2;
-    private static final int SNAME = 3;
-    private static final int FROM = 4;
-    private static final int TILL = 5;
-    private static final int RTIME = 6;
-    private static final int NONCE = 7;
-    private static final int ETYPE = 8;
-    private static final int ADDRESSES = 9;
-    private static final int ENC_AUTHORIZATION_DATA = 10;
-    private static final int ADDITIONAL_TICKETS = 11;
+    protected static enum MyEnum implements EnumType {
+        KDC_OPTIONS,
+        CNAME,
+        REALM,
+        SNAME,
+        FROM,
+        TILL,
+        RTIME,
+        NONCE,
+        ETYPE,
+        ADDRESSES,
+        ENC_AUTHORIZATION_DATA,
+        ADDITIONAL_TICKETS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(KDC_OPTIONS, KdcOptions.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaAuthenticationSetElem.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaAuthenticationSetElem.java
index 83b390e..0594bd2 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaAuthenticationSetElem.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaAuthenticationSetElem.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.pa;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.pa.PaAuthenticationSetElem.MyEnum.*;
 
 /**
  PA-AUTHENTICATION-SET-ELEM ::= SEQUENCE {
@@ -34,9 +36,21 @@
  }
  */
 public class PaAuthenticationSetElem extends KrbSequenceType {
-    private static final int PA_TYPE = 0;
-    private static final int PA_HINT = 1;
-    private static final int PA_VALUE = 2;
+    protected static enum MyEnum implements EnumType {
+        PA_TYPE,
+        PA_HINT,
+        PA_VALUE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(PA_TYPE, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaDataEntry.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaDataEntry.java
index ea2f131..1cf75ec 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaDataEntry.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaDataEntry.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.pa;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.pa.PaDataEntry.MyEnum.*;
 
 /**
  PA-DATA         ::= SEQUENCE {
@@ -33,8 +35,20 @@
  }
  */
 public class PaDataEntry extends KrbSequenceType {
-    private static final int PADATA_TYPE = 0;
-    private static final int PADATA_VALUE = 1;
+    protected static enum MyEnum implements EnumType {
+        PADATA_TYPE,
+        PADATA_VALUE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(PADATA_TYPE, 1, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaDataType.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaDataType.java
index da3807e..06e0db2 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaDataType.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaDataType.java
@@ -19,12 +19,12 @@
  */
 package org.apache.kerby.kerberos.kerb.type.pa;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
 /**
  * From krb5.h
  */
-public enum PaDataType implements Asn1EnumType {
+public enum PaDataType implements EnumType {
     NONE                (0),
     TGS_REQ              (1),
     AP_REQ              (1),
@@ -78,9 +78,14 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static PaDataType fromValue(Integer value) {
         if (value != null) {
-            for (Asn1EnumType e : values()) {
+            for (EnumType e : values()) {
                 if (e.getValue() == value.intValue()) {
                     return (PaDataType) e;
                 }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaEncTsEnc.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaEncTsEnc.java
index 4ffff7c..b7cf263 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaEncTsEnc.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/PaEncTsEnc.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.pa;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosTime;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.pa.PaEncTsEnc.MyEnum.*;
 
 /**
  PA-ENC-TS-ENC           ::= SEQUENCE {
@@ -32,8 +34,20 @@
  }
  */
 public class PaEncTsEnc extends KrbSequenceType {
-    private static final int PATIMESTAMP = 0;
-    private static final int PAUSEC = 1;
+    protected static enum MyEnum implements EnumType {
+        PATIMESTAMP,
+        PAUSEC;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(PATIMESTAMP, 0, KerberosTime.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/otp/OtpTokenInfo.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/otp/OtpTokenInfo.java
index 900d2d2..6e3da3d 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/otp/OtpTokenInfo.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/otp/OtpTokenInfo.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kerb.type.pa.otp;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.type.Asn1Utf8String;
@@ -27,6 +28,7 @@
 import org.apache.kerby.kerberos.kerb.type.KerberosString;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.kerberos.kerb.type.pa.pkinit.AlgorithmIdentifiers;
+import static org.apache.kerby.kerberos.kerb.type.pa.otp.OtpTokenInfo.MyEnum.*;
 
 /**
  OTP-TOKENINFO ::= SEQUENCE {
@@ -42,15 +44,27 @@
  }
  */
 public class OtpTokenInfo extends KrbSequenceType {
-    private static final int FLAGS = 0;
-    private static final int OTP_VENDOR = 1;
-    private static final int OTP_CHALLENGE = 2;
-    private static final int OTP_LENGTH = 3;
-    private static final int OTP_FORMAT = 4;
-    private static final int OTP_TOKEN_ID = 5;
-    private static final int OTP_ALG_ID = 6;
-    private static final int SUPPORTED_HASH_ALG = 7;
-    private static final int ITERATION_COUNT = 8;
+    protected static enum MyEnum implements EnumType {
+        FLAGS,
+        OTP_VENDOR,
+        OTP_CHALLENGE,
+        OTP_LENGTH,
+        OTP_FORMAT,
+        OTP_TOKEN_ID,
+        OTP_ALG_ID,
+        SUPPORTED_HASH_ALG,
+        ITERATION_COUNT;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(FLAGS, Asn1OctetString.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/otp/PaOtpChallenge.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/otp/PaOtpChallenge.java
index cbf245c..f5e58f6 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/otp/PaOtpChallenge.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/otp/PaOtpChallenge.java
@@ -20,11 +20,13 @@
 package org.apache.kerby.kerberos.kerb.type.pa.otp;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.type.Asn1Utf8String;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosString;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.pa.otp.PaOtpChallenge.MyEnum.*;
 
 /**
  PA-OTP-CHALLENGE ::= SEQUENCE {
@@ -36,11 +38,23 @@
  }
  */
 public class PaOtpChallenge extends KrbSequenceType {
-    private static final int NONCE = 0;
-    private static final int OTP_SERVICE = 1;
-    private static final int OTP_TOKEN_INFO = 2;
-    private static final int SALT = 3;
-    private static final int S2KPARAMS = 4;
+    protected static enum MyEnum implements EnumType {
+        NONCE,
+        OTP_SERVICE,
+        OTP_TOKEN_INFO,
+        SALT,
+        S2KPARAMS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(NONCE, Asn1OctetString.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/AuthPack.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/AuthPack.java
index c387674..60e4f65 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/AuthPack.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/AuthPack.java
@@ -20,9 +20,11 @@
 package org.apache.kerby.kerberos.kerb.type.pa.pkinit;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.x509.type.SubjectPublicKeyInfo;
+import static org.apache.kerby.kerberos.kerb.type.pa.pkinit.AuthPack.MyEnum.*;
 
 /**
  AuthPack ::= SEQUENCE {
@@ -33,10 +35,22 @@
  }
  */
 public class AuthPack extends KrbSequenceType {
-    private static final int PK_AUTHENTICATOR = 0;
-    private static final int CLIENT_PUBLIC_VALUE = 1;
-    private static final int SUPPORTED_CMS_TYPES = 2;
-    private static final int CLIENT_DH_NONCE = 3;
+    protected static enum MyEnum implements EnumType {
+        PK_AUTHENTICATOR,
+        CLIENT_PUBLIC_VALUE,
+        SUPPORTED_CMS_TYPES,
+        CLIENT_DH_NONCE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(PK_AUTHENTICATOR, PkAuthenticator.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/DHRepInfo.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/DHRepInfo.java
index 1ca5697..abb0d57 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/DHRepInfo.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/DHRepInfo.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.pa.pkinit;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.asn1.ImplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.pa.pkinit.DHRepInfo.MyEnum.*;
 
 /**
  DHRepInfo ::= SEQUENCE {
@@ -32,8 +34,20 @@
  }
  */
 public class DHRepInfo extends KrbSequenceType {
-    private static final int DH_SIGNED_DATA = 0;
-    private static final int SERVER_DH_NONCE = 1;
+    protected static enum MyEnum implements EnumType {
+        DH_SIGNED_DATA,
+        SERVER_DH_NONCE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ImplicitField(DH_SIGNED_DATA, Asn1OctetString.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/ExternalPrincipalIdentifier.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/ExternalPrincipalIdentifier.java
index d686773..27f84e9 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/ExternalPrincipalIdentifier.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/ExternalPrincipalIdentifier.java
@@ -20,9 +20,11 @@
 package org.apache.kerby.kerberos.kerb.type.pa.pkinit;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ImplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.pa.pkinit.ExternalPrincipalIdentifier.MyEnum.*;
 
 /**
  ExternalPrincipalIdentifier ::= SEQUENCE {
@@ -32,9 +34,21 @@
  }
  */
 public class ExternalPrincipalIdentifier extends KrbSequenceType {
-    private static final int SUBJECT_NAME = 0;
-    private static final int ISSUER_AND_SERIAL_NUMBER = 1;
-    private static final int SUBJECT_KEY_IDENTIFIER = 2;
+    protected static enum MyEnum implements EnumType {
+        SUBJECT_NAME,
+        ISSUER_AND_SERIAL_NUMBER,
+        SUBJECT_KEY_IDENTIFIER;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ImplicitField(SUBJECT_NAME, Asn1OctetString.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/KdcDHKeyInfo.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/KdcDHKeyInfo.java
index 7437f8d..f3669eb 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/KdcDHKeyInfo.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/KdcDHKeyInfo.java
@@ -19,12 +19,14 @@
  */
 package org.apache.kerby.kerberos.kerb.type.pa.pkinit;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosTime;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.pa.pkinit.KdcDHKeyInfo.MyEnum.*;
 
 /**
  KDCDHKeyInfo ::= SEQUENCE {
@@ -34,9 +36,21 @@
  }
  */
 public class KdcDHKeyInfo extends KrbSequenceType {
-    private static final int SUBJECT_PUBLICK_KEY = 0;
-    private static final int NONCE = 1;
-    private static final int DH_KEY_EXPIRATION = 2;
+    protected static enum MyEnum implements EnumType {
+        SUBJECT_PUBLICK_KEY,
+        NONCE,
+        DH_KEY_EXPIRATION;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(SUBJECT_PUBLICK_KEY, Asn1BitString.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/Krb5PrincipalName.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/Krb5PrincipalName.java
index 4f131a4..81cde21 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/Krb5PrincipalName.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/Krb5PrincipalName.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.pa.pkinit;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
 import org.apache.kerby.kerberos.kerb.type.base.Realm;
+import static org.apache.kerby.kerberos.kerb.type.pa.pkinit.Krb5PrincipalName.MyEnum.*;
 
 /**
  KRB5PrincipalName ::= SEQUENCE {
@@ -32,8 +34,20 @@
  }
  */
 public class Krb5PrincipalName extends KrbSequenceType {
-    private static final int REALM = 0;
-    private static final int PRINCIPAL_NAME = 1;
+    protected static enum MyEnum implements EnumType {
+        REALM,
+        PRINCIPAL_NAME;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(REALM, Realm.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PaPkAsRep.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PaPkAsRep.java
index 204b612..3d3ed3c 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PaPkAsRep.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PaPkAsRep.java
@@ -19,11 +19,13 @@
  */
 package org.apache.kerby.kerberos.kerb.type.pa.pkinit;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.asn1.ImplicitField;
+import static org.apache.kerby.kerberos.kerb.type.pa.pkinit.PaPkAsRep.MyEnum.*;
 
 /**
  PA-PK-AS-REP ::= CHOICE {
@@ -32,8 +34,20 @@
  }
  */
 public class PaPkAsRep extends Asn1Choice {
-    private static final int DH_INFO = 0;
-    private static final int ENCKEY_PACK = 1;
+    protected static enum MyEnum implements EnumType {
+        DH_INFO,
+        ENCKEY_PACK;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(DH_INFO, DHRepInfo.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PaPkAsReq.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PaPkAsReq.java
index 1d59112..ed6ebac 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PaPkAsReq.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PaPkAsReq.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.pa.pkinit;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.asn1.ImplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.pa.pkinit.PaPkAsReq.MyEnum.*;
 
 /**
  PA-PK-AS-REQ ::= SEQUENCE {
@@ -33,9 +35,21 @@
  }
  */
 public class PaPkAsReq extends KrbSequenceType {
-    private static final int SIGNED_AUTH_PACK = 0;
-    private static final int TRUSTED_CERTIFIERS = 1;
-    private static final int KDC_PKID = 2;
+    protected static enum MyEnum implements EnumType {
+        SIGNED_AUTH_PACK,
+        TRUSTED_CERTIFIERS,
+        KDC_PKID;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ImplicitField(SIGNED_AUTH_PACK, Asn1OctetString.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PkAuthenticator.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PkAuthenticator.java
index 4549552..9f5b8b1 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PkAuthenticator.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/PkAuthenticator.java
@@ -20,11 +20,13 @@
 package org.apache.kerby.kerberos.kerb.type.pa.pkinit;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosTime;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.pa.pkinit.PkAuthenticator.MyEnum.*;
 
 /**
  PKAuthenticator ::= SEQUENCE {
@@ -42,10 +44,22 @@
  }
  */
 public class PkAuthenticator extends KrbSequenceType {
-    private static final int CUSEC = 0;
-    private static final int CTIME = 1;
-    private static final int NONCE = 2;
-    private static final int PA_CHECKSUM = 3;
+    protected static enum MyEnum implements EnumType {
+        CUSEC,
+        CTIME,
+        NONCE,
+        PA_CHECKSUM;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(CUSEC, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/ReplyKeyPack.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/ReplyKeyPack.java
index 8baa470..f219c47 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/ReplyKeyPack.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/pkinit/ReplyKeyPack.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.pa.pkinit;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.kerberos.kerb.type.base.CheckSum;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
+import static org.apache.kerby.kerberos.kerb.type.pa.pkinit.ReplyKeyPack.MyEnum.*;
 
 /**
  ReplyKeyPack ::= SEQUENCE {
@@ -32,8 +34,20 @@
  }
  */
 public class ReplyKeyPack extends KrbSequenceType {
-    private static final int REPLY_KEY = 0;
-    private static final int AS_CHECKSUM = 1;
+    protected static enum MyEnum implements EnumType {
+        REPLY_KEY,
+        AS_CHECKSUM;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(REPLY_KEY, EncryptionKey.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/PaTokenChallenge.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/PaTokenChallenge.java
index 77bd369..ff94b95 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/PaTokenChallenge.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/PaTokenChallenge.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.kerberos.kerb.type.pa.token;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.pa.token.PaTokenChallenge.MyEnum.*;
 
 /**
  PA-TOKEN-CHALLENGE ::= SEQUENCE {
@@ -29,7 +31,19 @@
  }
 */
 public class PaTokenChallenge extends KrbSequenceType {
-    private static final int TOKENINFOS = 0;
+    protected static enum MyEnum implements EnumType {
+        TOKENINFOS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(TOKENINFOS, TokenInfos.class)
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/PaTokenRequest.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/PaTokenRequest.java
index 0b99fe2..9d5d730 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/PaTokenRequest.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/PaTokenRequest.java
@@ -20,9 +20,11 @@
 package org.apache.kerby.kerberos.kerb.type.pa.token;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
 import org.apache.kerby.kerberos.kerb.type.base.KrbToken;
+import static org.apache.kerby.kerberos.kerb.type.pa.token.PaTokenRequest.MyEnum.*;
 
 /**
  PA-TOKEN-REQUEST ::= SEQUENCE {
@@ -31,8 +33,20 @@
  }
 */
 public class PaTokenRequest extends KrbSequenceType {
-    private static final int TOKEN_INFO = 0;
-    private static final int TOKEN = 1;
+    protected static enum MyEnum implements EnumType {
+        TOKEN_INFO,
+        TOKEN;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(TOKEN_INFO, TokenInfo.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/TokenFlag.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/TokenFlag.java
index 037d7eb..a4f2211 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/TokenFlag.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/TokenFlag.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.pa.token;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum TokenFlag implements Asn1EnumType {
+public enum TokenFlag implements EnumType {
     NONE(-1),
     ID_TOKEN_REQUIRED(0x40000000),
     AC_TOKEN_REQUIRED(0x20000000),
@@ -39,8 +39,13 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static TokenFlag fromValue(int value) {
-        for (Asn1EnumType e : values()) {
+        for (EnumType e : values()) {
             if (e.getValue() == value) {
                 return (TokenFlag) e;
             }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/TokenInfo.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/TokenInfo.java
index 0acc254..1d4173c 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/TokenInfo.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/pa/token/TokenInfo.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.kerberos.kerb.type.pa.token;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.type.Asn1Utf8String;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KrbSequenceType;
+import static org.apache.kerby.kerberos.kerb.type.pa.token.TokenInfo.MyEnum.*;
 
 /**
  TokenInfo ::= SEQUENCE {
@@ -32,8 +34,20 @@
  }
  */
 public class TokenInfo extends KrbSequenceType {
-    private static final int FLAGS = 0;
-    private static final int TOKEN_VENDOR = 1;
+    protected static enum MyEnum implements EnumType {
+        FLAGS,
+        TOKEN_VENDOR;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(FLAGS, Asn1OctetString.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/EncTicketPart.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/EncTicketPart.java
index 40c4473..16b56d0 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/EncTicketPart.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/EncTicketPart.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kerb.type.ticket;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.type.KerberosString;
 import org.apache.kerby.kerberos.kerb.type.KerberosTime;
@@ -29,6 +30,7 @@
 import org.apache.kerby.kerberos.kerb.type.base.HostAddresses;
 import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
 import org.apache.kerby.kerberos.kerb.type.base.TransitedEncoding;
+import static org.apache.kerby.kerberos.kerb.type.ticket.EncTicketPart.MyEnum.*;
 
 /**
  -- Encrypted part of ticket
@@ -49,17 +51,29 @@
 public class EncTicketPart extends KrbAppSequenceType {
     public static final int TAG = 3;
 
-    private static final int FLAGS = 0;
-    private static final int KEY = 1;
-    private static final int CREALM = 2;
-    private static final int CNAME = 3;
-    private static final int TRANSITED = 4;
-    private static final int AUTHTIME = 5;
-    private static final int STARTTIME = 6;
-    private static final int ENDTIME = 7;
-    private static final int RENEW_TILL = 8;
-    private static final int CADDR = 9;
-    private static final int AUTHORIZATION_DATA = 10;
+    protected static enum MyEnum implements EnumType {
+        FLAGS,
+        KEY,
+        CREALM,
+        CNAME,
+        TRANSITED,
+        AUTHTIME,
+        STARTTIME,
+        ENDTIME,
+        RENEW_TILL,
+        CADDR,
+        AUTHORIZATION_DATA;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(FLAGS, 0, TicketFlags.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/Ticket.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/Ticket.java
index 1855e37..bf6a65c 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/Ticket.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/Ticket.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kerb.type.ticket;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.kerberos.kerb.KrbConstant;
@@ -27,6 +28,7 @@
 import org.apache.kerby.kerberos.kerb.type.KrbAppSequenceType;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptedData;
 import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
+import static org.apache.kerby.kerberos.kerb.type.ticket.Ticket.MyEnum.*;
 
 /**
  Ticket          ::= [APPLICATION 1] SEQUENCE {
@@ -40,10 +42,22 @@
     public static final int TKT_KVNO = KrbConstant.KRB_V5;
     public static final int TAG = 1;
 
-    private static final int TKT_VNO = 0;
-    private static final int REALM = 1;
-    private static final int SNAME = 2;
-    private static final int ENC_PART = 3;
+    protected static enum MyEnum implements EnumType {
+        TKT_VNO,
+        REALM,
+        SNAME,
+        ENC_PART;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(TKT_VNO, 0, Asn1Integer.class),
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/TicketFlag.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/TicketFlag.java
index e2e99a8..942af84 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/TicketFlag.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/ticket/TicketFlag.java
@@ -19,9 +19,9 @@
  */
 package org.apache.kerby.kerberos.kerb.type.ticket;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 
-public enum TicketFlag implements Asn1EnumType {
+public enum TicketFlag implements EnumType {
     NONE(-1),
     FORWARDABLE(0x40000000),
     FORWARDED(0x20000000),
@@ -50,8 +50,13 @@
         return value;
     }
 
+    @Override
+    public String getName() {
+        return name();
+    }
+
     public static TicketFlag fromValue(int value) {
-        for (Asn1EnumType e : values()) {
+        for (EnumType e : values()) {
             if (e.getValue() == value) {
                 return (TicketFlag) e;
             }
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Attribute.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Attribute.java
index 1eabefe..cdc3a27 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Attribute.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Attribute.java
@@ -20,9 +20,11 @@
 package org.apache.kerby.cms.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.x509.type.AttributeValues;
+import static org.apache.kerby.cms.type.Attribute.MyEnum.*;
 
 /**
  * Ref. RFC 5652
@@ -36,8 +38,20 @@
  * </pre>
  */
 public class Attribute extends Asn1SequenceType {
-    private static final int ATTR_TYPE = 0;
-    private static final int ATTR_VALUES = 1;
+    protected static enum MyEnum implements EnumType {
+        ATTR_TYPE,
+        ATTR_VALUES;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
         new Asn1FieldInfo(ATTR_TYPE, Asn1ObjectIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/AttributeCertificateInfoV1.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/AttributeCertificateInfoV1.java
index e1796e9..f0a5e39 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/AttributeCertificateInfoV1.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/AttributeCertificateInfoV1.java
@@ -19,6 +19,7 @@
  */
 package org.apache.kerby.cms.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1Integer;
@@ -29,6 +30,7 @@
 import org.apache.kerby.x509.type.Attributes;
 import org.apache.kerby.x509.type.CertificateSerialNumber;
 import org.apache.kerby.x509.type.Extensions;
+import static org.apache.kerby.cms.type.AttributeCertificateInfoV1.MyEnum.*;
 
 /**
  * AttributeCertificateInfoV1 ::= SEQUENCE {
@@ -46,16 +48,27 @@
  * AttCertVersionV1 ::= INTEGER { v1(0) }
  */
 public class AttributeCertificateInfoV1 extends Asn1SequenceType {
+    protected static enum MyEnum implements EnumType {
+        VERSION,
+        SUBJECT,
+        ISSUER,
+        SIGNATURE,
+        SERIAL_NUMBER,
+        ATTR_CERT_VALIDITY_PERIOD,
+        ATTRIBUTES,
+        ISSUER_UNIQUE_ID,
+        EXTENSIONS;
 
-    private static final int VERSION = 0;
-    private static final int SUBJECT = 1;
-    private static final int ISSUER = 2;
-    private static final int SIGNATURE = 3;
-    private static final int SERIAL_NUMBER = 4;
-    private static final int ATTR_CERT_VALIDITY_PERIOD = 5;
-    private static final int ATTRIBUTES = 6;
-    private static final int ISSUER_UNIQUE_ID = 7;
-    private static final int EXTENSIONS = 8;
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(VERSION, Asn1Integer.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/AttributeCertificateV1.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/AttributeCertificateV1.java
index c45a76f..a1aa414 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/AttributeCertificateV1.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/AttributeCertificateV1.java
@@ -19,11 +19,13 @@
  */
 package org.apache.kerby.cms.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.x509.type.AlgorithmIdentifier;
 import org.apache.kerby.x509.type.AttributeCertificateInfo;
+import static org.apache.kerby.cms.type.AttributeCertificateV1.MyEnum.*;
 
 /**
  * AttributeCertificateV1 ::= SEQUENCE {
@@ -33,9 +35,21 @@
  * }
  */
 public class AttributeCertificateV1 extends Asn1SequenceType {
-    private static final int ACI_INFO = 0;
-    private static final int SIGNATURE_ALGORITHM = 1;
-    private static final int SIGNATURE = 2;
+    protected static enum MyEnum implements EnumType {
+        ACI_INFO,
+        SIGNATURE_ALGORITHM,
+        SIGNATURE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(ACI_INFO, AttributeCertificateInfoV1.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Certificate.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Certificate.java
index 46e625b..fd15ee7 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Certificate.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Certificate.java
@@ -19,11 +19,13 @@
  */
 package org.apache.kerby.cms.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.x509.type.AlgorithmIdentifier;
 import org.apache.kerby.x509.type.TBSCertificate;
+import static org.apache.kerby.cms.type.Certificate.MyEnum.*;
 
 /**
  * <pre>
@@ -35,10 +37,21 @@
  * </pre>
  */
 public class Certificate extends Asn1SequenceType {
+    protected static enum MyEnum implements EnumType {
+        TBS_CERTIFICATE,
+        SIGNATURE_ALGORITHM,
+        SIGNATURE;
 
-    private static final int TBS_CERTIFICATE = 0;
-    private static final int SIGNATURE_ALGORITHM = 1;
-    private static final int SIGNATURE = 2;
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(TBS_CERTIFICATE, TBSCertificate.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CertificateChoices.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CertificateChoices.java
index 598c896..91b1930 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CertificateChoices.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CertificateChoices.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.cms.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.ImplicitField;
+import static org.apache.kerby.cms.type.CertificateChoices.MyEnum.*;
 
 /**
  * CertificateChoices ::= CHOICE {
@@ -32,12 +34,23 @@
  *   other [3] IMPLICIT OtherCertificateFormat }
  */
 public class CertificateChoices extends Asn1Choice {
+    protected static enum MyEnum implements EnumType {
+        CERTIFICATE,
+        EXTENDED_CERTIFICATE,
+        V1_ATTR_CERT,
+        V2_ATTR_CERT,
+        OTHER;
 
-    private static final int CERTIFICATE = 0;
-    private static final int EXTENDED_CERTIFICATE = 1;
-    private static final int V1_ATTR_CERT = 2;
-    private static final int V2_ATTR_CERT = 3;
-    private static final int OTHER = 4;
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(CERTIFICATE, Certificate.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CertificateList.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CertificateList.java
index 8502ca6..c7dd0dd 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CertificateList.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CertificateList.java
@@ -19,11 +19,13 @@
  */
 package org.apache.kerby.cms.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.x509.type.AlgorithmIdentifier;
 import org.apache.kerby.x509.type.TBSCertList;
+import static org.apache.kerby.cms.type.CertificateList.MyEnum.*;
 
 /**
  * Ref. RFC-2459
@@ -37,9 +39,21 @@
  * </pre>
  */
 public class CertificateList extends Asn1SequenceType {
-    private static final int TBS_CERT_LIST = 0;
-    private static final int SIGNATURE_ALGORITHMS = 1;
-    private static final int SIGNATURE_VALUE = 2;
+    protected static enum MyEnum implements EnumType {
+        TBS_CERT_LIST,
+        SIGNATURE_ALGORITHMS,
+        SIGNATURE_VALUE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(TBS_CERT_LIST, TBSCertList.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CmsVersion.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CmsVersion.java
index bde3992..e1f1f8f 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CmsVersion.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CmsVersion.java
@@ -19,7 +19,7 @@
  */
 package org.apache.kerby.cms.type;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 
 /**
@@ -27,7 +27,7 @@
  * { v0(0), v1(1), v2(2), v3(3), v4(4), v5(5) }
  */
 
-enum CmsVersionEnum implements Asn1EnumType {
+enum CmsVersionEnum implements EnumType {
     V0,
     V1,
     V2,
@@ -39,6 +39,11 @@
     public int getValue() {
         return ordinal();
     }
+
+    @Override
+    public String getName() {
+        return name();
+    }
 }
 
 public class CmsVersion extends Asn1Integer {
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CompressedData.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CompressedData.java
index 9f6f6cd..1ba4a78 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CompressedData.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/CompressedData.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.cms.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.x509.type.AlgorithmIdentifier;
+import static org.apache.kerby.cms.type.CompressedData.MyEnum.*;
 
 /** 
  * Ref. RFC 3274
@@ -35,10 +37,21 @@
  * </pre>
  */
 public class CompressedData extends Asn1SequenceType {
+    protected static enum MyEnum implements EnumType {
+        VERSION,
+        COMPRESSION_ALGORITHM,
+        ENCAP_CONTENT_INFO;
 
-    private static final int VERSION = 0;
-    private static final int COMPRESSION_ALGORITHM = 1;
-    private static final int ENCAP_CONTENT_INFO = 2;
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(VERSION, CmsVersion.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ContentInfo.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ContentInfo.java
index 19c17ea..a33d0e3 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ContentInfo.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ContentInfo.java
@@ -19,12 +19,14 @@
  */
 package org.apache.kerby.cms.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Any;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.type.Asn1Type;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.cms.type.ContentInfo.MyEnum.*;
 
 /**
  * Ref. RFC 5652
@@ -39,8 +41,20 @@
  * </pre>
  */
 public class ContentInfo extends Asn1SequenceType {
-    private static final int CONTENT_TYPE = 0;
-    private static final int CONTENT = 1;
+    protected static enum MyEnum implements EnumType {
+        CONTENT_TYPE,
+        CONTENT;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
         new Asn1FieldInfo(CONTENT_TYPE, Asn1ObjectIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/EncapsulatedContentInfo.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/EncapsulatedContentInfo.java
index 24fa2ab..9744c67 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/EncapsulatedContentInfo.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/EncapsulatedContentInfo.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.cms.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.cms.type.EncapsulatedContentInfo.MyEnum.*;
 
 /**
  * EncapsulatedContentInfo ::= SEQUENCE {
@@ -34,8 +36,20 @@
  * ContentType ::= OBJECT IDENTIFIER
  */
 public class EncapsulatedContentInfo extends Asn1SequenceType {
-    private static final int CONTENT_TYPE = 0;
-    private static final int CONTENT = 1;
+    protected static enum MyEnum implements EnumType {
+        CONTENT_TYPE,
+        CONTENT;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
             new Asn1FieldInfo(CONTENT_TYPE, Asn1ObjectIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ExtendedCertificate.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ExtendedCertificate.java
index 7ab4681..bc37a57 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ExtendedCertificate.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ExtendedCertificate.java
@@ -20,7 +20,9 @@
 package org.apache.kerby.cms.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.cms.type.ExtendedCertificate.MyEnum.*;
 
 /**
  * ExtendedCertificate ::= SEQUENCE {
@@ -30,9 +32,21 @@
  * }
  */
 public class ExtendedCertificate extends Asn1SequenceType {
-    private static final int EXTENDED_CERTIFICATE_INFO = 0;
-    private static final int SIGNATURE_ALGORITHMS = 1;
-    private static final int SIGNATURE = 2;
+    protected static enum MyEnum implements EnumType {
+        EXTENDED_CERTIFICATE_INFO,
+        SIGNATURE_ALGORITHMS,
+        SIGNATURE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(EXTENDED_CERTIFICATE_INFO, ExtendedCertificateInfo.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ExtendedCertificateInfo.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ExtendedCertificateInfo.java
index a4803a4..130db3a 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ExtendedCertificateInfo.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/ExtendedCertificateInfo.java
@@ -20,7 +20,9 @@
 package org.apache.kerby.cms.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.cms.type.ExtendedCertificateInfo.MyEnum.*;
 
 /**
  * ExtendedCertificateInfo ::= SEQUENCE {
@@ -30,9 +32,21 @@
  * }
  */
 public class ExtendedCertificateInfo extends Asn1SequenceType {
-    private static final int CMS_VERSION = 0;
-    private static final int CERTIFICATE = 1;
-    private static final int ATTRIBUTES = 2;
+    protected static enum MyEnum implements EnumType {
+        CMS_VERSION,
+        CERTIFICATE,
+        ATTRIBUTES;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(CMS_VERSION, CmsVersion.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/IssuerAndSerialNumber.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/IssuerAndSerialNumber.java
index 2416d3e..07ea824 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/IssuerAndSerialNumber.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/IssuerAndSerialNumber.java
@@ -20,9 +20,11 @@
 package org.apache.kerby.cms.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.x500.type.Name;
+import static org.apache.kerby.cms.type.IssuerAndSerialNumber.MyEnum.*;
 
 /**
  * Ref. RFC5652
@@ -36,8 +38,20 @@
  * </pre>
  */
 public class IssuerAndSerialNumber extends Asn1SequenceType {
-    private static final int ISSUER = 0;
-    private static final int SERIAL_NUMBER = 1;
+    protected static enum MyEnum implements EnumType {
+        ISSUER,
+        SERIAL_NUMBER;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
         new Asn1FieldInfo(ISSUER, Name.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/OtherCertificateFormat.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/OtherCertificateFormat.java
index 74f2d7c..423b95c 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/OtherCertificateFormat.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/OtherCertificateFormat.java
@@ -19,11 +19,13 @@
  */
 package org.apache.kerby.cms.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Any;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.type.Asn1Type;
+import static org.apache.kerby.cms.type.OtherCertificateFormat.MyEnum.*;
 
 /**
  * OtherCertificateFormat ::= SEQUENCE {
@@ -32,9 +34,20 @@
  * }
  */
 public class OtherCertificateFormat extends Asn1SequenceType {
+    protected static enum MyEnum implements EnumType {
+        OTHER_CERT_FORMAT,
+        OTHER_CERT;
 
-    private static final int OTHER_CERT_FORMAT = 0;
-    private static final int OTHER_CERT = 1;
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(OTHER_CERT_FORMAT, Asn1ObjectIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/OtherRevocationInfoFormat.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/OtherRevocationInfoFormat.java
index e320a09..eb19db8 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/OtherRevocationInfoFormat.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/OtherRevocationInfoFormat.java
@@ -19,11 +19,13 @@
  */
 package org.apache.kerby.cms.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Any;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.type.Asn1Type;
+import static org.apache.kerby.cms.type.OtherRevocationInfoFormat.MyEnum.*;
 
 /**
  * OtherRevocationInfoFormat ::= SEQUENCE {
@@ -32,8 +34,20 @@
  * }
  */
 public class OtherRevocationInfoFormat extends Asn1SequenceType {
-    private static final int OTHER_REV_INFO_FORMAT = 0;
-    private static final int OTHER_REV_INFO = 1;
+    protected static enum MyEnum implements EnumType {
+        OTHER_REV_INFO_FORMAT,
+        OTHER_REV_INFO;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(OTHER_REV_INFO_FORMAT, Asn1ObjectIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/RevocationInfoChoice.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/RevocationInfoChoice.java
index e1c0451..de59a30 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/RevocationInfoChoice.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/RevocationInfoChoice.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.cms.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.ImplicitField;
+import static org.apache.kerby.cms.type.RevocationInfoChoice.MyEnum.*;
 
 /**
  * RevocationInfoChoice ::= CHOICE {
@@ -30,8 +32,20 @@
  * }
  */
 public class RevocationInfoChoice extends Asn1Choice {
-    private static final int CRL = 0;
-    private static final int OTHER = 1;
+    protected static enum MyEnum implements EnumType {
+        CRL,
+        OTHER;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(CRL, CertificateList.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignedData.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignedData.java
index 0d23bbc..39e5a25 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignedData.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignedData.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.cms.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ImplicitField;
+import static org.apache.kerby.cms.type.SignedData.MyEnum.*;
 
 /**
  * Ref. RFC 5652
@@ -38,12 +40,24 @@
  *
  */
 public class SignedData extends Asn1SequenceType {
-    private static final int CMS_VERSION = 0;
-    private static final int DIGEST_ALGORITHMS = 1;
-    private static final int ENCAP_CONTENT_INFO = 2;
-    private static final int CERTIFICATES = 3;
-    private static final int CRLS = 4;
-    private static final int SIGNER_INFOS = 5;
+    protected static enum MyEnum implements EnumType {
+        CMS_VERSION,
+        DIGEST_ALGORITHMS,
+        ENCAP_CONTENT_INFO,
+        CERTIFICATES,
+        CRLS,
+        SIGNER_INFOS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
         new Asn1FieldInfo(CMS_VERSION, CmsVersion.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignerIdentifier.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignerIdentifier.java
index 9cd618b..3c6c3a1 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignerIdentifier.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignerIdentifier.java
@@ -19,10 +19,12 @@
  */
 package org.apache.kerby.cms.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.x509.type.SubjectKeyIdentifier;
+import static org.apache.kerby.cms.type.SignerIdentifier.MyEnum.*;
 
 /**
  * Ref. RFC 5652
@@ -36,8 +38,20 @@
  * </pre>
  */
 public class SignerIdentifier extends Asn1Choice {
-    private static final int ISSUER_AND_SERIAL_NUMBER = 0;
-    private static final int SUBJECT_KEY_IDENTIFIER = 1;
+    protected static enum MyEnum implements EnumType {
+        ISSUER_AND_SERIAL_NUMBER,
+        SUBJECT_KEY_IDENTIFIER;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
         new Asn1FieldInfo(ISSUER_AND_SERIAL_NUMBER, IssuerAndSerialNumber.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignerInfo.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignerInfo.java
index 342d965..211bc55 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignerInfo.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/SignerInfo.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.cms.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ImplicitField;
+import static org.apache.kerby.cms.type.SignerInfo.MyEnum.*;
 
 /**
  * Ref. RFC 5652
@@ -39,13 +41,25 @@
  * </pre>
  */
 public class SignerInfo extends Asn1SequenceType {
-    private static final int CMS_VERSION = 0;
-    private static final int SID = 1;
-    private static final int DIGEST_ALGORITHM = 2;
-    private static final int SIGNED_ATTRS = 3;
-    private static final int SIGNATURE_ALGORITHMS = 4;
-    private static final int SIGNATURE = 5;
-    private static final int UNSIGNED_ATTRS = 6;
+    protected static enum MyEnum implements EnumType {
+        CMS_VERSION,
+        SID,
+        DIGEST_ALGORITHM,
+        SIGNED_ATTRS,
+        SIGNATURE_ALGORITHMS,
+        SIGNATURE,
+        UNSIGNED_ATTRS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
         new Asn1FieldInfo(CMS_VERSION, CmsVersion.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Subject.java b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Subject.java
index 5c0bc88..cdd3b7e 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Subject.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/cms/type/Subject.java
@@ -19,11 +19,13 @@
  */
 package org.apache.kerby.cms.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.x509.type.GeneralNames;
 import org.apache.kerby.x509.type.IssuerSerial;
+import static org.apache.kerby.cms.type.Subject.MyEnum.*;
 
 /**
  * subject CHOICE {
@@ -35,8 +37,20 @@
  *
  */
 public class Subject extends Asn1Choice {
-    private static final int BASE_CERTIFICATE_ID = 0;
-    private static final int SUBJECT_NAME = 1;
+    protected static enum MyEnum implements EnumType {
+        BASE_CERTIFICATE_ID,
+        SUBJECT_NAME;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
             new ExplicitField(BASE_CERTIFICATE_ID, IssuerSerial.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x500/type/AttributeTypeAndValue.java b/kerby-pkix/src/main/java/org/apache/kerby/x500/type/AttributeTypeAndValue.java
index fd4d40c..790334f 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x500/type/AttributeTypeAndValue.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x500/type/AttributeTypeAndValue.java
@@ -19,11 +19,13 @@
  */
 package org.apache.kerby.x500.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Any;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.type.Asn1Type;
+import static org.apache.kerby.x500.type.AttributeTypeAndValue.MyEnum.*;
 
 /**
  * AttributeTypeAndValue ::= SEQUENCE {
@@ -32,9 +34,20 @@
  * }
  */
 public class AttributeTypeAndValue extends Asn1SequenceType {
+    protected static enum MyEnum implements EnumType {
+        TYPE,
+        VALUE;
 
-    private static final int TYPE = 0;
-    private static final int VALUE = 1;
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
             new Asn1FieldInfo(TYPE, Asn1ObjectIdentifier.class, true),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x500/type/Name.java b/kerby-pkix/src/main/java/org/apache/kerby/x500/type/Name.java
index 0e56095..b8ef0f5 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x500/type/Name.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x500/type/Name.java
@@ -19,8 +19,10 @@
  */
 package org.apache.kerby.x500.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import static org.apache.kerby.x500.type.Name.MyEnum.*;
 
 /**
  *
@@ -29,7 +31,19 @@
  * </pre>
  */
 public class Name extends Asn1Choice {
-    private static final int RDN_SEQUENCE = 0;
+    protected static enum MyEnum implements EnumType {
+        RDN_SEQUENCE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
         new Asn1FieldInfo(RDN_SEQUENCE, RDNSequence.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AccessDescription.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AccessDescription.java
index 4f88e22..9f177f0 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AccessDescription.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AccessDescription.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.AccessDescription.MyEnum.*;
 
 /**
  *
@@ -33,8 +35,20 @@
  * </pre>
  */
 public class AccessDescription extends Asn1SequenceType {
-    private static final int ACCESS_METHOD = 0;
-    private static final int ACCESS_LOCATION = 1;
+    protected static enum MyEnum implements EnumType {
+        ACCESS_METHOD,
+        ACCESS_LOCATION;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(ACCESS_METHOD, Asn1ObjectIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AlgorithmIdentifier.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AlgorithmIdentifier.java
index 8fd4db2..c934f34 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AlgorithmIdentifier.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AlgorithmIdentifier.java
@@ -19,11 +19,13 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Any;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.type.Asn1Type;
+import static org.apache.kerby.x509.type.AlgorithmIdentifier.MyEnum.*;
 
 /**
  * AlgorithmIdentifier  ::=  SEQUENCE  {
@@ -32,8 +34,20 @@
  * }
  */
 public class AlgorithmIdentifier extends Asn1SequenceType {
-    private static final int ALGORITHM = 0;
-    private static final int PARAMETERS = 1;
+    protected static enum MyEnum implements EnumType {
+        ALGORITHM,
+        PARAMETERS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(ALGORITHM, Asn1ObjectIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttCertIssuer.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttCertIssuer.java
index 5665c07..977dcaa 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttCertIssuer.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttCertIssuer.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.AttCertIssuer.MyEnum.*;
 
 /**
  *
@@ -33,8 +35,20 @@
  * </pre>
  */
 public class AttCertIssuer extends Asn1Choice {
-    private static final int V1_FORM = 0;
-    private static final int V2_FORM = 1;
+    protected static enum MyEnum implements EnumType {
+        V1_FORM,
+        V2_FORM;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(V1_FORM, GeneralNames.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttCertValidityPeriod.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttCertValidityPeriod.java
index 777cc91..25939dc 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttCertValidityPeriod.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttCertValidityPeriod.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1GeneralizedTime;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.AttCertValidityPeriod.MyEnum.*;
 
 /**
  * <pre>
@@ -32,8 +34,20 @@
  * </pre>
  */
 public class AttCertValidityPeriod extends Asn1SequenceType {
-    private static final int NOT_BEFORE = 0;
-    private static final int NOT_AFTER = 1;
+    protected static enum MyEnum implements EnumType {
+        NOT_BEFORE,
+        NOT_AFTER;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(NOT_BEFORE, Asn1GeneralizedTime.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Attribute.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Attribute.java
index 77d8f6b..4e56cb1 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Attribute.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Attribute.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.Attribute.MyEnum.*;
 
 /**
  * <pre>
@@ -32,8 +34,20 @@
  * </pre>
  */
 public class Attribute extends Asn1SequenceType {
-    private static final int ATTR_TYPE = 0;
-    private static final int ATTR_VALUES = 1;
+    protected static enum MyEnum implements EnumType {
+        ATTR_TYPE,
+        ATTR_VALUES;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(ATTR_TYPE, Asn1ObjectIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttributeCertificate.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttributeCertificate.java
index 8e7a308..f24c383 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttributeCertificate.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttributeCertificate.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.AttributeCertificate.MyEnum.*;
 
 /**
  * <pre>
@@ -33,9 +35,21 @@
  * </pre>
  */
 public class AttributeCertificate extends Asn1SequenceType {
-    private static final int ACI_INFO = 0;
-    private static final int SIGNATURE_ALGORITHM = 1;
-    private static final int SIGNATURE_VALUE = 2;
+    protected static enum MyEnum implements EnumType {
+        ACI_INFO,
+        SIGNATURE_ALGORITHM,
+        SIGNATURE_VALUE;
+        
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(ACI_INFO, AttributeCertificateInfo.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttributeCertificateInfo.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttributeCertificateInfo.java
index e38ff47..6d671c1 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttributeCertificateInfo.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AttributeCertificateInfo.java
@@ -19,10 +19,12 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.AttributeCertificateInfo.MyEnum.*;
 
 /**
  *
@@ -45,15 +47,27 @@
  * </pre>
  */
 public class AttributeCertificateInfo extends Asn1SequenceType {
-    private static final int VERSION = 0;
-    private static final int HOLDER = 1;
-    private static final int ISSUER = 2;
-    private static final int SIGNATURE = 3;
-    private static final int SERIAL_NUMBER = 4;
-    private static final int ATTR_CERT_VALIDITY_PERIOD = 5;
-    private static final int ATTRIBUTES = 6;
-    private static final int ISSUER_UNIQUE_ID = 7;
-    private static final int EXTENSIONS = 8;
+    protected static enum MyEnum implements EnumType {
+        VERSION,
+        HOLDER,
+        ISSUER,
+        SIGNATURE,
+        SERIAL_NUMBER,
+        ATTR_CERT_VALIDITY_PERIOD,
+        ATTRIBUTES,
+        ISSUER_UNIQUE_ID,
+        EXTENSIONS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(VERSION, Asn1Integer.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AuthorityKeyIdentifier.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AuthorityKeyIdentifier.java
index 3ac11b3..8861394 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AuthorityKeyIdentifier.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/AuthorityKeyIdentifier.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ImplicitField;
+import static org.apache.kerby.x509.type.AuthorityKeyIdentifier.MyEnum.*;
 
 /**
  *
@@ -39,10 +41,21 @@
  *
  */
 public class AuthorityKeyIdentifier extends Asn1SequenceType {
-    private static final int KEY_IDENTIFIER = 0;
-    private static final int AUTHORITY_CERT_ISSUER = 1;
-    private static final int AUTHORITY_CERT_SERIAL_NUMBER = 2;
+    protected static enum MyEnum implements EnumType {
+        KEY_IDENTIFIER,
+        AUTHORITY_CERT_ISSUER,
+        AUTHORITY_CERT_SERIAL_NUMBER;
 
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ImplicitField(KEY_IDENTIFIER, KeyIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/BasicConstraints.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/BasicConstraints.java
index bece3bd..fc860e8 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/BasicConstraints.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/BasicConstraints.java
@@ -19,10 +19,12 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Boolean;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.BasicConstraints.MyEnum.*;
 
 import java.math.BigInteger;
 
@@ -35,8 +37,20 @@
  * </pre>
  */
 public class BasicConstraints extends Asn1SequenceType {
-    private static final int CA = 0;
-    private static final int PATH_LEN_CONSTRAINT = 1;
+    protected static enum MyEnum implements EnumType {
+        CA,
+        PATH_LEN_CONSTRAINT;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(CA, Asn1Boolean.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CRLReason.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CRLReason.java
index 1596b8a..6ec021d 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CRLReason.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CRLReason.java
@@ -19,7 +19,7 @@
  */
 package org.apache.kerby.x509.type;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Enumerated;
 
 /**
@@ -40,7 +40,7 @@
  * </pre>
  */
 
-enum CRLReasonEnum implements Asn1EnumType {
+enum CRLReasonEnum implements EnumType {
     UNSPECIFIED,
     KEY_COMPROMISE,
     CA_COMPROMISE,
@@ -56,11 +56,16 @@
     public int getValue() {
         return ordinal();
     }
+
+    @Override
+    public String getName() {
+        return name();
+    }
 }
 
 public class CRLReason extends Asn1Enumerated<CRLReasonEnum> {
     @Override
-    public Asn1EnumType[] getAllEnumValues() {
+    public EnumType[] getAllEnumValues() {
         return CRLReasonEnum.values();
     }
 }
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Certificate.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Certificate.java
index fbb5567..a14cae4 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Certificate.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Certificate.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.Certificate.MyEnum.*;
 
 /**
  * <pre>
@@ -33,9 +35,21 @@
  * </pre>
  */
 public class Certificate extends Asn1SequenceType {
-    private static final int TBS_CERTIFICATE = 0;
-    private static final int SIGNATURE_ALGORITHM = 1;
-    private static final int SIGNATURE = 2;
+    protected static enum MyEnum implements EnumType {
+        TBS_CERTIFICATE,
+        SIGNATURE_ALGORITHM,
+        SIGNATURE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(TBS_CERTIFICATE, TBSCertificate.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CertificateList.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CertificateList.java
index 60b8d85..5ab01e7 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CertificateList.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CertificateList.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.CertificateList.MyEnum.*;
 
 /**
  *
@@ -35,9 +37,21 @@
  * </pre>
  */
 public class CertificateList extends Asn1SequenceType {
-    private static final int TBS_CERT_LIST = 0;
-    private static final int SIGNATURE_ALGORITHMS = 1;
-    private static final int SIGNATURE_VALUE = 2;
+    protected static enum MyEnum implements EnumType {
+        TBS_CERT_LIST,
+        SIGNATURE_ALGORITHMS,
+        SIGNATURE_VALUE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(TBS_CERT_LIST, TBSCertList.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CertificatePair.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CertificatePair.java
index 35f27f0..c2ea503 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CertificatePair.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/CertificatePair.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.CertificatePair.MyEnum.*;
 
 /**
  *
@@ -34,8 +36,20 @@
  * </pre>
  */
 public class CertificatePair extends Asn1SequenceType {
-    private static final int FORWARD = 0;
-    private static final int REVERSE = 1;
+    protected static enum MyEnum implements EnumType {
+        FORWARD,
+        REVERSE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(FORWARD, Certificate.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DSAParameter.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DSAParameter.java
index d97db4c..c97b70f 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DSAParameter.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DSAParameter.java
@@ -20,15 +20,29 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.DSAParameter.MyEnum.*;
 
 import java.math.BigInteger;
 
 public class DSAParameter extends Asn1SequenceType {
-    private static final int P = 0;
-    private static final int Q = 1;
-    private static final int G = 2;
+    protected static enum MyEnum implements EnumType {
+        P,
+        Q,
+        G;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(P, Asn1Integer.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DigestInfo.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DigestInfo.java
index 6df3743..293d079 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DigestInfo.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DigestInfo.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.DigestInfo.MyEnum.*;
 
 /**
  * <pre>
@@ -32,8 +34,20 @@
  * </pre>
  */
 public class DigestInfo extends Asn1SequenceType {
-    private static final int DIGEST_ALGORITHM = 0;
-    private static final int DIGEST = 1;
+    protected static enum MyEnum implements EnumType {
+        DIGEST_ALGORITHM,
+        DIGEST;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(DIGEST_ALGORITHM, AlgorithmIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DigestedObjectType.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DigestedObjectType.java
index e67c503..5c9ccc7 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DigestedObjectType.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DigestedObjectType.java
@@ -19,7 +19,7 @@
  */
 package org.apache.kerby.x509.type;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Enumerated;
 
 /**
@@ -34,7 +34,7 @@
  * </pre>
  * 
  */
-enum DigestedObjectEnum implements Asn1EnumType {
+enum DigestedObjectEnum implements EnumType {
     PUBLIC_KEY,
     PUBLIC_KEY_CERT,
     OTHER_OBJECT_TYPES;
@@ -43,11 +43,16 @@
     public int getValue() {
         return ordinal();
     }
+
+    @Override
+    public String getName() {
+        return name();
+    }
 }
 
 public class DigestedObjectType extends Asn1Enumerated<DigestedObjectEnum> {
     @Override
-    public Asn1EnumType[] getAllEnumValues() {
+    public EnumType[] getAllEnumValues() {
         return DigestedObjectEnum.values();
     }
 }
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DirectoryString.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DirectoryString.java
index f2c5cd9..637215b 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DirectoryString.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DirectoryString.java
@@ -19,6 +19,7 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BmpString;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
@@ -26,6 +27,7 @@
 import org.apache.kerby.asn1.type.Asn1T61String;
 import org.apache.kerby.asn1.type.Asn1UniversalString;
 import org.apache.kerby.asn1.type.Asn1Utf8String;
+import static org.apache.kerby.x509.type.DirectoryString.MyEnum.*;
 
 /**
  * <pre>
@@ -39,12 +41,23 @@
  * </pre>
  */
 public class DirectoryString extends Asn1Choice {
+    protected static enum MyEnum implements EnumType {
+        TELETEX_STRING,
+        PRINTABLE_STRING,
+        UNIVERSAL_STRING,
+        UTF8_STRING,
+        BMP_STRING;
 
-    private static final int TELETEX_STRING = 0;
-    private static final int PRINTABLE_STRING = 1;
-    private static final int UNIVERSAL_STRING = 2;
-    private static final int UTF8_STRING = 3;
-    private static final int BMP_STRING = 4;
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
             new Asn1FieldInfo(TELETEX_STRING, Asn1T61String.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DisplayText.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DisplayText.java
index 9162f03..68de432 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DisplayText.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DisplayText.java
@@ -19,12 +19,14 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BmpString;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1IA5String;
 import org.apache.kerby.asn1.type.Asn1Utf8String;
 import org.apache.kerby.asn1.type.Asn1VisibleString;
+import static org.apache.kerby.x509.type.DisplayText.MyEnum.*;
 
 /**
  * <pre>
@@ -37,10 +39,22 @@
  * </pre>
  */
 public class DisplayText extends Asn1Choice {
-   private static final int IA5_STRING = 0;
-   private static final int VISIBLE_STRING = 1;
-   private static final int BMP_STRING = 2;
-   private static final int UTF8_STRING = 3;
+   protected static enum MyEnum implements EnumType {
+      IA5_STRING,
+      VISIBLE_STRING,
+      BMP_STRING,
+      UTF8_STRING;
+
+      @Override
+      public int getValue() {
+         return ordinal();
+      }
+
+      @Override
+      public String getName() {
+         return name();
+      }
+   }
 
    static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
            new Asn1FieldInfo(IA5_STRING, Asn1IA5String.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DistributionPoint.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DistributionPoint.java
index 6bdd897..8d7471b 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DistributionPoint.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DistributionPoint.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.DistributionPoint.MyEnum.*;
 
 /**
  *
@@ -34,9 +36,21 @@
  * </pre>
  */
 public class DistributionPoint extends Asn1SequenceType {
-    private static final int DISTRIBUTION_POINT = 0;
-    private static final int REASONS = 1;
-    private static final int CRL_ISSUER = 2;
+    protected static enum MyEnum implements EnumType {
+        DISTRIBUTION_POINT,
+        REASONS,
+        CRL_ISSUER;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(DISTRIBUTION_POINT, DistributionPointName.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DistributionPointName.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DistributionPointName.java
index 2c83ee5..8fa3e51 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DistributionPointName.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/DistributionPointName.java
@@ -19,10 +19,12 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.x500.type.RelativeDistinguishedName;
+import static org.apache.kerby.x509.type.DistributionPointName.MyEnum.*;
 
 /**
  *
@@ -34,8 +36,20 @@
  * </pre>
  */
 public class DistributionPointName extends Asn1Choice {
-    private static final int FULL_NAME = 0;
-    private static final int NAME_RELATIVE_TO_CRL_ISSUER = 1;
+    protected static enum MyEnum implements EnumType {
+        FULL_NAME,
+        NAME_RELATIVE_TO_CRL_ISSUER;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(FULL_NAME, GeneralNames.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/EDIPartyName.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/EDIPartyName.java
index 45eeb66..ee790fb 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/EDIPartyName.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/EDIPartyName.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.EDIPartyName.MyEnum.*;
 
 /**
  * <pre>
@@ -32,8 +34,20 @@
  * </pre>
  */
 public class EDIPartyName extends Asn1Choice {
-    private static final int NAME_ASSIGNER = 0;
-    private static final int PARTY_NAME = 1;
+    protected static enum MyEnum implements EnumType {
+        NAME_ASSIGNER,
+        PARTY_NAME;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[]{
             new ExplicitField(NAME_ASSIGNER, DirectoryString.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Extension.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Extension.java
index da44646..fc625f4 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Extension.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Extension.java
@@ -19,11 +19,13 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Boolean;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.Extension.MyEnum.*;
 
 /**
  * Ref. X.509 V3 extension
@@ -37,9 +39,21 @@
  * </pre>
  */
 public class Extension extends Asn1SequenceType {
-    private static final int EXTN_ID = 0;
-    private static final int CRITICAL = 1;
-    private static final int EXTN_VALUE = 2;
+    protected static enum MyEnum implements EnumType {
+        EXTN_ID,
+        CRITICAL,
+        EXTN_VALUE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(EXTN_ID, Asn1ObjectIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/GeneralName.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/GeneralName.java
index dcf6286..c1b79cf 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/GeneralName.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/GeneralName.java
@@ -19,6 +19,7 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1IA5String;
@@ -27,6 +28,7 @@
 import org.apache.kerby.asn1.type.Asn1OctetString;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.x500.type.Name;
+import static org.apache.kerby.x509.type.GeneralName.MyEnum.*;
 
 /**
  *
@@ -45,16 +47,27 @@
  * </pre>
  */
 public class GeneralName extends Asn1Choice {
+    protected static enum MyEnum implements EnumType {
+        OTHER_NAME,
+        RFC822_NAME,
+        DNS_NAME,
+        X400_ADDRESS,
+        DIRECTORY_NAME,
+        EDI_PARTY_NAME,
+        UNIFORM_RESOURCE_IDENTIFIER,
+        IP_ADDRESS,
+        REGISTERED_ID;
 
-    private static final int OTHER_NAME = 0;
-    private static final int RFC822_NAME = 1;
-    private static final int DNS_NAME = 2;
-    private static final int X400_ADDRESS = 3;
-    private static final int DIRECTORY_NAME = 4;
-    private static final int EDI_PARTY_NAME = 5;
-    private static final int UNIFORM_RESOURCE_IDENTIFIER = 6;
-    private static final int IP_ADDRESS = 7;
-    private static final int REGISTERED_ID = 8;
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(OTHER_NAME, OtherName.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/GeneralSubtree.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/GeneralSubtree.java
index 84c8109..34ad9fc 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/GeneralSubtree.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/GeneralSubtree.java
@@ -20,9 +20,11 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.GeneralSubtree.MyEnum.*;
 
 /**
  *
@@ -37,9 +39,21 @@
  * 
  */
 public class GeneralSubtree extends Asn1SequenceType {
-    private static final int BASE = 0;
-    private static final int MINIMUM = 1;
-    private static final int MAXMUM = 2;
+    protected static enum MyEnum implements EnumType {
+        BASE,
+        MINIMUM,
+        MAXMUM;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(BASE, GeneralName.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Holder.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Holder.java
index 44319fd..e4aa59b 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Holder.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Holder.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.Holder.MyEnum.*;
 
 /**
  * <pre>
@@ -38,9 +40,21 @@
  * </pre>
  */
 public class Holder extends Asn1SequenceType {
-    private static final int BASE_CERTIFICATE_ID = 0;
-    private static final int ENTITY_NAME = 1;
-    private static final int OBJECT_DIGEST_INFO = 2;
+    protected static enum MyEnum implements EnumType {
+        BASE_CERTIFICATE_ID,
+        ENTITY_NAME,
+        OBJECT_DIGEST_INFO;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(BASE_CERTIFICATE_ID, IssuerSerial.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IetfAttrSyntax.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IetfAttrSyntax.java
index b7363dc..9a46084 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IetfAttrSyntax.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IetfAttrSyntax.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.IetfAttrSyntax.MyEnum.*;
 
 /**
  * Ref. RFC3281
@@ -39,8 +41,20 @@
  * </pre>
  */
 public class IetfAttrSyntax extends Asn1SequenceType {
-    public static final int POLICY_AUTHORITY = 0;
-    public static final int VALUES = 1;
+    protected static enum MyEnum implements EnumType {
+        POLICY_AUTHORITY,
+        VALUES;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(POLICY_AUTHORITY, GeneralNames.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IetfAttrSyntaxChoice.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IetfAttrSyntaxChoice.java
index 8149e51..86d7606 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IetfAttrSyntaxChoice.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IetfAttrSyntaxChoice.java
@@ -19,10 +19,12 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1OctetString;
+import static org.apache.kerby.x509.type.IetfAttrSyntaxChoice.MyEnum.*;
 
 /**
  * Ref. RFC3281
@@ -38,9 +40,21 @@
  * </pre>
  */
 public class IetfAttrSyntaxChoice extends Asn1Choice {
-    public static final int OCTETS    = 1;
-    public static final int OID       = 2;
-    public static final int UTF8      = 3;
+    protected static enum MyEnum implements EnumType {
+        OCTETS,
+        OID,
+        UTF8;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(OCTETS, Asn1OctetString.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IssuerSerial.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IssuerSerial.java
index 34e8fd8..e8f5416 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IssuerSerial.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IssuerSerial.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.IssuerSerial.MyEnum.*;
 
 /**
  * <pre>
@@ -33,9 +35,21 @@
  * </pre>
  */
 public class IssuerSerial extends Asn1SequenceType {
-    private static final int ISSUER = 0;
-    private static final int SERIAL = 1;
-    private static final int ISSUER_UID = 2;
+    protected static enum MyEnum implements EnumType {
+        ISSUER,
+        SERIAL,
+        ISSUER_UID;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(ISSUER, GeneralNames.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IssuingDistributionPoint.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IssuingDistributionPoint.java
index a725b5a..0970947 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IssuingDistributionPoint.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/IssuingDistributionPoint.java
@@ -19,10 +19,12 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Boolean;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.IssuingDistributionPoint.MyEnum.*;
 
 /**
  * <pre>
@@ -37,12 +39,23 @@
  * </pre>
  */
 public class IssuingDistributionPoint extends Asn1SequenceType {
-    private static final int DISTRIBUTION_POINT = 0;
-    private static final int ONLY_CONTAINS_USER_CERTS = 1;
-    private static final int ONLY_CONTAINS_CA_CERTS = 2;
-    private static final int ONLY_SOME_REASONS = 3;
-    private static final int INDIRECT_CRL = 4;
-    private static final int ONLY_CONTAINS_ATTRIBUTE_CERTS = 5;
+    protected static enum MyEnum implements EnumType {
+        DISTRIBUTION_POINT,
+        ONLY_CONTAINS_USER_CERTS,
+        ONLY_CONTAINS_CA_CERTS,
+        ONLY_SOME_REASONS,
+        INDIRECT_CRL,
+        ONLY_CONTAINS_ATTRIBUTE_CERTS;
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(DISTRIBUTION_POINT, DistributionPointName.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/KeyUsage.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/KeyUsage.java
index bbded47..cde64dd 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/KeyUsage.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/KeyUsage.java
@@ -19,7 +19,7 @@
  */
 package org.apache.kerby.x509.type;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Flags;
 
 /**
@@ -40,7 +40,7 @@
  * </pre>
  */
 
-enum KeyUsageEnum implements Asn1EnumType {
+enum KeyUsageEnum implements EnumType {
     DIGITAL_SIGNATURE,
     NON_REPUDIATION,
     KEY_ENCIPHERMENT,
@@ -55,6 +55,11 @@
     public int getValue() {
         return ordinal();
     }
+
+    @Override
+    public String getName() {
+        return name();
+    }
 }
 
 public class KeyUsage extends Asn1Flags {
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/NameConstraints.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/NameConstraints.java
index 96babc9..49e9f2c 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/NameConstraints.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/NameConstraints.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.NameConstraints.MyEnum.*;
 
 /*
  * NameConstraints ::= SEQUENCE {
@@ -30,8 +32,20 @@
  * }
  */
 public class NameConstraints extends Asn1SequenceType {
-    private static final int PERMITTED_SUBTREES = 0;
-    private static final int EXCLUDED_SUBTREES = 1;
+    protected static enum MyEnum implements EnumType {
+        PERMITTED_SUBTREES,
+        EXCLUDED_SUBTREES;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(PERMITTED_SUBTREES, GeneralSubtrees.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/NoticeReference.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/NoticeReference.java
index 436fbc2..f23a4bd 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/NoticeReference.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/NoticeReference.java
@@ -20,7 +20,9 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.NoticeReference.MyEnum.*;
 
 /**
  * <pre>
@@ -33,8 +35,20 @@
  *
  */
 public class NoticeReference extends Asn1SequenceType {
-    private static final int ORGANIZATION = 0;
-    private static final int NOTICE_NUMBERS = 1;
+    protected static enum MyEnum implements EnumType {
+        ORGANIZATION,
+        NOTICE_NUMBERS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(ORGANIZATION, DisplayText.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/ObjectDigestInfo.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/ObjectDigestInfo.java
index c6489a8..a18f63e 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/ObjectDigestInfo.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/ObjectDigestInfo.java
@@ -19,10 +19,12 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.ObjectDigestInfo.MyEnum.*;
 
 /**
  *
@@ -43,10 +45,22 @@
  * 
  */
 public class ObjectDigestInfo extends Asn1SequenceType {
-    private static final int DIGESTED_OBJECT_TYPE = 0;
-    private static final int OTHER_OBJECT_TYPE_ID = 1;
-    private static final int DIGEST_ALGORITHM = 2;
-    private static final int OBJECT_DIGEST = 3;
+    protected static enum MyEnum implements EnumType {
+        DIGESTED_OBJECT_TYPE,
+        OTHER_OBJECT_TYPE_ID,
+        DIGEST_ALGORITHM,
+        OBJECT_DIGEST;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(DIGESTED_OBJECT_TYPE, DigestedObjectType.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/OtherName.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/OtherName.java
index de21159..0995a4b 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/OtherName.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/OtherName.java
@@ -19,12 +19,14 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Any;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.type.Asn1Type;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.OtherName.MyEnum.*;
 
 /**
  * <pre>
@@ -36,8 +38,20 @@
  * </pre>
  */
 public class OtherName extends Asn1SequenceType {
-    private static final int TYPE_ID = 0;
-    private static final int VALUE = 1;
+    protected static enum MyEnum implements EnumType {
+        TYPE_ID,
+        VALUE;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(TYPE_ID, Asn1ObjectIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyConstraints.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyConstraints.java
index ded02b5..ed7eba5 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyConstraints.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyConstraints.java
@@ -20,9 +20,11 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.PolicyConstraints.MyEnum.*;
 
 /**
  * Ref. RFC 5280
@@ -37,8 +39,20 @@
  * </pre>
  */
 public class PolicyConstraints extends Asn1SequenceType {
-    private static final int REQUIRE_EXPLICIT_POLICY = 0;
-    private static final int INHIBIT_POLICY_MAPPING = 1;
+    protected static enum MyEnum implements EnumType {
+        REQUIRE_EXPLICIT_POLICY,
+        INHIBIT_POLICY_MAPPING;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(REQUIRE_EXPLICIT_POLICY, Asn1Integer.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyInformation.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyInformation.java
index 5b5f06f..81793cc 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyInformation.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyInformation.java
@@ -20,7 +20,9 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.PolicyInformation.MyEnum.*;
 
 /*
  * <pre>
@@ -31,8 +33,20 @@
  * </pre>
  */
 public class PolicyInformation extends Asn1SequenceType {
-    private static final int POLICY_IDENTIFIER = 0;
-    private static final int POLICY_QUALIFIERS = 1;
+    protected static enum MyEnum implements EnumType {
+        POLICY_IDENTIFIER,
+        POLICY_QUALIFIERS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(POLICY_IDENTIFIER, CertPolicyId.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyMapping.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyMapping.java
index 56f5e68..f6d9797 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyMapping.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyMapping.java
@@ -20,7 +20,9 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.PolicyMapping.MyEnum.*;
 
 /**
  * Ref. RFC3280
@@ -32,8 +34,20 @@
  *
  */
 public class PolicyMapping extends Asn1SequenceType {
-    private static final int ISSUER_DOMAIN_POLICY = 0;
-    private static final int SUBJECT_DOMAIN_POLICY = 1;
+    protected static enum MyEnum implements EnumType {
+        ISSUER_DOMAIN_POLICY,
+        SUBJECT_DOMAIN_POLICY;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(ISSUER_DOMAIN_POLICY, CertPolicyId.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyQualifierInfo.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyQualifierInfo.java
index 0f9434c..4b401f8 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyQualifierInfo.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PolicyQualifierInfo.java
@@ -19,10 +19,12 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Any;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.type.Asn1Type;
+import static org.apache.kerby.x509.type.PolicyQualifierInfo.MyEnum.*;
 
 /**
  * 
@@ -36,8 +38,20 @@
  * </pre>
  */
 public class PolicyQualifierInfo extends Asn1SequenceType {
-    private static final int POLICY_QUALIFIER_ID = 0;
-    private static final int QUALIFIER = 1;
+    protected static enum MyEnum implements EnumType {
+        POLICY_QUALIFIER_ID,
+        QUALIFIER;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(POLICY_QUALIFIER_ID, PolicyQualifierId.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PrivateKeyUsagePeriod.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PrivateKeyUsagePeriod.java
index 1645d8f..2b365d0 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PrivateKeyUsagePeriod.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/PrivateKeyUsagePeriod.java
@@ -20,9 +20,11 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1GeneralizedTime;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.PrivateKeyUsagePeriod.MyEnum.*;
 
 /**
  * <pre>
@@ -33,8 +35,20 @@
  * </pre>
  */
 public class PrivateKeyUsagePeriod extends Asn1SequenceType {
-    private static final int NOT_BEFORE = 0;
-    private static final int NOT_AFTER = 1;
+    protected static enum MyEnum implements EnumType {
+        NOT_BEFORE,
+        NOT_AFTER;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(NOT_BEFORE, Asn1GeneralizedTime.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/ReasonFlags.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/ReasonFlags.java
index c397f08..0df6b8e 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/ReasonFlags.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/ReasonFlags.java
@@ -19,7 +19,7 @@
  */
 package org.apache.kerby.x509.type;
 
-import org.apache.kerby.asn1.type.Asn1EnumType;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Flags;
 
 /**
@@ -39,7 +39,7 @@
  * </pre>
  */
 
-enum ReasonFlagsEnum implements Asn1EnumType {
+enum ReasonFlagsEnum implements EnumType {
     UNUSED,
     KEY_COMPROMISE,
     CA_COMPROMISE,
@@ -54,6 +54,11 @@
     public int getValue() {
         return ordinal();
     }
+
+    @Override
+    public String getName() {
+        return name();
+    }
 }
 
 public class ReasonFlags extends Asn1Flags {
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/RevokedCertificate.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/RevokedCertificate.java
index 48a347a..c53c323 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/RevokedCertificate.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/RevokedCertificate.java
@@ -20,7 +20,9 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.RevokedCertificate.MyEnum.*;
 
 /**
  * Ref. RFC 2459
@@ -35,9 +37,21 @@
  * </pre>
  */
 public class RevokedCertificate extends Asn1SequenceType {
-    private static final int USER_CERTIFICATE = 0;
-    private static final int REVOCATION_DATA = 1;
-    private static final int CRL_ENTRY_EXTENSIONS = 2;
+    protected static enum MyEnum implements EnumType {
+        USER_CERTIFICATE,
+        REVOCATION_DATA,
+        CRL_ENTRY_EXTENSIONS;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(USER_CERTIFICATE, CertificateSerialNumber.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/RoleSyntax.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/RoleSyntax.java
index d9c27d1..7495a1a 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/RoleSyntax.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/RoleSyntax.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.RoleSyntax.MyEnum.*;
 
 /**
  *Ref. RFC3281
@@ -33,8 +35,20 @@
  * </pre>
  */
 public class RoleSyntax extends Asn1SequenceType {
-    private static final int ROLE_AUTHORITY = 0;
-    private static final int ROLE_NAME = 1;
+    protected static enum MyEnum implements EnumType {
+        ROLE_AUTHORITY,
+        ROLE_NAME;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(ROLE_AUTHORITY, GeneralNames.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/SubjectPublicKeyInfo.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/SubjectPublicKeyInfo.java
index 3b1eda2..9f82d38 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/SubjectPublicKeyInfo.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/SubjectPublicKeyInfo.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.SubjectPublicKeyInfo.MyEnum.*;
 
 /**
  * SubjectPublicKeyInfo  ::=  SEQUENCE  {
@@ -30,8 +32,20 @@
  * }
  */
 public class SubjectPublicKeyInfo extends Asn1SequenceType {
-    private static final int ALGORITHM = 0;
-    private static final int SUBJECT_PUBLIC_KEY = 1;
+    protected static enum MyEnum implements EnumType {
+        ALGORITHM,
+        SUBJECT_PUBLIC_KEY;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(ALGORITHM, AlgorithmIdentifier.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TBSCertList.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TBSCertList.java
index e4167ff..4e9ba5e 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TBSCertList.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TBSCertList.java
@@ -20,10 +20,12 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.x500.type.Name;
+import static org.apache.kerby.x509.type.TBSCertList.MyEnum.*;
 
 /**
  * Ref. RFC-2459
@@ -47,14 +49,25 @@
  * </pre>
  */
 public class TBSCertList extends Asn1SequenceType {
+    protected static enum MyEnum implements EnumType {
+        VERSION,
+        SIGNATURE,
+        ISSUER,
+        THIS_UPDATA,
+        NEXT_UPDATE,
+        REVOKED_CERTIFICATES,
+        CRL_EXTENSIONS;
 
-    private static final int VERSION = 0;
-    private static final int SIGNATURE = 1;
-    private static final int ISSUER = 2;
-    private static final int THIS_UPDATA = 3;
-    private static final int NEXT_UPDATE = 4;
-    private static final int REVOKED_CERTIFICATES = 5;
-    private static final int CRL_EXTENSIONS = 6;
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(VERSION, Asn1Integer.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TBSCertificate.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TBSCertificate.java
index b5cbcf3..2cb7c1d 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TBSCertificate.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TBSCertificate.java
@@ -19,6 +19,7 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1BitString;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1Integer;
@@ -26,6 +27,8 @@
 import org.apache.kerby.asn1.ExplicitField;
 import org.apache.kerby.asn1.ImplicitField;
 import org.apache.kerby.x500.type.Name;
+import static org.apache.kerby.x509.type.TBSCertificate.MyEnum.*;
+
 
 /**
  * <pre>
@@ -44,17 +47,28 @@
  * </pre>
  */
 public class TBSCertificate extends Asn1SequenceType {
+    protected static enum MyEnum implements EnumType {
+        VERSION,
+        SERIAL_NUMBER,
+        SIGNATURE,
+        ISSUER,
+        VALIDITY,
+        SUBJECT,
+        SUBJECT_PUBLIC_KEY_INFO,
+        ISSUER_UNIQUE_ID,
+        SUBJECT_UNIQUE_ID,
+        EXTENSIONS;
 
-    private static final int VERSION = 0;
-    private static final int SERIAL_NUMBER = 1;
-    private static final int SIGNATURE = 2;
-    private static final int ISSUER = 3;
-    private static final int VALIDITY = 4;
-    private static final int SUBJECT = 5;
-    private static final int SUBJECT_PUBLIC_KEY_INFO = 6;
-    private static final int ISSUER_UNIQUE_ID = 7;
-    private static final int SUBJECT_UNIQUE_ID = 8;
-    private static final int EXTENSIONS = 9;
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new ExplicitField(VERSION, 0, Asn1Integer.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Target.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Target.java
index 4e07667..cc011da 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Target.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Target.java
@@ -19,9 +19,11 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.Target.MyEnum.*;
 
 /**
  * Ref. RFC 3281
@@ -34,9 +36,21 @@
  * </pre>
  */
 public class Target extends Asn1Choice {
-    private static final int TARGET_NAME = 0;
-    private static final int TARGET_GROUP = 1;
-    private static final int TARGET_CERT = 1;
+    protected static enum MyEnum implements EnumType {
+        TARGET_NAME,
+        TARGET_GROUP,
+        TARGET_CERT;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new ExplicitField(TARGET_NAME, GeneralName.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TargetCert.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TargetCert.java
index 441d249..1b433f5 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TargetCert.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/TargetCert.java
@@ -20,7 +20,9 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.TargetCert.MyEnum.*;
 
 /**
  * TargetCert  ::= SEQUENCE {
@@ -30,9 +32,21 @@
  * }
  */
 public class TargetCert extends Asn1SequenceType {
-    private static final int TARGET_CERTIFICATE = 0;
-    private static final int TARGET_NAME = 1;
-    private static final int CERT_DIGEST_INFO = 2;
+    protected static enum MyEnum implements EnumType {
+        TARGET_CERTIFICATE,
+        TARGET_NAME,
+        CERT_DIGEST_INFO;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
             new Asn1FieldInfo(TARGET_CERTIFICATE, IssuerSerial.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Time.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Time.java
index 5038e2f..ebba32e 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Time.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/Time.java
@@ -19,10 +19,12 @@
  */
 package org.apache.kerby.x509.type;
 
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1Choice;
 import org.apache.kerby.asn1.Asn1FieldInfo;
 import org.apache.kerby.asn1.type.Asn1GeneralizedTime;
 import org.apache.kerby.asn1.type.Asn1UtcTime;
+import static org.apache.kerby.x509.type.Time.MyEnum.*;
 
 import java.util.Date;
 
@@ -36,8 +38,20 @@
  * </pre>
  */
 public class Time extends Asn1Choice {
-    private static final int UTC_TIME = 0;
-    private static final int GENERAL_TIME = 1;
+    protected static enum MyEnum implements EnumType {
+        UTC_TIME,
+        GENERAL_TIME;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(UTC_TIME, Asn1UtcTime.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/UserNotice.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/UserNotice.java
index 3c1c879..97f7b03 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/UserNotice.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/UserNotice.java
@@ -20,7 +20,9 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
+import static org.apache.kerby.x509.type.UserNotice.MyEnum.*;
 
 /**
  *
@@ -33,8 +35,20 @@
  *
  */
 public class UserNotice extends Asn1SequenceType {
-    private static final int NOTICE_REF = 0;
-    private static final int EXPLICIT_TEXT = 1;
+    protected static enum MyEnum implements EnumType {
+        NOTICE_REF,
+        EXPLICIT_TEXT;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(NOTICE_REF, NoticeReference.class),
diff --git a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/V2Form.java b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/V2Form.java
index 4964d29..e156206 100644
--- a/kerby-pkix/src/main/java/org/apache/kerby/x509/type/V2Form.java
+++ b/kerby-pkix/src/main/java/org/apache/kerby/x509/type/V2Form.java
@@ -20,8 +20,10 @@
 package org.apache.kerby.x509.type;
 
 import org.apache.kerby.asn1.Asn1FieldInfo;
+import org.apache.kerby.asn1.EnumType;
 import org.apache.kerby.asn1.type.Asn1SequenceType;
 import org.apache.kerby.asn1.ExplicitField;
+import static org.apache.kerby.x509.type.V2Form.MyEnum.*;
 
 /**
  * Produce an object suitable for an ASN1OutputStream.
@@ -37,9 +39,21 @@
  * </pre>
  */
 public class V2Form extends Asn1SequenceType {
-    private static final int ISSUER_NAME = 0;
-    private static final int BASE_CERTIFICATE_ID = 1;
-    private static final int OBJECT_DIGEST_INFO = 2;
+    protected static enum MyEnum implements EnumType {
+        ISSUER_NAME,
+        BASE_CERTIFICATE_ID,
+        OBJECT_DIGEST_INFO;
+
+        @Override
+        public int getValue() {
+            return ordinal();
+        }
+
+        @Override
+        public String getName() {
+            return name();
+        }
+    }
 
     static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
         new Asn1FieldInfo(ISSUER_NAME, GeneralNames.class),