Fix existing encoding issues in CMS/X509/PKINIT tests, and Asn1Encodable encode may also throw IOException
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
index 4deeee8..5015ba2 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/Asn1.java
@@ -37,11 +37,11 @@
 
     }
 
-    public static void encode(ByteBuffer buffer, Asn1Type value) {
+    public static void encode(ByteBuffer buffer, Asn1Type value) throws IOException {
         value.encode(buffer);
     }
 
-    public static byte[] encode(Asn1Type value) {
+    public static byte[] encode(Asn1Type value) throws IOException {
         return value.encode();
     }
 
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Any.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Any.java
index 50c7256..79d41df 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Any.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Any.java
@@ -69,7 +69,7 @@
     }
 
     @Override
-    public void encode(ByteBuffer buffer) {
+    public void encode(ByteBuffer buffer) throws IOException {
         Asn1Encodeable theValue = (Asn1Encodeable) getValue();
 
         if (theValue != null) {
@@ -88,7 +88,7 @@
     }
 
     @Override
-    protected int encodingBodyLength() {
+    public int encodingLength() {
         Asn1Encodeable theValue = (Asn1Encodeable) getValue();
 
         if (theValue != null) {
@@ -105,7 +105,18 @@
             }
         }
 
-        return 0;
+        return super.encodingLength();
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        Asn1Encodeable theValue = (Asn1Encodeable) getValue();
+
+        if (theValue == null) {
+            return 0;
+        }
+
+        return -1; // Indicate error, shouldn't be here.
     }
 
     @Override
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 5cec8c9..1b921e1 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
@@ -53,15 +53,15 @@
         if (body != null) {
             return body.length + 1;
         }
-        return 1;
+        return 0;
     }
 
     @Override
     protected void toBytes() {
         byte[] bytes = new byte[encodingBodyLength()];
-        bytes[0] = (byte) padding;
         byte[] body = getValue();
         if (body != null) {
+            bytes[0] = (byte) padding;
             System.arraycopy(body, 0, bytes, 1, bytes.length - 1);
         }
         setBytes(bytes);
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 ea01b93..8835c9d 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
@@ -87,7 +87,7 @@
     }
 
     @Override
-    public byte[] encode() {
+    public byte[] encode() throws IOException {
         Asn1Encodeable theValue = (Asn1Encodeable) getValue();
 
         if (theValue != null) {
@@ -103,7 +103,7 @@
     }
 
     @Override
-    public void encode(ByteBuffer buffer) {
+    public void encode(ByteBuffer buffer) throws IOException {
         Asn1Encodeable theValue = (Asn1Encodeable) getValue();
 
         if (theValue != null) {
@@ -118,7 +118,7 @@
     }
 
     @Override
-    protected int encodingBodyLength() {
+    public int encodingLength() {
         Asn1Encodeable theValue = (Asn1Encodeable) getValue();
 
         if (theValue != null) {
@@ -131,11 +131,22 @@
             }
         }
 
-        return 0;
+        return super.encodingLength();
     }
 
     @Override
-    protected void encodeBody(ByteBuffer buffer) {
+    protected int encodingBodyLength() {
+        Asn1Encodeable theValue = (Asn1Encodeable) getValue();
+
+        if (theValue == null) {
+            return 0;
+        }
+
+        return -1; // Indicate error, shouldn't be here.
+    }
+
+    @Override
+    protected void encodeBody(ByteBuffer buffer) throws IOException {
         Asn1Encodeable theValue = (Asn1Encodeable) getValue();
 
         if (theValue != null) {
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 76e9926..0812fb7 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
@@ -53,7 +53,7 @@
     }
 
     @Override
-    protected int encodingBodyLength() {
+    protected int encodingBodyLength() throws IOException {
         int allLen = 0;
         int fieldLen;
         for (int i = 0; i < fields.length; ++i) {
@@ -73,7 +73,7 @@
     }
 
     @Override
-    protected void encodeBody(ByteBuffer buffer) {
+    protected void encodeBody(ByteBuffer buffer) throws IOException {
         for (int i = 0; i < fields.length; ++i) {
             Asn1Type field = fields[i];
             if (field != null) {
@@ -99,7 +99,7 @@
         int lastPos = -1, foundPos = -1;
 
         for (Asn1ParseResult parseItem : parseResults) {
-            if (parseItem.isEOC() || parseItem.isNull()) {
+            if (parseItem.isEOC()) {
                 continue;
             }
 
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 8ccf4cc..fd8a187 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
@@ -69,7 +69,7 @@
     }
 
     @Override
-    protected int encodingBodyLength() {
+    protected int encodingBodyLength() throws IOException {
         List<Asn1Type> valueItems = getValue();
         int allLen = 0;
         for (Asn1Type item : valueItems) {
@@ -81,7 +81,7 @@
     }
 
     @Override
-    protected void encodeBody(ByteBuffer buffer) {
+    protected void encodeBody(ByteBuffer buffer) throws IOException {
         List<Asn1Type> valueItems = getValue();
         for (Asn1Type item : valueItems) {
             if (item != null) {
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java
index e5cc5b4..0bd2e81 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java
@@ -129,7 +129,7 @@
     }
 
     @Override
-    public byte[] encode() {
+    public byte[] encode() throws IOException {
         int len = encodingLength();
         ByteBuffer byteBuffer = ByteBuffer.allocate(len);
         encode(byteBuffer);
@@ -138,14 +138,14 @@
     }
 
     @Override
-    public void encode(ByteBuffer buffer) {
+    public void encode(ByteBuffer buffer) throws IOException {
         Asn1Util.encodeTag(buffer, tag());
         int bodyLen = getBodyLength();
         Asn1Util.encodeLength(buffer, bodyLen);
         encodeBody(buffer);
     }
 
-    protected void encodeBody(ByteBuffer buffer) { }
+    protected void encodeBody(ByteBuffer buffer) throws IOException { }
 
     @Override
     public void decode(byte[] content) throws IOException {
@@ -159,18 +159,29 @@
 
     @Override
     protected int getHeaderLength() {
-        return encodingHeaderLength();
+        try {
+            return encodingHeaderLength();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Override
     protected int getBodyLength() {
         if (bodyLength == -1) {
-            bodyLength = encodingBodyLength();
+            try {
+                bodyLength = encodingBodyLength();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+            if (bodyLength == -1) {
+                throw new RuntimeException("Unexpected body length: -1");
+            }
         }
         return bodyLength;
     }
 
-    protected int encodingHeaderLength() {
+    protected int encodingHeaderLength() throws IOException {
         int headerLen = Asn1Util.lengthOfTagLength(tagNo());
         int bodyLen = getBodyLength();
         headerLen += Asn1Util.lengthOfBodyLength(bodyLen);
@@ -178,7 +189,7 @@
         return headerLen;
     }
 
-    protected abstract int encodingBodyLength();
+    protected abstract int encodingBodyLength() throws IOException;
 
     @Override
     public void decode(ByteBuffer content) throws IOException {
@@ -215,7 +226,7 @@
     }
 
     @Override
-    public byte[] taggedEncode(TaggingOption taggingOption) {
+    public byte[] taggedEncode(TaggingOption taggingOption) throws IOException {
         int len = taggedEncodingLength(taggingOption);
         ByteBuffer byteBuffer = ByteBuffer.allocate(len);
         taggedEncode(byteBuffer, taggingOption);
@@ -224,7 +235,7 @@
     }
 
     @Override
-    public void taggedEncode(ByteBuffer buffer, TaggingOption taggingOption) {
+    public void taggedEncode(ByteBuffer buffer, TaggingOption taggingOption) throws IOException {
         Tag taggingTag = taggingOption.getTag(!isPrimitive());
         Asn1Util.encodeTag(buffer, taggingTag);
 
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 2e094e4..4948828 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
@@ -22,6 +22,8 @@
 import org.apache.kerby.asn1.Tag;
 import org.apache.kerby.asn1.UniversalTag;
 
+import java.io.IOException;
+
 /**
  * An ASN1 object has a tag.
  */
@@ -105,17 +107,21 @@
         return Asn1Collection.isCollection(tag());
     }
 
-    protected abstract int getHeaderLength();
+    protected abstract int getHeaderLength() throws IOException;
 
-    protected abstract int getBodyLength();
+    protected abstract int getBodyLength() throws IOException;
 
     protected String simpleInfo() {
         String simpleInfo = tag().typeStr();
 
-        simpleInfo += " ["
-            + "tag=" + tag()
-            + ", len=" + getHeaderLength() + "+" + getBodyLength()
-            + "] ";
+        try {
+            simpleInfo += " ["
+                + "tag=" + tag()
+                + ", len=" + getHeaderLength() + "+" + getBodyLength()
+                + "] ";
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
 
         return simpleInfo;
     }
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 594bcd2..98eefa2 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
@@ -62,7 +62,7 @@
     }
 
     @Override
-    protected int encodingBodyLength() {
+    protected int encodingBodyLength() throws IOException {
         Asn1Encodeable value = (Asn1Encodeable) getValue();
         if (isImplicit()) {
             return value.encodingBodyLength();
@@ -72,7 +72,7 @@
     }
 
     @Override
-    protected void encodeBody(ByteBuffer buffer) {
+    protected void encodeBody(ByteBuffer buffer) throws IOException {
         Asn1Encodeable value = (Asn1Encodeable) getValue();
         if (isImplicit()) {
             value.encodeBody(buffer);
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingCollection.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingCollection.java
index 1db30e4..9595866 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingCollection.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1TaggingCollection.java
@@ -126,12 +126,12 @@
 
 
     @Override
-    protected int encodingBodyLength() {
+    protected int encodingBodyLength() throws IOException {
         return tagging.encodingBodyLength();
     }
 
     @Override
-    protected void encodeBody(ByteBuffer buffer) {
+    protected void encodeBody(ByteBuffer buffer) throws IOException {
         tagging.encodeBody(buffer);
     }
 
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Type.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Type.java
index 4c1c538..6b0fa67 100644
--- a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Type.java
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Type.java
@@ -121,19 +121,19 @@
      * Generally it's called to prepare for the encoding buffer.
      * @return length of encoding bytes
      */
-    int encodingLength();
+    int encodingLength() throws IOException;
 
     /**
      * Encode the type, by recursively.
      * @return encoded bytes
      */
-    byte[] encode();
+    byte[] encode() throws IOException;
 
     /**
      * Encode the type, by recursively, using the provided buffer.
      * @param buffer The byte buffer
      */
-    void encode(ByteBuffer buffer);
+    void encode(ByteBuffer buffer) throws IOException;
 
     /**
      * Decode the content bytes into this type.
@@ -154,14 +154,14 @@
      * @param taggingOption The tagging option
      * @return encoded bytes
      */
-    byte[] taggedEncode(TaggingOption taggingOption);
+    byte[] taggedEncode(TaggingOption taggingOption) throws IOException;
 
     /**
      * Tag and encode this type using the provided tagging option.
      * @param buffer The byte buffer
      * @param taggingOption The tagging option
      */
-    void taggedEncode(ByteBuffer buffer, TaggingOption taggingOption);
+    void taggedEncode(ByteBuffer buffer, TaggingOption taggingOption) throws IOException;
 
     /**
      * Decode the content bytes into this type as it's tagged with the provided
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 2f7dcf4..22dd8a0 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
@@ -30,13 +30,13 @@
 public class TestAsn1Boolean {
 
     @Test
-    public void testEncoding() {
+    public void testEncoding() throws IOException {
         testEncodingWith(true, "0x01 01 FF", true);
         testEncodingWith(false, "0x01 01 00", true);
     }
 
     private void testEncodingWith(Boolean value, String expectedEncoding,
-                                  boolean isDer) {
+                                  boolean isDer) throws IOException {
         byte[] expected = HexUtil.hex2bytesFriendly(expectedEncoding);
         Asn1Boolean aValue = new Asn1Boolean(value);
         if (isDer) {
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Collection.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Collection.java
index 2ae62e7..ffa4a95 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Collection.java
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestAsn1Collection.java
@@ -38,7 +38,7 @@
     };
 
     @Test
-    public void testSequenceEncoding() {
+    public void testSequenceEncoding() throws IOException {
         Asn1Sequence seq = new Asn1Sequence();
         seq.addItem(new Asn1IA5String(TEST_STR));
         seq.addItem(new Asn1Boolean(TEST_BOOL));
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 f93b53c..16b5852 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
@@ -30,7 +30,7 @@
 public class TestAsn1Integer {
 
     @Test
-    public void testEncoding() {
+    public void testEncoding() throws IOException {
         testEncodingWith(0, "0x02 01 00");
         testEncodingWith(1, "0x02 01 01");
         testEncodingWith(2, "0x02 01 02");
@@ -42,7 +42,7 @@
         testEncodingWith(1234567890, "0x02 04 49 96 02 D2");
     }
 
-    private void testEncodingWith(int value, String expectedEncoding) {
+    private void testEncodingWith(int value, String expectedEncoding) throws IOException {
         byte[] expected = HexUtil.hex2bytesFriendly(expectedEncoding);
         Asn1Integer aValue = new Asn1Integer(value);
         aValue.useDER();
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 39c43dc..b6b400f 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
@@ -43,7 +43,7 @@
                 "0x06 08 2A 86 48 86 F7 0D 02 05");
     }
 
-    private void testEncodingWith(String oid, String expectedEncoding) {
+    private void testEncodingWith(String oid, String expectedEncoding) throws IOException {
         byte[] expected = HexUtil.hex2bytesFriendly(expectedEncoding);
         Asn1ObjectIdentifier aValue = new Asn1ObjectIdentifier(oid);
         aValue.useDER();
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 0e11692..7cfb377 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
@@ -46,7 +46,7 @@
         testEncodingWith(date, "0x17 0D 30 33 30 37 30 34 31 31 33 33 32 38 5A");
     }
 
-    private void testEncodingWith(Date value, String expectedEncoding) {
+    private void testEncodingWith(Date value, String expectedEncoding) throws IOException {
         byte[] expected = HexUtil.hex2bytesFriendly(expectedEncoding);
         Asn1UtcTime aValue = new Asn1UtcTime(value);
         aValue.useDER();
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 a8970b8..4dcb5be 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
@@ -35,7 +35,7 @@
     static boolean verbose = false;
 
     @Test
-    public void testEncoding() {
+    public void testEncoding() throws IOException {
         PersonnelRecord pr = TestData.createSamplePersonnel();
 
         if (verbose) {
diff --git a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestTaggingEncoding.java b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestTaggingEncoding.java
index 6956b46..2828249 100644
--- a/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestTaggingEncoding.java
+++ b/kerby-asn1/src/test/java/org/apache/kerby/asn1/TestTaggingEncoding.java
@@ -122,7 +122,7 @@
     }
 
     @Test
-    public void testAsn1TaggingEncoding() {
+    public void testAsn1TaggingEncoding() throws IOException {
         Type1 aType1 = new Type1(TEST_STRING);
         Type2 aType2 = new Type2(aType1);
         Type3 aType3 = new Type3(aType2);
@@ -160,7 +160,7 @@
     }
 
     @Test
-    public void testTaggingEncodingOption() {
+    public void testTaggingEncodingOption() throws IOException {
         Type1 aType1 = new Type1(TEST_STRING);
         Type2 aType2 = new Type2(aType1);
         Type3 aType3 = new Type3(aType2);
diff --git a/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/EncryptionKeyAdapter.java b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/EncryptionKeyAdapter.java
index fd3fd20..6694ab9 100644
--- a/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/EncryptionKeyAdapter.java
+++ b/kerby-backend/json-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/typeAdapter/EncryptionKeyAdapter.java
@@ -26,6 +26,8 @@
 import com.google.gson.JsonParseException;
 import com.google.gson.JsonSerializationContext;
 import com.google.gson.JsonSerializer;
+import org.apache.kerby.kerberos.kerb.KrbCodec;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
 import org.apache.kerby.util.HexUtil;
 
@@ -56,7 +58,11 @@
                                  Type type, JsonSerializationContext jsonSerializationContext) {
         JsonObject jsonObject = new JsonObject();
         jsonObject.addProperty("kvno", encryptionKey.getKvno());
-        jsonObject.addProperty("key", HexUtil.bytesToHex(encryptionKey.encode()));
+        try {
+            jsonObject.addProperty("key", HexUtil.bytesToHex(KrbCodec.encode(encryptionKey)));
+        } catch (KrbException e) {
+            throw new RuntimeException(e);
+        }
         return jsonObject;
     }
 }
diff --git a/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java b/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java
index 9d6151d..99110a5 100644
--- a/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java
+++ b/kerby-backend/ldap-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/LdapIdentityBackend.java
@@ -155,7 +155,7 @@
         private byte[][] keys;
         private String[] kvnos;
 
-        public KeysInfo(KrbIdentity identity) {
+        public KeysInfo(KrbIdentity identity) throws KrbException {
             Map<EncryptionType, EncryptionKey> keymap = identity.getKeys();
             this.etypes = new String[keymap.size()];
             this.keys = new byte[keymap.size()][];
@@ -163,7 +163,11 @@
             int i = 0;
             for (Map.Entry<EncryptionType, EncryptionKey> entryKey : keymap.entrySet()) {
                 etypes[i] = entryKey.getKey().getValue() + "";
-                keys[i] = entryKey.getValue().encode();
+                try {
+                    keys[i] = entryKey.getValue().encode();
+                } catch (IOException e) {
+                    throw new KrbException("encode key failed", e);
+                }
                 kvnos[i] = entryKey.getValue().getKvno() + "";
                 i++;
             }
diff --git a/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/IdentityZNode.java b/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/IdentityZNode.java
index 1f08279..92c7bf9 100644
--- a/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/IdentityZNode.java
+++ b/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/IdentityZNode.java
@@ -323,7 +323,7 @@
         return keys;
     }
 
-    public void setKeys(Map<EncryptionType, EncryptionKey> keys) throws KeeperException {
+    public void setKeys(Map<EncryptionType, EncryptionKey> keys) throws KeeperException, IOException {
         if (ZKUtil.checkExists(this.zk, IdentityZNodeHelper.getKeysZNode(this.identityName)) == -1) {
             ZKUtil.createWithParents(this.zk, IdentityZNodeHelper.getKeysZNode(this.identityName));
         }
diff --git a/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java b/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java
index 8449110..95d14a5 100644
--- a/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java
+++ b/kerby-backend/zookeeper-backend/src/main/java/org/apache/kerby/kerberos/kdc/identitybackend/ZookeeperIdentityBackend.java
@@ -229,7 +229,7 @@
     protected KrbIdentity doAddIdentity(KrbIdentity identity) throws KrbException {
         try {
             setIdentity(identity);
-        } catch (KeeperException e) {
+        } catch (Exception e) {
             throw new KrbException("Fail to add identity to zookeeper", e);
         }
         return doGetIdentity(identity.getPrincipalName());
@@ -242,7 +242,7 @@
     protected KrbIdentity doUpdateIdentity(KrbIdentity identity) throws KrbException {
         try {
             setIdentity(identity);
-        } catch (KeeperException e) {
+        } catch (Exception e) {
             throw new KrbException("Fail to update identity in zookeeper", e);
         }
         return doGetIdentity(identity.getPrincipalName());
@@ -296,7 +296,7 @@
      * @param identity . The identity to update
      * @throws org.apache.zookeeper.KeeperException
      */
-    private void setIdentity(KrbIdentity identity) throws KeeperException {
+    private void setIdentity(KrbIdentity identity) throws KeeperException, IOException {
         String principalName = identity.getPrincipalName();
         principalName = replaceSlash(principalName);
         IdentityZNode identityZNode = new IdentityZNode(zooKeeper, principalName);
diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/AnonymousPkinitKdcTest.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/AnonymousPkinitKdcTest.java
index 9dc7766..fa26413 100644
--- a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/AnonymousPkinitKdcTest.java
+++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/AnonymousPkinitKdcTest.java
@@ -20,13 +20,21 @@
 package org.apache.kerby.kerberos.kdc;
 
 import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbPkinitClient;
 import org.apache.kerby.kerberos.kerb.server.KdcConfigKey;
 import org.apache.kerby.kerberos.kerb.server.KdcTestBase;
+import org.apache.kerby.kerberos.kerb.type.ticket.SgtTicket;
+import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
 import org.junit.Before;
+import org.junit.Test;
+
+import java.net.URL;
+
+import static org.assertj.core.api.Assertions.assertThat;
 
 public class AnonymousPkinitKdcTest extends KdcTestBase {
 
-    //private String serverPrincipal;
+    private String serverPrincipal;
 
     @Before
     public void setUp() throws Exception {
@@ -50,8 +58,6 @@
         getKdcServer().createPrincipal("WELLKNOWN/ANONYMOUS");
     }
 
-    // TO BE FIXED
-    /*
     @Test
     public void testAnonymity() throws Exception {
 
@@ -72,5 +78,5 @@
         serverPrincipal = getServerPrincipal();
         SgtTicket tkt = getKrbClient().requestSgt(tgt, serverPrincipal);
         assertThat(tkt).isNotNull();
-    }*/
+    }
 }
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java
index c46e38e..38e93b2 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbHandler.java
@@ -24,6 +24,7 @@
 import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.client.preauth.PreauthHandler;
 import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
+import org.apache.kerby.kerberos.kerb.transport.KrbTransport;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptionType;
 import org.apache.kerby.kerberos.kerb.type.base.EtypeInfo2;
 import org.apache.kerby.kerberos.kerb.type.base.EtypeInfo2Entry;
@@ -35,7 +36,6 @@
 import org.apache.kerby.kerberos.kerb.type.kdc.KdcReq;
 import org.apache.kerby.kerberos.kerb.type.pa.PaDataEntry;
 import org.apache.kerby.kerberos.kerb.type.pa.PaDataType;
-import org.apache.kerby.kerberos.kerb.transport.KrbTransport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -80,7 +80,7 @@
             requestMessage = ByteBuffer.allocate(bodyLen + 4);
             requestMessage.putInt(bodyLen);
         }
-        kdcReq.encode(requestMessage);
+        KrbCodec.encode(kdcReq, requestMessage);
         requestMessage.flip();
         try {
             sendMessage(kdcRequest, requestMessage);
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbKdcOption.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbKdcOption.java
index cee1d23..3c85666 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbKdcOption.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/KrbKdcOption.java
@@ -20,9 +20,7 @@
 package org.apache.kerby.kerberos.kerb.client;
 
 import org.apache.kerby.KOption;
-import org.apache.kerby.KOptionGroup;
 import org.apache.kerby.KOptionInfo;
-import org.apache.kerby.KOptionType;
 
 /**
  * This defines KDC options for client side API to use.
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/TokenOption.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/TokenOption.java
index 9dabea1..123ff85 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/TokenOption.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/TokenOption.java
@@ -20,7 +20,6 @@
 package org.apache.kerby.kerberos.kerb.client;
 
 import org.apache.kerby.KOption;
-import org.apache.kerby.KOptionGroup;
 import org.apache.kerby.KOptionInfo;
 import org.apache.kerby.KOptionType;
 
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/DefaultInternalKrbClient.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/DefaultInternalKrbClient.java
index b6d799f..e2c18d3 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/DefaultInternalKrbClient.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/impl/DefaultInternalKrbClient.java
@@ -24,11 +24,11 @@
 import org.apache.kerby.kerberos.kerb.client.KrbSetting;
 import org.apache.kerby.kerberos.kerb.client.request.AsRequest;
 import org.apache.kerby.kerberos.kerb.client.request.TgsRequest;
-import org.apache.kerby.kerberos.kerb.type.ticket.SgtTicket;
-import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
 import org.apache.kerby.kerberos.kerb.transport.KrbNetwork;
 import org.apache.kerby.kerberos.kerb.transport.KrbTransport;
 import org.apache.kerby.kerberos.kerb.transport.TransportPair;
+import org.apache.kerby.kerberos.kerb.type.ticket.SgtTicket;
+import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
 
 import java.io.IOException;
 
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/AbstractPreauthPlugin.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/AbstractPreauthPlugin.java
index da6e4ba..660b4e0 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/AbstractPreauthPlugin.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/AbstractPreauthPlugin.java
@@ -19,14 +19,14 @@
  */
 package org.apache.kerby.kerberos.kerb.client.preauth;
 
-import org.apache.kerby.kerberos.kerb.client.KrbContext;
 import org.apache.kerby.KOptions;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbContext;
 import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
 import org.apache.kerby.kerberos.kerb.preauth.PaFlag;
 import org.apache.kerby.kerberos.kerb.preauth.PaFlags;
 import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
 import org.apache.kerby.kerberos.kerb.preauth.PreauthPluginMeta;
-import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptionType;
 import org.apache.kerby.kerberos.kerb.type.pa.PaData;
 import org.apache.kerby.kerberos.kerb.type.pa.PaDataEntry;
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/KrbPreauth.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/KrbPreauth.java
index 521c595..7f7ac92 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/KrbPreauth.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/KrbPreauth.java
@@ -19,13 +19,13 @@
  */
 package org.apache.kerby.kerberos.kerb.client.preauth;
 
-import org.apache.kerby.kerberos.kerb.client.KrbContext;
 import org.apache.kerby.KOptions;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbContext;
 import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
 import org.apache.kerby.kerberos.kerb.preauth.PaFlags;
 import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
 import org.apache.kerby.kerberos.kerb.preauth.PreauthPluginMeta;
-import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptionType;
 import org.apache.kerby.kerberos.kerb.type.pa.PaData;
 import org.apache.kerby.kerberos.kerb.type.pa.PaDataEntry;
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandle.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandle.java
index d7a8cec..8e11308 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandle.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandle.java
@@ -20,10 +20,10 @@
 package org.apache.kerby.kerberos.kerb.client.preauth;
 
 import org.apache.kerby.KOptions;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
 import org.apache.kerby.kerberos.kerb.preauth.PaFlags;
 import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
-import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.type.pa.PaData;
 import org.apache.kerby.kerberos.kerb.type.pa.PaDataEntry;
 import org.apache.kerby.kerberos.kerb.type.pa.PaDataType;
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandler.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandler.java
index e3483aa..8cccd0b 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandler.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/PreauthHandler.java
@@ -19,14 +19,14 @@
  */
 package org.apache.kerby.kerberos.kerb.client.preauth;
 
-import org.apache.kerby.kerberos.kerb.client.KrbContext;
 import org.apache.kerby.KOptions;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.KrbContext;
 import org.apache.kerby.kerberos.kerb.client.preauth.builtin.EncTsPreauth;
 import org.apache.kerby.kerberos.kerb.client.preauth.builtin.TgtPreauth;
 import org.apache.kerby.kerberos.kerb.client.preauth.pkinit.PkinitPreauth;
 import org.apache.kerby.kerberos.kerb.client.preauth.token.TokenPreauth;
 import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
-import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.type.pa.PaData;
 import org.apache.kerby.kerberos.kerb.type.pa.PaDataEntry;
 import org.apache.kerby.kerberos.kerb.type.pa.PaDataType;
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/builtin/EncTsPreauth.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/builtin/EncTsPreauth.java
index e25f360..a332515 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/builtin/EncTsPreauth.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/builtin/EncTsPreauth.java
@@ -19,6 +19,8 @@
  */
 package org.apache.kerby.kerberos.kerb.client.preauth.builtin;
 
+import org.apache.kerby.kerberos.kerb.KrbCodec;
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.client.preauth.AbstractPreauthPlugin;
 import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
 import org.apache.kerby.kerberos.kerb.common.EncryptionUtil;
@@ -26,7 +28,6 @@
 import org.apache.kerby.kerberos.kerb.preauth.PaFlags;
 import org.apache.kerby.kerberos.kerb.preauth.PluginRequestContext;
 import org.apache.kerby.kerberos.kerb.preauth.builtin.EncTsPreauthMeta;
-import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptedData;
 import org.apache.kerby.kerberos.kerb.type.base.KeyUsage;
 import org.apache.kerby.kerberos.kerb.type.pa.PaData;
@@ -106,7 +107,7 @@
                 kdcRequest.getAsKey(), KeyUsage.AS_REQ_PA_ENC_TS);
         PaDataEntry tsPaEntry = new PaDataEntry();
         tsPaEntry.setPaDataType(PaDataType.ENC_TIMESTAMP);
-        tsPaEntry.setPaDataValue(paDataValue.encode());
+        tsPaEntry.setPaDataValue(KrbCodec.encode(paDataValue));
 
         return tsPaEntry;
     }
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/builtin/TgtPreauth.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/builtin/TgtPreauth.java
index a01ce88..4010aab 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/builtin/TgtPreauth.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/builtin/TgtPreauth.java
@@ -19,6 +19,7 @@
  */
 package org.apache.kerby.kerberos.kerb.client.preauth.builtin;
 
+import org.apache.kerby.kerberos.kerb.KrbCodec;
 import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.client.preauth.AbstractPreauthPlugin;
 import org.apache.kerby.kerberos.kerb.client.request.KdcRequest;
@@ -72,7 +73,7 @@
 
         PaDataEntry paEntry = new PaDataEntry();
         paEntry.setPaDataType(PaDataType.TGS_REQ);
-        paEntry.setPaDataValue(tgsRequest.getApReq().encode());
+        paEntry.setPaDataValue(KrbCodec.encode(tgsRequest.getApReq()));
 
         return paEntry;
     }
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitPreauth.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitPreauth.java
index f00cf0f..640f718 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitPreauth.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/pkinit/PkinitPreauth.java
@@ -22,6 +22,7 @@
 import org.apache.kerby.KOptions;
 import org.apache.kerby.asn1.type.Asn1Integer;
 import org.apache.kerby.asn1.type.Asn1ObjectIdentifier;
+import org.apache.kerby.kerberos.kerb.KrbCodec;
 import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.client.KrbContext;
 import org.apache.kerby.kerberos.kerb.client.PkinitOption;
@@ -166,7 +167,7 @@
         CheckSum checkSum = null;
         try {
             checkSum = CheckSumUtil.makeCheckSum(CheckSumType.NIST_SHA,
-                    kdcRequest.getKdcReq().getReqBody().encode());
+                KrbCodec.encode(kdcRequest.getKdcReq().getReqBody()));
         } catch (KrbException e) {
             throw new KrbException("Fail to encode checksum.", e);
         }
@@ -216,7 +217,7 @@
 
     private PaPkAsReq makePaPkAsReq(KdcRequest kdcRequest,
                                     PkinitRequestContext reqCtx,
-                                    int cusec, KerberosTime ctime, int nonce, CheckSum checkSum) {
+                                    int cusec, KerberosTime ctime, int nonce, CheckSum checkSum) throws KrbException {
 
         LOG.info("Making the PK_AS_REQ.");
         PaPkAsReq paPkAsReq = new PaPkAsReq();
@@ -265,7 +266,7 @@
             pubInfo.setAlgorithm(dhAlg);
 
             Asn1Integer publickey = new Asn1Integer(clientPubKey.getY());
-            pubInfo.setSubjectPubKey(publickey.encode());
+            pubInfo.setSubjectPubKey(KrbCodec.encode(publickey));
 
             authPack.setClientPublicValue(pubInfo);
 
@@ -290,12 +291,12 @@
         return paPkAsReq;
     }
 
-    private byte[] signAuthPack(AuthPack authPack) {
+    private byte[] signAuthPack(AuthPack authPack) throws KrbException {
 
         Asn1ObjectIdentifier oid = pkinitContext.cryptoctx.getIdPkinitAuthDataOID();
 
         byte[] signedDataBytes = PkinitCrypto.cmsSignedDataCreate(
-                authPack.encode(), oid, 3, null, null, null, null);
+            KrbCodec.encode(authPack), oid, 3, null, null, null, null);
 
         return signedDataBytes;
     }
@@ -363,7 +364,7 @@
 
         PaDataEntry paDataEntry = new PaDataEntry();
         paDataEntry.setPaDataType(PaDataType.PK_AS_REQ);
-        paDataEntry.setPaDataValue(paPkAsReq.encode());
+        paDataEntry.setPaDataValue(KrbCodec.encode(paPkAsReq));
         return paDataEntry;
     }
 }
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/token/TokenPreauth.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/token/TokenPreauth.java
index c505e88..15f9874 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/token/TokenPreauth.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/preauth/token/TokenPreauth.java
@@ -21,6 +21,7 @@
 
 import org.apache.kerby.KOption;
 import org.apache.kerby.KOptions;
+import org.apache.kerby.kerberos.kerb.KrbCodec;
 import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.client.KrbContext;
 import org.apache.kerby.kerberos.kerb.client.TokenOption;
@@ -196,7 +197,7 @@
 
         PaDataEntry paDataEntry = new PaDataEntry();
         paDataEntry.setPaDataType(PaDataType.TOKEN_REQUEST);
-        paDataEntry.setPaDataValue(paDataValue.encode());
+        paDataEntry.setPaDataValue(KrbCodec.encode(paDataValue));
 
         return paDataEntry;
     }
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/ArmoredRequest.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/ArmoredRequest.java
index e122856..4bc99ed 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/ArmoredRequest.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/ArmoredRequest.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kerb.client.request;
 
 import org.apache.kerby.KOptions;
+import org.apache.kerby.kerberos.kerb.KrbCodec;
 import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.ccache.Credential;
 import org.apache.kerby.kerberos.kerb.ccache.CredentialCache;
@@ -69,7 +70,7 @@
         KrbFastRequestState state = kdcRequest.getFastRequestState();
         fastAsArmor(state, kdcRequest.getArmorKey(), subKey, credential, kdcReq);
         kdcRequest.setFastRequestState(state);
-        kdcRequest.setOuterRequestBody(state.getFastOuterRequest().encode());
+        kdcRequest.setOuterRequestBody(KrbCodec.encode(state.getFastOuterRequest()));
         kdcReq.getPaData().addElement(makeFastEntry(state, kdcReq,
             kdcRequest.getOuterRequestBody()));
     }
@@ -149,7 +150,7 @@
 
         PaDataEntry paDataEntry = new PaDataEntry();
         paDataEntry.setPaDataType(PaDataType.FX_FAST);
-        paDataEntry.setPaDataValue(armoredReq.encode());
+        paDataEntry.setPaDataValue(KrbCodec.encode(armoredReq));
 
         return paDataEntry;
     }
@@ -159,7 +160,7 @@
         KrbFastArmor fastArmor = new KrbFastArmor();
         fastArmor.setArmorType(ArmorType.ARMOR_AP_REQUEST);
         ApReq apReq = makeApReq(subKey, credential);
-        fastArmor.setArmorValue(apReq.encode());
+        fastArmor.setArmorValue(KrbCodec.encode(apReq));
         return fastArmor;
     }
 
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequestWithPasswd.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequestWithPasswd.java
index df3a5a9..627c419 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequestWithPasswd.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/request/AsRequestWithPasswd.java
@@ -19,10 +19,10 @@
  */
 package org.apache.kerby.kerberos.kerb.client.request;
 
+import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.client.KrbContext;
 import org.apache.kerby.kerberos.kerb.client.KrbOption;
 import org.apache.kerby.kerberos.kerb.crypto.EncryptionHandler;
-import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
 import org.apache.kerby.kerberos.kerb.type.pa.PaDataType;
 
diff --git a/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/KrbClientSettingTest.java b/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/KrbClientSettingTest.java
index 36eeaa2..da0064e 100644
--- a/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/KrbClientSettingTest.java
+++ b/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/KrbClientSettingTest.java
@@ -24,7 +24,7 @@
 import java.io.File;
 import java.net.URL;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.*;
 
 public class KrbClientSettingTest {
 
diff --git a/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/TestKrbConfigLoad.java b/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/TestKrbConfigLoad.java
index bda9c50..4520e86 100644
--- a/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/TestKrbConfigLoad.java
+++ b/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/TestKrbConfigLoad.java
@@ -25,7 +25,7 @@
 import java.io.File;
 import java.net.URL;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.*;
 
 /**
  * Test for loading configurations form krb5.conf.
diff --git a/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/TestKrbConfigLoadForSpecials.java b/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/TestKrbConfigLoadForSpecials.java
index 320a8bd..a713e1e 100644
--- a/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/TestKrbConfigLoadForSpecials.java
+++ b/kerby-kerb/kerb-client/src/test/java/org/apache/kerby/kerberos/kerb/client/TestKrbConfigLoadForSpecials.java
@@ -24,7 +24,7 @@
 import java.io.File;
 import java.net.URL;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.*;
 
 /**
  * Test for loading configurations form krb5.conf with default kdc realm.
diff --git a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/CheckSumUtil.java b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/CheckSumUtil.java
index 139354a..1b3400a 100644
--- a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/CheckSumUtil.java
+++ b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/CheckSumUtil.java
@@ -20,6 +20,7 @@
 package org.apache.kerby.kerberos.kerb.common;
 
 import org.apache.kerby.asn1.type.Asn1Encodeable;
+import org.apache.kerby.kerberos.kerb.KrbCodec;
 import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.crypto.CheckSumHandler;
 import org.apache.kerby.kerberos.kerb.crypto.EncTypeHandler;
@@ -52,14 +53,14 @@
 
     public static CheckSum seal(Asn1Encodeable asn1Object,
                                 CheckSumType checkSumType) throws KrbException {
-        byte[] encoded = asn1Object.encode();
+        byte[] encoded = KrbCodec.encode(asn1Object);
         CheckSum checksum = makeCheckSum(checkSumType, encoded);
         return checksum;
     }
 
     public static CheckSum seal(Asn1Encodeable asn1Object, CheckSumType checkSumType,
                                      EncryptionKey key, KeyUsage usage) throws KrbException {
-        byte[] encoded = asn1Object.encode();
+        byte[] encoded = KrbCodec.encode(asn1Object);
         CheckSum checksum = makeCheckSumWithKey(checkSumType, encoded, key, usage);
         return checksum;
     }
diff --git a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/EncryptionUtil.java b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/EncryptionUtil.java
index d205b35..7924697 100644
--- a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/EncryptionUtil.java
+++ b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/common/EncryptionUtil.java
@@ -126,7 +126,7 @@
 
     public static EncryptedData seal(Asn1Encodeable asn1Type,
                                      EncryptionKey key, KeyUsage usage) throws KrbException {
-        byte[] encoded = asn1Type.encode();
+        byte[] encoded = KrbCodec.encode(asn1Type);
         EncryptedData encrypted = EncryptionHandler.encrypt(encoded, key, usage);
         return encrypted;
     }
diff --git a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitCrypto.java b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitCrypto.java
index e9e1ae9..409ef44 100644
--- a/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitCrypto.java
+++ b/kerby-kerb/kerb-common/src/main/java/org/apache/kerby/kerberos/kerb/preauth/pkinit/PkinitCrypto.java
@@ -26,6 +26,7 @@
 import org.apache.kerby.cms.type.RevocationInfoChoices;
 import org.apache.kerby.cms.type.SignedData;
 import org.apache.kerby.cms.type.SignerInfos;
+import org.apache.kerby.kerberos.kerb.KrbCodec;
 import org.apache.kerby.kerberos.kerb.KrbErrorCode;
 import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
@@ -223,7 +224,7 @@
     public static byte[] cmsSignedDataCreate(byte[] data, Asn1ObjectIdentifier oid, int version,
                                              DigestAlgorithmIdentifiers digestAlgorithmIdentifiers,
                                              CertificateSet certificateSet,
-                                             RevocationInfoChoices crls, SignerInfos signerInfos) {
+                                             RevocationInfoChoices crls, SignerInfos signerInfos) throws KrbException {
         ContentInfo contentInfo = new ContentInfo();
         contentInfo.setContentType(new Asn1ObjectIdentifier("1.2.840.113549.1.7.2"));
         SignedData signedData = new SignedData();
@@ -245,7 +246,7 @@
             signedData.setSignerInfos(signerInfos);
         }
         contentInfo.setContent(signedData);
-        return contentInfo.encode();
+        return KrbCodec.encode(contentInfo);
     }
 
     public static X509Certificate[] createCertChain(PkinitPlgCryptoContext cryptoContext)
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 ce8b34c..1c2f4dc 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
@@ -38,7 +38,19 @@
 public class KrbCodec {
 
     public static byte[] encode(Asn1Type krbObj) throws KrbException {
-        return krbObj.encode();
+        try {
+            return krbObj.encode();
+        } catch (IOException e) {
+            throw new KrbException("encode failed", e);
+        }
+    }
+
+    public static void encode(Asn1Type krbObj, ByteBuffer buffer) throws KrbException {
+        try {
+            krbObj.encode(buffer);
+        } catch (IOException e) {
+            throw new KrbException("encode failed", e);
+        }
     }
 
     public static <T extends Asn1Type> T decode(
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcHandler.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcHandler.java
index 78eb8a0..2728124 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcHandler.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/KdcHandler.java
@@ -129,7 +129,7 @@
         } else {
             responseMessage = ByteBuffer.allocate(bodyLen);
         }
-        krbResponse.encode(responseMessage);
+        KrbCodec.encode(krbResponse, responseMessage);
         responseMessage.flip();
 
         return responseMessage;
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java
index 7e2c54a..bceef01 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/pkinit/PkinitPreauth.java
@@ -280,13 +280,14 @@
         paDataEntry.setPaDataType(PaDataType.PK_AS_REP);
         //TODO CHOICE
         //paDataEntry.setPaDataValue(paPkAsRep.encode());
-        paDataEntry.setPaDataValue(paPkAsRep.getDHRepInfo().encode());
+        byte[] paData = KrbCodec.encode(paPkAsRep.getDHRepInfo());
+        paDataEntry.setPaDataValue(paData);
 
         return paDataEntry;
     }
 
     private PaPkAsRep makePaPkAsRep(PkinitPlgCryptoContext cryptoContext,
-                                    DHPublicKey severPubKey, String identityString) {
+                                    DHPublicKey severPubKey, String identityString) throws KrbException {
 
         List<String> identityList = Arrays.asList(identityString.split(","));
 
@@ -322,7 +323,8 @@
         KdcDHKeyInfo kdcDhKeyInfo = new KdcDHKeyInfo();
 
         Asn1Integer publickey = new Asn1Integer(severPubKey.getY());
-        kdcDhKeyInfo.setSubjectPublicKey(publickey.encode());
+        byte[] pubKeyData = KrbCodec.encode(publickey);
+        kdcDhKeyInfo.setSubjectPublicKey(pubKeyData);
         kdcDhKeyInfo.setNonce(0);
         kdcDhKeyInfo.setDHKeyExpiration(
                 new KerberosTime(System.currentTimeMillis() + KerberosTime.DAY));
@@ -338,7 +340,7 @@
         }
 
         Asn1ObjectIdentifier oid = cryptoContext.getIdPkinitDHKeyDataOID();
-        signedDataBytes = PkinitCrypto.cmsSignedDataCreate(kdcDhKeyInfo.encode(), oid, 3, null,
+        signedDataBytes = PkinitCrypto.cmsSignedDataCreate(KrbCodec.encode(kdcDhKeyInfo), oid, 3, null,
                 null, null, null);
 
         dhRepInfo.setDHSignedData(signedDataBytes);
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
index 2a80845..d3c675c 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/request/KdcRequest.java
@@ -214,7 +214,7 @@
                 KrbFastReq fastReq = KrbCodec.decode(
                         EncryptionHandler.decrypt(encryptedData, getArmorKey(), KeyUsage.FAST_ENC),
                         KrbFastReq.class);
-                innerBodyout = fastReq.getKdcReqBody().encode();
+                innerBodyout = KrbCodec.encode(fastReq.getKdcReqBody());
 
                 // TODO: get checksumed data in stream
                 CheckSum checkSum = fastArmoredReq.getReqChecksum();
@@ -222,7 +222,8 @@
                     LOG.warn("Checksum is empty.");
                     throw new KrbException(KrbErrorCode.KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED);
                 }
-                CheckSumHandler.verifyWithKey(checkSum, getKdcReq().getReqBody().encode(),
+                byte[] reqBody = KrbCodec.encode(getKdcReq().getReqBody());
+                    CheckSumHandler.verifyWithKey(checkSum, reqBody,
                         getArmorKey().getKeyData(), KeyUsage.FAST_REQ_CHKSUM);
             }
         }
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/PKCS8Key.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/PKCS8Key.java
index 7c4cdaf..b39e3be 100644
--- a/kerby-pkix/src/main/java/org/apache/commons/ssl/PKCS8Key.java
+++ b/kerby-pkix/src/main/java/org/apache/commons/ssl/PKCS8Key.java
@@ -130,7 +130,7 @@
      *                                  occured.
      */
     public PKCS8Key(final ByteArrayInputStream in, char[] password)
-        throws GeneralSecurityException {
+        throws GeneralSecurityException, IOException {
         this(Util.streamToBytes(in), password);
     }
 
@@ -142,7 +142,7 @@
      *                                  occured.
      */
     public PKCS8Key(final byte[] encoded, char[] password)
-        throws GeneralSecurityException {
+        throws GeneralSecurityException, IOException {
         DecryptResult decryptResult =
             new DecryptResult("UNENCRYPTED", 0, encoded);
 
@@ -925,7 +925,7 @@
     }
 
     public static byte[] formatAsPKCS8(byte[] privateKey, String oid,
-                                       PkcsStructure pkcs8) {
+                                       PkcsStructure pkcs8) throws IOException {
         Asn1Integer derZero = new Asn1Integer(BigInteger.ZERO);
         Asn1Sequence outterSeq = new Asn1Sequence();
         Asn1Sequence innerSeq = new Asn1Sequence();
diff --git a/kerby-pkix/src/test/java/org/apache/kerby/cms/TestCertificate.java b/kerby-pkix/src/test/java/org/apache/kerby/cms/TestCertificate.java
index 5db4a0d..c62d69a 100644
--- a/kerby-pkix/src/test/java/org/apache/kerby/cms/TestCertificate.java
+++ b/kerby-pkix/src/test/java/org/apache/kerby/cms/TestCertificate.java
@@ -46,10 +46,13 @@
     @Test
     public void testEncodingCertificate() throws IOException {
         byte[] data = readDataFile("/certificate1.txt");
+        Asn1.parseAndDump(data);
         try {
             Certificate certificate = new Certificate();
             certificate.decode(data);
-            certificate.encode();
+            Asn1.dump(certificate);
+            byte[] encodedData = certificate.encode();
+            Asn1.parseAndDump(encodedData);
 
         } catch (Exception e) {
             e.printStackTrace();
diff --git a/kerby-pkix/src/test/java/org/apache/kerby/cms/TestSignedData.java b/kerby-pkix/src/test/java/org/apache/kerby/cms/TestSignedData.java
index 2483be3..4b67bd2 100644
--- a/kerby-pkix/src/test/java/org/apache/kerby/cms/TestSignedData.java
+++ b/kerby-pkix/src/test/java/org/apache/kerby/cms/TestSignedData.java
@@ -49,17 +49,15 @@
             contentInfo.getContentAs(SignedData.class);
             Asn1.dump(signedData);
 
-            // TO BE FIXED
-            //Asn1.dump(contentInfo);
-            //byte[] encodedData = contentInfo.encode();
-            //Asn1.parseAndDump(encodedData);
+            Asn1.dump(contentInfo);
+            byte[] encodedData = contentInfo.encode();
+            Asn1.parseAndDump(encodedData);
         } catch (Exception e) {
             e.printStackTrace();
             Assert.fail();
         }
     }
 
-    // To be fixed
     @Test
     public void testEncoding() throws IOException {
         ContentInfo contentInfo = new ContentInfo();
@@ -77,7 +75,7 @@
         certificateChoices.setCertificate(certificate);
         CertificateSet certificateSet = new CertificateSet();
         certificateSet.addElement(certificateChoices);
-        //signedData.setCertificates(certificateSet);
+        signedData.setCertificates(certificateSet);
 
         contentInfo.setContent(signedData);
         Asn1.dump(contentInfo);