directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dran...@apache.org
Subject [08/13] directory-kerby git commit: Consolidated facility and support modules into kerby-common
Date Sat, 16 Jan 2016 09:38:36 GMT
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Boolean.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Boolean.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Boolean.java
new file mode 100644
index 0000000..9679783
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Boolean.java
@@ -0,0 +1,85 @@
+/**
+ *  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 org.apache.kerby.asn1.parse.Asn1ParseResult;
+
+import java.io.IOException;
+
+/**
+ * ASN1 Boolean type
+ */
+public class Asn1Boolean extends Asn1Simple<Boolean> {
+    private static final byte[] TRUE_BYTE = new byte[] {(byte) 0xff};
+    private static final byte[] FALSE_BYTE = new byte[] {(byte) 0x00};
+
+    public static final Asn1Boolean TRUE = new Asn1Boolean(true);
+    public static final Asn1Boolean FALSE = new Asn1Boolean(false);
+
+    /**
+     * Default constructor, generally for decoding as a container
+     */
+    public Asn1Boolean() {
+        this(null);
+    }
+
+    /**
+     * Constructor with a value, generally for encoding of the value
+     * @param value The boolean value
+     */
+    public Asn1Boolean(Boolean value) {
+        super(UniversalTag.BOOLEAN, value);
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        return 1;
+    }
+
+    @Override
+    protected void decodeBody(Asn1ParseResult parseResult) throws IOException {
+        if (parseResult.getBodyLength() != 1) {
+            throw new IOException("More than 1 byte found for Boolean");
+        }
+        super.decodeBody(parseResult);
+    }
+
+    @Override
+    protected void toBytes() {
+        setBytes(getValue() ? TRUE_BYTE : FALSE_BYTE);
+    }
+
+    @Override
+    protected void toValue() throws IOException {
+        byte[] bytes = getBytes();
+        if (bytes[0] == 0) {
+            setValue(false);
+        } else if ((bytes[0] & 0xff) == 0xff) {
+            // DER only accepts 0xFF as true
+            setValue(true);
+        } else if (isBER()) {
+            // BER accepts any non-zero as true
+            setValue(true);
+        } else {
+            setValue(false);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java
new file mode 100644
index 0000000..8835c9d
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Choice.java
@@ -0,0 +1,241 @@
+/**
+ *  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.Asn1Binder;
+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 org.apache.kerby.asn1.TaggingOption;
+import org.apache.kerby.asn1.UniversalTag;
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class Asn1Choice
+    extends AbstractAsn1Type<Asn1Type> implements Asn1Dumpable {
+
+    private final Asn1FieldInfo[] fieldInfos;
+    private final Tag[] tags;
+
+    private Asn1FieldInfo chosenField;
+
+    public Asn1Choice(Asn1FieldInfo[] fieldInfos) {
+        super(UniversalTag.CHOICE);
+
+        this.fieldInfos = fieldInfos;
+        this.tags = new Tag[fieldInfos.length];
+        initTags();
+    }
+
+    @Override
+    public Tag tag() {
+        if (getValue() != null) {
+            return getValue().tag();
+        } else if (chosenField != null) {
+            return chosenField.getFieldTag();
+        }
+        return super.tag();
+    }
+
+    private void initTags() {
+        for (int i = 0; i < fieldInfos.length; i++) {
+            tags[i] = fieldInfos[i].getFieldTag();
+        }
+    }
+
+    public boolean matchAndSetValue(Tag tag) {
+        int foundPos = -1;
+        for (int i = 0; i < fieldInfos.length; i++) {
+            if (tag.isContextSpecific()) {
+                if (fieldInfos[i].getTagNo() == tag.tagNo()) {
+                    foundPos = i;
+                    break;
+                }
+            } else if (tags[i].equals(tag)) {
+                foundPos = i;
+                break;
+            }
+        }
+
+        if (foundPos != -1) {
+            this.chosenField = fieldInfos[foundPos];
+            setValue(fieldInfos[foundPos].createFieldValue());
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public byte[] encode() throws IOException {
+        Asn1Encodeable theValue = (Asn1Encodeable) getValue();
+
+        if (theValue != null) {
+            if (chosenField.isTagged()) {
+                TaggingOption taggingOption =
+                        chosenField.getTaggingOption();
+                return theValue.taggedEncode(taggingOption);
+            } else {
+                return theValue.encode();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void encode(ByteBuffer buffer) throws IOException {
+        Asn1Encodeable theValue = (Asn1Encodeable) getValue();
+
+        if (theValue != null) {
+            if (chosenField.isTagged()) {
+                TaggingOption taggingOption =
+                        chosenField.getTaggingOption();
+                theValue.taggedEncode(buffer, taggingOption);
+            } else {
+                theValue.encode(buffer);
+            }
+        }
+    }
+
+    @Override
+    public int encodingLength() {
+        Asn1Encodeable theValue = (Asn1Encodeable) getValue();
+
+        if (theValue != null) {
+            if (chosenField.isTagged()) {
+                TaggingOption taggingOption =
+                    chosenField.getTaggingOption();
+                return theValue.taggedEncodingLength(taggingOption);
+            } else {
+                return theValue.encodingLength();
+            }
+        }
+
+        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
+    protected void encodeBody(ByteBuffer buffer) throws IOException {
+        Asn1Encodeable theValue = (Asn1Encodeable) getValue();
+
+        if (theValue != null) {
+            if (chosenField.isTagged()) {
+                TaggingOption taggingOption =
+                    chosenField.getTaggingOption();
+                theValue.taggedEncode(buffer, taggingOption);
+            } else {
+                theValue.encode(buffer);
+            }
+        }
+    }
+
+    @Override
+    public void decode(ByteBuffer content) throws IOException {
+        chosenField = null;
+        setValue(null);
+
+        super.decode(content);
+    }
+
+    @Override
+    public void decode(Asn1ParseResult parseResult) throws IOException {
+        if (chosenField == null) {
+            matchAndSetValue(parseResult.tag());
+        }
+
+        decodeBody(parseResult);
+    }
+
+    @Override
+    protected void decodeBody(Asn1ParseResult parseResult) throws IOException {
+        if (chosenField == null) {
+            matchAndSetValue(parseResult.tag());
+        }
+
+        if (chosenField == null) {
+            throw new IOException("Unexpected item, not in choices: "
+                + parseResult.simpleInfo());
+        }
+
+        Asn1Type fieldValue = getValue();
+        if (parseResult.isContextSpecific()) {
+            Asn1Binder.bindWithTagging(parseResult, fieldValue,
+                chosenField.getTaggingOption());
+        } else {
+            Asn1Binder.bind(parseResult, fieldValue);
+        }
+    }
+
+    protected <T extends Asn1Type> T getChoiceValueAs(EnumType index, Class<T> t) {
+        if (chosenField == null || getValue() == null) {
+            return null;
+        }
+
+        if (chosenField != null && index != chosenField.getIndex()) {
+            throw new IllegalArgumentException("Incorrect chosen value requested");
+        }
+
+        return (T) getValue();
+    }
+
+    protected void setChoiceValue(EnumType index, Asn1Type value) {
+        if (fieldInfos[index.getValue()].getIndex() != index) {
+            throw new IllegalArgumentException("Incorrect choice option to set");
+        }
+
+        this.chosenField = fieldInfos[index.getValue()];
+        setValue(value);
+    }
+
+    protected void setChoiceValueAsOctets(EnumType index, byte[] bytes) {
+        Asn1OctetString value = new Asn1OctetString(bytes);
+        setChoiceValue(index, value);
+    }
+
+    protected byte[] getChoiceValueAsOctets(EnumType index) {
+        Asn1OctetString value = getChoiceValueAs(index, Asn1OctetString.class);
+        if (value != null) {
+            return value.getValue();
+        }
+        return null;
+    }
+
+    @Override
+    public void dumpWith(Asn1Dumper dumper, int indents) {
+        Asn1Type theValue = getValue();
+        dumper.indent(indents).append("<Choice>").newLine();
+        //dumper.append(simpleInfo()).newLine();
+        dumper.dumpType(indents, theValue);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java
new file mode 100644
index 0000000..982c29e
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Collection.java
@@ -0,0 +1,79 @@
+/**
+ *  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.Tag;
+import org.apache.kerby.asn1.UniversalTag;
+
+/**
+ * ASN1 complex type of multiple ASN1 objects.
+ */
+public class Asn1Collection extends Asn1Constructed {
+
+    public Asn1Collection(UniversalTag universalTag) {
+        super(new Tag(universalTag));
+    }
+
+    public static boolean isCollection(Tag tag) {
+        return isCollection(tag.universalTag());
+    }
+
+    public static boolean isCollection(int tag) {
+        return isCollection(new Tag(tag));
+    }
+
+    public static boolean isCollection(UniversalTag universalTag) {
+        switch (universalTag) {
+            case SEQUENCE:
+            case SEQUENCE_OF:
+            case SET:
+            case SET_OF:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public static Asn1Collection createCollection(Tag tag) {
+        if (!isCollection(tag)) {
+            throw new IllegalArgumentException("Not collection type, tag: " + tag);
+        }
+        return createCollection(tag.universalTag());
+    }
+
+    public static Asn1Collection createCollection(UniversalTag universalTag) {
+        if (!isCollection(universalTag)) {
+            throw new IllegalArgumentException("Not collection type, tag: " + universalTag);
+        }
+
+        switch (universalTag) {
+            case SEQUENCE:
+                return new Asn1Sequence();
+            case SEQUENCE_OF:
+                return new Asn1Sequence();
+            case SET:
+                return new Asn1Set();
+            case SET_OF:
+                return new Asn1Set();
+            default:
+                throw new IllegalArgumentException("Unexpected tag " + universalTag.getValue());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionOf.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionOf.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionOf.java
new file mode 100644
index 0000000..5c9d3a2
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionOf.java
@@ -0,0 +1,88 @@
+/**
+ *  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.Asn1Binder;
+import org.apache.kerby.asn1.UniversalTag;
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+
+import java.io.IOException;
+import java.lang.reflect.ParameterizedType;
+import java.util.List;
+
+public abstract class Asn1CollectionOf<T extends Asn1Type>
+    extends Asn1Collection {
+
+    public Asn1CollectionOf(UniversalTag universalTag) {
+        super(universalTag);
+    }
+
+    @Override
+    protected void decodeElements() throws IOException {
+        for (Asn1ParseResult parsingItem : getContainer().getChildren()) {
+            if (parsingItem.isEOC()) {
+                continue;
+            }
+
+            Asn1Type tmpValue = createElement();
+            Asn1Binder.bind(parsingItem, tmpValue);
+            addItem(tmpValue);
+        }
+    }
+
+    public List<T> getElements() {
+        return (List<T>) getValue();
+    }
+
+    public void setElements(List<T> elements) {
+        super.clear();
+
+        for (T ele : elements) {
+            addElement(ele);
+        }
+    }
+
+    public void addElements(T ... elements) {
+        for (T ele : elements) {
+            addElement(ele);
+        }
+    }
+
+    public void addElement(T element) {
+        super.addItem(element);
+    }
+
+    private Class<T> getElementType() {
+        Class<T> elementType = (Class<T>) ((ParameterizedType)
+            getClass().getGenericSuperclass()).getActualTypeArguments()[0];
+        return elementType;
+    }
+
+    protected T createElement() throws IOException {
+        Class<?> eleType = getElementType();
+        try {
+            T result = (T) eleType.newInstance();
+            return result;
+        } catch (Exception e) {
+            throw new IOException("Failed to create element type, "
+                + "no default constructor? " + eleType.getName(), e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java
new file mode 100644
index 0000000..8f546c6
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1CollectionType.java
@@ -0,0 +1,299 @@
+/**
+ *  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.Asn1Binder;
+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;
+import org.apache.kerby.asn1.parse.Asn1Container;
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.util.List;
+
+/**
+ * For collection type that may consist of tagged fields
+ */
+public abstract class Asn1CollectionType
+    extends AbstractAsn1Type<Asn1CollectionType> implements Asn1Dumpable {
+    private final Asn1FieldInfo[] fieldInfos;
+    private final Asn1Type[] fields;
+
+    public Asn1CollectionType(UniversalTag universalTag,
+                              final Asn1FieldInfo[] fieldInfos) {
+        super(universalTag);
+
+        setValue(this);
+        this.fieldInfos = fieldInfos;
+        this.fields = new Asn1Type[fieldInfos.length];
+        usePrimitive(false);
+    }
+
+    @Override
+    protected int encodingBodyLength() throws IOException {
+        int allLen = 0;
+        int fieldLen;
+        for (int i = 0; i < fields.length; ++i) {
+            Asn1Encodeable field = (Asn1Encodeable) fields[i];
+            if (field != null) {
+                if (fieldInfos[i].isTagged()) {
+                    TaggingOption taggingOption =
+                        fieldInfos[i].getTaggingOption();
+                    fieldLen = field.taggedEncodingLength(taggingOption);
+                } else {
+                    fieldLen = field.encodingLength();
+                }
+                allLen += fieldLen;
+            }
+        }
+        return allLen;
+    }
+
+    @Override
+    protected void encodeBody(ByteBuffer buffer) throws IOException {
+        for (int i = 0; i < fields.length; ++i) {
+            Asn1Type field = fields[i];
+            if (field != null) {
+                if (fieldInfos[i].isTagged()) {
+                    TaggingOption taggingOption =
+                        fieldInfos[i].getTaggingOption();
+                    field.taggedEncode(buffer, taggingOption);
+                } else {
+                    field.encode(buffer);
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void decodeBody(Asn1ParseResult parseResult) throws IOException {
+        checkAndInitFields();
+        useDefinitiveLength(parseResult.isDefinitiveLength());
+
+        Asn1Container container = (Asn1Container) parseResult;
+        List<Asn1ParseResult> parseResults = container.getChildren();
+
+        int lastPos = -1, foundPos = -1;
+
+        for (Asn1ParseResult parseItem : parseResults) {
+            if (parseItem.isEOC()) {
+                continue;
+            }
+
+            foundPos = match(lastPos, parseItem);
+            if (foundPos == -1) {
+                throw new IOException("Unexpected item: " + parseItem.simpleInfo());
+            }
+            lastPos = foundPos;
+
+            attemptBinding(parseItem, foundPos);
+        }
+    }
+
+    private void attemptBinding(Asn1ParseResult parseItem,
+                                int foundPos) throws IOException {
+        Asn1Type fieldValue = fields[foundPos];
+        Asn1FieldInfo fieldInfo = fieldInfos[foundPos];
+
+        if (fieldValue instanceof Asn1Any) {
+            Asn1Any any = (Asn1Any) fieldValue;
+            any.setDecodeInfo(fieldInfo);
+            Asn1Binder.bind(parseItem, any);
+        } else {
+            if (parseItem.isContextSpecific()) {
+                Asn1Binder.bindWithTagging(parseItem, fieldValue,
+                    fieldInfo.getTaggingOption());
+            } else {
+                Asn1Binder.bind(parseItem, fieldValue);
+            }
+        }
+    }
+
+    private int match(int lastPos, Asn1ParseResult parseItem) {
+        int foundPos = -1;
+        for (int i = lastPos + 1; i < fieldInfos.length; ++i) {
+            Asn1Type fieldValue = fields[i];
+            Asn1FieldInfo fieldInfo = fieldInfos[i];
+
+            if (fieldInfo.isTagged()) {
+                if (!parseItem.isContextSpecific()) {
+                    continue;
+                }
+                if (fieldInfo.getTagNo() == parseItem.tagNo()) {
+                    foundPos = i;
+                    break;
+                }
+            } else if (fieldValue.tag().equals(parseItem.tag())) {
+                foundPos = i;
+                break;
+            } else if (fieldValue instanceof Asn1Choice) {
+                Asn1Choice aChoice = (Asn1Choice) fields[i];
+                if (aChoice.matchAndSetValue(parseItem.tag())) {
+                    foundPos = i;
+                    break;
+                }
+            } else if (fieldValue instanceof Asn1Any) {
+                foundPos = i;
+                break;
+            }
+        }
+
+        return foundPos;
+    }
+
+    private void checkAndInitFields() {
+        for (int i = 0; i < fieldInfos.length; ++i) {
+            checkAndInitField(i);
+        }
+    }
+
+    private void checkAndInitField(int index) {
+        if (fields[index] == null) {
+            fields[index] = fieldInfos[index].createFieldValue();
+        }
+    }
+
+    protected abstract Asn1Collection createCollection();
+
+    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(EnumType index, Asn1Type value) {
+        fields[index.getValue()] = value;
+    }
+
+    protected String getFieldAsString(EnumType index) {
+        Asn1Type value = fields[index.getValue()];
+        if (value == null) {
+            return null;
+        }
+
+        if (value instanceof Asn1String) {
+            return ((Asn1String) value).getValue();
+        }
+
+        throw new RuntimeException("The targeted field type isn't of string");
+    }
+
+    protected byte[] getFieldAsOctets(EnumType index) {
+        Asn1OctetString value = getFieldAs(index, Asn1OctetString.class);
+        if (value != null) {
+            return value.getValue();
+        }
+        return null;
+    }
+
+    protected void setFieldAsOctets(EnumType index, byte[] bytes) {
+        Asn1OctetString value = new Asn1OctetString(bytes);
+        setFieldAs(index, value);
+    }
+
+    protected Integer getFieldAsInteger(EnumType index) {
+        Asn1Integer value = getFieldAs(index, Asn1Integer.class);
+        if (value != null && value.getValue() != null) {
+            return value.getValue().intValue();
+        }
+        return null;
+    }
+
+    protected void setFieldAsInt(EnumType index, int value) {
+        setFieldAs(index, new Asn1Integer(value));
+    }
+
+    protected void setFieldAsInt(EnumType index, BigInteger value) {
+        setFieldAs(index, new Asn1Integer(value));
+    }
+
+    protected void setFieldAsObjId(EnumType index, String value) {
+        setFieldAs(index, new Asn1ObjectIdentifier(value));
+    }
+
+    protected String getFieldAsObjId(EnumType index) {
+        Asn1ObjectIdentifier objId = getFieldAs(index, Asn1ObjectIdentifier.class);
+        if (objId != null) {
+            return objId.getValue();
+        }
+        return null;
+    }
+
+    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);
+        }
+        return null;
+    }
+
+    protected void setFieldAsAny(EnumType index, Asn1Type value) {
+        if (value != null) {
+            Asn1Any any = new Asn1Any(value);
+            any.setDecodeInfo(fieldInfos[index.getValue()]);
+            setFieldAs(index, any);
+        }
+    }
+
+    protected void setAnyFieldValueType(EnumType index,
+                                        Class<? extends Asn1Type> valueType) {
+        if (valueType != null) {
+            checkAndInitField(index.getValue());
+            Asn1Type value = fields[index.getValue()];
+            if (value != null && value instanceof Asn1Any) {
+                Asn1Any any = (Asn1Any) value;
+                any.setValueType(valueType);
+            }
+        }
+    }
+
+    @Override
+    public void dumpWith(Asn1Dumper dumper, int indents) {
+        dumper.indent(indents).appendType(getClass());
+        dumper.append(simpleInfo()).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);
+            } else {
+                dumper.newLine().dumpType(indents + 8, fdValue);
+            }
+            if (i < fieldInfos.length - 1) {
+                dumper.newLine();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Constructed.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Constructed.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Constructed.java
new file mode 100644
index 0000000..fd8a187
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Constructed.java
@@ -0,0 +1,132 @@
+/**
+ *  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.Asn1Converter;
+import org.apache.kerby.asn1.Asn1Dumpable;
+import org.apache.kerby.asn1.Asn1Dumper;
+import org.apache.kerby.asn1.Tag;
+import org.apache.kerby.asn1.parse.Asn1Container;
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * ASN1 constructed types, mainly structured ones, but also some primitive ones.
+ */
+public class Asn1Constructed
+    extends AbstractAsn1Type<List<Asn1Type>> implements Asn1Dumpable {
+
+    protected Asn1Container container;
+
+    private boolean lazy = false;
+
+    public Asn1Constructed(Tag tag) {
+        super(tag);
+        setValue(new ArrayList<Asn1Type>());
+        usePrimitive(false);
+    }
+
+
+    public Asn1Container getContainer() {
+        return container;
+    }
+
+    public void setLazy(boolean lazy) {
+        this.lazy = lazy;
+    }
+
+    public boolean isLazy() {
+        return lazy;
+    }
+
+    public void addItem(Asn1Type value) {
+        getValue().add(value);
+    }
+
+    public void clear() {
+        getValue().clear();
+    }
+
+    @Override
+    protected int encodingBodyLength() throws IOException {
+        List<Asn1Type> valueItems = getValue();
+        int allLen = 0;
+        for (Asn1Type item : valueItems) {
+            if (item != null) {
+                allLen += item.encodingLength();
+            }
+        }
+        return allLen;
+    }
+
+    @Override
+    protected void encodeBody(ByteBuffer buffer) throws IOException {
+        List<Asn1Type> valueItems = getValue();
+        for (Asn1Type item : valueItems) {
+            if (item != null) {
+                item.encode(buffer);
+            }
+        }
+    }
+
+    @Override
+    protected void decodeBody(Asn1ParseResult parseResult) throws IOException {
+        Asn1Container container = (Asn1Container) parseResult;
+        this.container = container;
+        useDefinitiveLength(parseResult.isDefinitiveLength());
+
+        if (!isLazy()) {
+            decodeElements();
+        }
+    }
+
+    protected void decodeElements() throws IOException {
+        for (Asn1ParseResult parsingItem : getContainer().getChildren()) {
+            if (parsingItem.isEOC()) {
+                continue;
+            }
+
+            Asn1Type tmpValue = Asn1Converter.convert(parsingItem, lazy);
+            addItem(tmpValue);
+        }
+    }
+
+    @Override
+    public void dumpWith(Asn1Dumper dumper, int indents) {
+        String typeStr = tag().typeStr() + " ["
+            + "tag=" + tag()
+            + ", len=" + getHeaderLength() + "+" + getBodyLength()
+            + "] ";
+        dumper.indent(indents).append(typeStr).newLine();
+
+        List<Asn1Type> items = getValue();
+        int i = 0;
+        for (Asn1Type aObj : items) {
+            dumper.dumpType(indents + 4, aObj);
+            if (i++ != items.size() - 1) {
+                dumper.newLine();
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java
new file mode 100644
index 0000000..0bd2e81
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Encodeable.java
@@ -0,0 +1,292 @@
+/**
+ *  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.Tag;
+import org.apache.kerby.asn1.TaggingOption;
+import org.apache.kerby.asn1.UniversalTag;
+import org.apache.kerby.asn1.parse.Asn1Container;
+import org.apache.kerby.asn1.parse.Asn1DerivedItem;
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+import org.apache.kerby.asn1.parse.Asn1Parser;
+import org.apache.kerby.asn1.util.Asn1Util;
+
+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 abstract class Asn1Encodeable extends Asn1Object implements Asn1Type {
+
+    private int bodyLength = -1;
+
+    // encoding options
+    private EncodingType encodingType = EncodingType.BER;
+    private boolean isImplicit = true;
+    private boolean isDefinitiveLength = true; // by default!!
+
+    /**
+     * Constructor with a tag
+     * @param tag The tag
+     */
+    public Asn1Encodeable(Tag tag) {
+        super(tag);
+    }
+
+    /**
+     * Default constructor with an universal tag.
+     * @param tag the tag
+     */
+    public Asn1Encodeable(UniversalTag tag) {
+        super(tag);
+    }
+
+    /**
+     * Constructor with a tag
+     * @param tag The tag
+     */
+    public Asn1Encodeable(int tag) {
+        super(tag);
+    }
+
+    @Override
+    public void usePrimitive(boolean isPrimitive) {
+        tag().usePrimitive(isPrimitive);
+    }
+
+    @Override
+    public boolean isPrimitive() {
+        return tag().isPrimitive();
+    }
+
+    @Override
+    public void useDefinitiveLength(boolean isDefinitiveLength) {
+        this.isDefinitiveLength = isDefinitiveLength;
+    }
+
+    @Override
+    public boolean isDefinitiveLength() {
+        return isDefinitiveLength;
+    }
+
+    @Override
+    public void useImplicit(boolean isImplicit) {
+        this.isImplicit = isImplicit;
+    }
+
+    @Override
+    public boolean isImplicit() {
+        return isImplicit;
+    }
+
+    @Override
+    public void useDER() {
+        this.encodingType = EncodingType.DER;
+    }
+
+    @Override
+    public boolean isDER() {
+        return encodingType == EncodingType.DER;
+    }
+
+    @Override
+    public void useBER() {
+        this.encodingType = EncodingType.BER;
+    }
+
+    @Override
+    public boolean isBER() {
+        return encodingType == EncodingType.BER;
+    }
+
+    @Override
+    public void useCER() {
+        this.encodingType = EncodingType.CER;
+    }
+
+    @Override
+    public boolean isCER() {
+        return encodingType == EncodingType.CER;
+    }
+
+    @Override
+    public byte[] encode() throws IOException {
+        int len = encodingLength();
+        ByteBuffer byteBuffer = ByteBuffer.allocate(len);
+        encode(byteBuffer);
+        byteBuffer.flip();
+        return byteBuffer.array();
+    }
+
+    @Override
+    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) throws IOException { }
+
+    @Override
+    public void decode(byte[] content) throws IOException {
+        decode(ByteBuffer.wrap(content));
+    }
+
+    @Override
+    public int encodingLength() {
+        return getHeaderLength() + getBodyLength();
+    }
+
+    @Override
+    protected int getHeaderLength() {
+        try {
+            return encodingHeaderLength();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    protected int getBodyLength() {
+        if (bodyLength == -1) {
+            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() throws IOException {
+        int headerLen = Asn1Util.lengthOfTagLength(tagNo());
+        int bodyLen = getBodyLength();
+        headerLen += Asn1Util.lengthOfBodyLength(bodyLen);
+
+        return headerLen;
+    }
+
+    protected abstract int encodingBodyLength() throws IOException;
+
+    @Override
+    public void decode(ByteBuffer content) throws IOException {
+        Asn1ParseResult parseResult = Asn1Parser.parse(content);
+        decode(parseResult);
+    }
+
+    public void decode(Asn1ParseResult parseResult) throws IOException {
+        Asn1ParseResult tmpParseResult = parseResult;
+
+        if (!tag().equals(parseResult.tag())) {
+            // Primitive but using constructed encoding
+            if (isPrimitive() && !parseResult.isPrimitive()) {
+                Asn1Container container = (Asn1Container) parseResult;
+                tmpParseResult = new Asn1DerivedItem(tag(), container);
+            } else {
+                throw new IOException("Unexpected item " + parseResult.simpleInfo()
+                    + ", expecting " + tag());
+            }
+        }
+
+        decodeBody(tmpParseResult);
+    }
+
+    protected abstract void decodeBody(Asn1ParseResult parseResult) throws IOException;
+
+    protected int taggedEncodingLength(TaggingOption taggingOption) {
+        int taggingTagNo = taggingOption.getTagNo();
+        int taggingBodyLen = taggingOption.isImplicit() ? getBodyLength()
+                : encodingLength();
+        int taggingEncodingLen = Asn1Util.lengthOfTagLength(taggingTagNo)
+                    + Asn1Util.lengthOfBodyLength(taggingBodyLen) + taggingBodyLen;
+        return taggingEncodingLen;
+    }
+
+    @Override
+    public byte[] taggedEncode(TaggingOption taggingOption) throws IOException {
+        int len = taggedEncodingLength(taggingOption);
+        ByteBuffer byteBuffer = ByteBuffer.allocate(len);
+        taggedEncode(byteBuffer, taggingOption);
+        byteBuffer.flip();
+        return byteBuffer.array();
+    }
+
+    @Override
+    public void taggedEncode(ByteBuffer buffer, TaggingOption taggingOption) throws IOException {
+        Tag taggingTag = taggingOption.getTag(!isPrimitive());
+        Asn1Util.encodeTag(buffer, taggingTag);
+
+        int taggingBodyLen = taggingOption.isImplicit() ? encodingBodyLength()
+            : encodingLength();
+        Asn1Util.encodeLength(buffer, taggingBodyLen);
+
+        if (taggingOption.isImplicit()) {
+            encodeBody(buffer);
+        } else {
+            encode(buffer);
+        }
+    }
+
+    @Override
+    public void taggedDecode(byte[] content,
+                             TaggingOption taggingOption) throws IOException {
+        taggedDecode(ByteBuffer.wrap(content), taggingOption);
+    }
+
+    @Override
+    public void taggedDecode(ByteBuffer content,
+                             TaggingOption taggingOption) throws IOException {
+        Asn1ParseResult parseResult = Asn1Parser.parse(content);
+        taggedDecode(parseResult, taggingOption);
+    }
+
+    public void taggedDecode(Asn1ParseResult parseResult,
+                                TaggingOption taggingOption) throws IOException {
+        Tag expectedTaggingTagFlags = taggingOption.getTag(!isPrimitive());
+
+        Asn1ParseResult tmpParseResult = parseResult;
+        if (!expectedTaggingTagFlags.equals(parseResult.tag())) {
+            // Primitive but using constructed encoding
+            if (isPrimitive() && !parseResult.isPrimitive()) {
+                Asn1Container container = (Asn1Container) parseResult;
+                tmpParseResult = new Asn1DerivedItem(tag(), container);
+            } else {
+                throw new IOException("Unexpected tag " + parseResult.tag()
+                    + ", expecting " + expectedTaggingTagFlags);
+            }
+        }
+
+        if (taggingOption.isImplicit()) {
+            decodeBody(tmpParseResult);
+        } else {
+
+            Asn1Container container = (Asn1Container) parseResult;
+            tmpParseResult = container.getChildren().get(0);
+            
+            decode(tmpParseResult);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Enumerated.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Enumerated.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Enumerated.java
new file mode 100644
index 0000000..223fc97
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Enumerated.java
@@ -0,0 +1,65 @@
+/**
+ *  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.EnumType;
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+/**
+ * The ASN1 enumerated type
+ */
+public abstract class Asn1Enumerated<T extends EnumType> extends Asn1Simple<T> {
+
+    /**
+     * Default constructor, generally for decoding as a container
+     */
+    public Asn1Enumerated() {
+        this(null);
+    }
+
+    /**
+     * Constructor with a value, generally for encoding of the value
+     * @param value The boolean value
+     */
+    public Asn1Enumerated(T value) {
+        super(UniversalTag.ENUMERATED, value);
+    }
+
+    protected void toBytes() {
+        BigInteger biValue = BigInteger.valueOf(getValue().getValue());
+        setBytes(biValue.toByteArray());
+    }
+
+    protected void toValue() throws IOException {
+        BigInteger biVal = new BigInteger(getBytes());
+        int iVal = biVal.intValue();
+        EnumType[] allValues = getAllEnumValues();
+        for (EnumType val : allValues) {
+            if (val.getValue() == iVal) {
+                setValue((T) val);
+            }
+        }
+    }
+
+    protected abstract EnumType[] getAllEnumValues();
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Eoc.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Eoc.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Eoc.java
new file mode 100644
index 0000000..44cdd21
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Eoc.java
@@ -0,0 +1,70 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+
+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
+    public void encode(ByteBuffer buffer) {
+        buffer.put((byte) 0);
+        buffer.put((byte) 0);
+    }
+
+    @Override
+    protected byte[] encodeBody() {
+        return EMPTY_BYTES;
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        return 0;
+    }
+
+    @Override
+    protected void decodeBody(Asn1ParseResult parseResult) throws IOException {
+        if (parseResult.getBodyLength() != 0) {
+            throw new IOException("Unexpected bytes found for EOC");
+        }
+    }
+
+    @Override
+    public String toString() {
+        String typeStr = tag().typeStr() + " ["
+            + "tag=" + tag()
+            + ", len=" + getHeaderLength() + "+" + getBodyLength()
+            + "] ";
+        return typeStr + "eoc";
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Flags.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Flags.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Flags.java
new file mode 100644
index 0000000..f11d6df
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Flags.java
@@ -0,0 +1,132 @@
+/**
+ *  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.EnumType;
+
+import java.io.IOException;
+
+/**
+ KrbFlags   ::= BIT STRING (SIZE (32..MAX))
+ -- minimum number of bits shall be sent,
+ -- but no fewer than 32
+ */
+public class Asn1Flags extends Asn1BitString {
+    private static final int MAX_SIZE = 32;
+    private static final int MASK;
+
+    static {
+        int maskBuilder = 0;
+        for (int i = 0; i < MAX_SIZE; i++) {
+          maskBuilder = maskBuilder << 1;
+          maskBuilder |= 0x00000001;
+        }
+        MASK = maskBuilder;
+    }
+
+    private int flags;
+
+    public Asn1Flags() {
+        this(0);
+    }
+
+    public Asn1Flags(int value) {
+        super();
+        setFlags(value);
+    }
+
+    public void setFlags(int flags) {
+        this.flags = flags;
+        flags2Value();
+    }
+
+    @Override
+    public void setValue(byte[] value) {
+        super.setValue(value);
+        value2Flags();
+    }
+
+    public int getFlags() {
+        return flags;
+    }
+
+    public boolean isFlagSet(int flag) {
+        return (flags & flag) != 0;
+    }
+
+    public void setFlag(int flag)  {
+        setFlags(flags | flag);
+    }
+
+    public void clearFlag(int flag) {
+        setFlags(flags & (MASK ^ flag));
+    }
+
+    public void clear() {
+        setFlags(0);
+    }
+
+    public boolean isFlagSet(EnumType flag) {
+        return isFlagSet(flag.getValue());
+    }
+
+    public void setFlag(EnumType flag) {
+        setFlag(flag.getValue());
+    }
+
+    public void setFlag(EnumType flag, boolean isSet)  {
+        if (isSet) {
+            setFlag(flag.getValue());
+        } else {
+            clearFlag(flag.getValue());
+        }
+    }
+
+    public void clearFlag(EnumType flag) {
+        clearFlag(flag.getValue());
+    }
+
+    private void flags2Value() {
+        byte[] bytes = new byte[4];
+        bytes[0] = (byte) (flags >> 24);
+        bytes[1] = (byte) ((flags >> 16) & 0xFF);
+        bytes[2] = (byte) ((flags >> 8) & 0xFF);
+        bytes[3] = (byte) (flags & 0xFF);
+
+        setValue(bytes);
+    }
+
+    private void value2Flags() {
+        byte[] valueBytes = getValue();
+        flags = ((valueBytes[0] & 0xFF) << 24) | ((valueBytes[1] & 0xFF) << 16)
+            | ((valueBytes[2] & 0xFF) << 8) | (0xFF & valueBytes[3]);
+    }
+
+    @Override
+    protected void toValue() throws IOException {
+        super.toValue();
+
+        if (getPadding() != 0 || getValue().length != 4) {
+            throw new IOException("Bad bitstring decoded as invalid krb flags");
+        }
+
+        value2Flags();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java
new file mode 100644
index 0000000..aae244d
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java
@@ -0,0 +1,32 @@
+/**
+ *  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;
+
+public class Asn1GeneralString extends Asn1String {
+    public Asn1GeneralString() {
+        super(UniversalTag.GENERAL_STRING);
+    }
+
+    public Asn1GeneralString(String value) {
+        super(UniversalTag.GENERAL_STRING, value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
new file mode 100644
index 0000000..48d0cef
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
@@ -0,0 +1,136 @@
+/**
+ *  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.charset.StandardCharsets;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+public class Asn1GeneralizedTime extends Asn1Simple<Date> {
+    public Asn1GeneralizedTime() {
+        this(null);
+    }
+
+    /**
+     * time in milliseconds
+     * @param time The long time
+     */
+    public Asn1GeneralizedTime(long time) {
+        super(UniversalTag.GENERALIZED_TIME, new Date(time));
+    }
+
+    public Asn1GeneralizedTime(Date date) {
+        super(UniversalTag.GENERALIZED_TIME, date);
+    }
+
+    protected void toValue() throws IOException {
+        String dateStr = new String(getBytes(), StandardCharsets.US_ASCII);
+        SimpleDateFormat sdf;
+        String fixedDateStr = dateStr;
+
+        boolean withZ = dateStr.endsWith("Z");
+        String timeZonePart = getTimeZonePart(dateStr);
+        boolean withZone = timeZonePart != null;
+        String millSecs = getMillSeconds(dateStr);
+
+        fixedDateStr = dateStr.substring(0, 14) + millSecs;
+        if (withZ) {
+            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+            sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
+        } else if (withZone) {
+            fixedDateStr += timeZonePart;
+            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSSz");
+            sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
+        } else {
+            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+            sdf.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
+        }
+
+        try {
+            setValue(sdf.parse(fixedDateStr));
+        } catch (ParseException e) {
+            throw new IOException("Failed to parse as generalized time string " + dateStr);
+        }
+    }
+
+    @Override
+    protected void toBytes() {
+        Date date = getValue();
+        SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+        dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+        String str = dateF.format(date);
+        byte[] bytes = str.getBytes(StandardCharsets.US_ASCII);
+        setBytes(bytes);
+    }
+
+    /**
+     * Extract the fractional part in seconds and convert into integer by (frac * 1000) as milli seconds
+     */
+    private String getMillSeconds(String dateStr) {
+        char[] millDigits = new char[] {'0', '0', '0'};
+
+        int iPos = dateStr.indexOf('.');
+        if (iPos > 0) {
+            if (iPos != 14) {
+                throw new IllegalArgumentException("Bad generalized time string, "
+                        + "with improper milli seconds " + dateStr);
+            }
+
+            char chr;
+            int j = 0;
+            for (int i = 15; i < dateStr.length() && j < millDigits.length; i++) {
+                chr = dateStr.charAt(i);
+                if ('0' <= chr && chr <= '9') {
+                    millDigits[j++] = chr;
+                } else {
+                    break;
+                }
+            }
+        }
+
+        return new String(millDigits);
+    }
+
+    /**
+     * Extract the timezone part if any
+     */
+    private String getTimeZonePart(String dateStr) {
+        int iPos = dateStr.indexOf('+');
+        if (iPos == -1) {
+            iPos = dateStr.indexOf('-');
+        }
+        if (iPos > 0 && iPos != dateStr.length() - 5) {
+            throw new IllegalArgumentException("Bad generalized time string, "
+                    + "with improper timezone part " + dateStr);
+        }
+
+        if (iPos > 0) {
+            return dateStr.substring(iPos);
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java
new file mode 100644
index 0000000..b7a60d1
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java
@@ -0,0 +1,32 @@
+/**
+ *  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;
+
+public class Asn1IA5String extends Asn1String {
+    public Asn1IA5String() {
+        super(UniversalTag.IA5_STRING);
+    }
+
+    public Asn1IA5String(String value) {
+        super(UniversalTag.IA5_STRING, value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java
new file mode 100644
index 0000000..f5b0509
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java
@@ -0,0 +1,51 @@
+/**
+ *  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.math.BigInteger;
+
+public class Asn1Integer extends Asn1Simple<BigInteger> {
+    public Asn1Integer() {
+        this((BigInteger) null);
+    }
+
+    public Asn1Integer(Integer value) {
+        this(BigInteger.valueOf(value));
+    }
+
+    public Asn1Integer(Long value) {
+        this(BigInteger.valueOf(value));
+    }
+
+    public Asn1Integer(BigInteger value) {
+        super(UniversalTag.INTEGER, value);
+    }
+
+    protected void toBytes() {
+        setBytes(getValue().toByteArray());
+    }
+
+    protected void toValue() throws IOException {
+        setValue(new BigInteger(getBytes()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java
new file mode 100644
index 0000000..b43bb4f
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java
@@ -0,0 +1,63 @@
+/**
+ *  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 org.apache.kerby.asn1.parse.Asn1ParseResult;
+
+import java.io.IOException;
+
+/**
+ * The Asn1 Null type
+ */
+public final class Asn1Null extends Asn1Simple<Object> {
+    public static final Asn1Null INSTANCE = new Asn1Null();
+    private static final byte[]  EMPTY_BYTES = new byte[0];
+
+    private Asn1Null() {
+        super(UniversalTag.NULL, null);
+    }
+
+    @Override
+    protected byte[] encodeBody() {
+        return EMPTY_BYTES;
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        return 0;
+    }
+
+    @Override
+    protected void decodeBody(Asn1ParseResult parseResult) throws IOException {
+        if (parseResult.getHeader().getLength() != 0) {
+            throw new IOException("Unexpected bytes found for NULL");
+        }
+    }
+
+    @Override
+    public String toString() {
+        String typeStr = tag().typeStr() + " ["
+            + "tag=" + tag()
+            + ", len=" + getHeaderLength() + "+" + getBodyLength()
+            + "] ";
+        return typeStr + "null";
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java
new file mode 100644
index 0000000..3ef4ae1
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java
@@ -0,0 +1,45 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1NumericsString extends Asn1String {
+    public Asn1NumericsString() {
+        this(null);
+    }
+
+    public Asn1NumericsString(String value) {
+        super(UniversalTag.NUMERIC_STRING, value);
+        if (value != null && !isNumeric(value)) {
+             throw new IllegalArgumentException("Invalid numeric string");
+        }
+    }
+
+    public static boolean isNumeric(String  s) {
+        for (int i = s.length() - 1; i >= 0; i--) {
+            char c = s.charAt(i);
+            if (!(c >= '0' && c <= '9' || c == ' ')) {
+                return false;
+            }
+        }
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Object.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Object.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Object.java
new file mode 100644
index 0000000..4948828
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Object.java
@@ -0,0 +1,128 @@
+/**
+ *  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.Tag;
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+
+/**
+ * An ASN1 object has a tag.
+ */
+public abstract class Asn1Object {
+
+    private final Tag tag;
+
+    /**
+     * Constructor with a tag
+     * @param tag The tag
+     */
+    public Asn1Object(Tag tag) {
+        this.tag = new Tag(tag);
+    }
+
+    /**
+     * Default constructor with an universal tag.
+     * @param tag the tag
+     */
+    public Asn1Object(UniversalTag tag) {
+        this.tag = new Tag(tag);
+    }
+
+    /**
+     * Constructor with a tag
+     * @param tag The tag
+     */
+    public Asn1Object(int tag) {
+        this.tag = new Tag(tag);
+    }
+
+    public Tag tag() {
+        return tag;
+    }
+
+    public int tagFlags() {
+        return tag().tagFlags();
+    }
+
+    public int tagNo() {
+        return tag().tagNo();
+    }
+
+    public void usePrimitive(boolean isPrimitive) {
+        tag().usePrimitive(isPrimitive);
+    }
+
+    public boolean isPrimitive() {
+        return tag().isPrimitive();
+    }
+
+    public boolean isUniversal() {
+        return tag().isUniversal();
+    }
+
+    public boolean isAppSpecific() {
+        return tag().isAppSpecific();
+    }
+
+    public boolean isContextSpecific() {
+        return tag().isContextSpecific();
+    }
+
+    public boolean isTagSpecific() {
+        return tag().isSpecific();
+    }
+
+    public boolean isEOC() {
+        return tag().isEOC();
+    }
+
+    public boolean isNull() {
+        return tag().isNull();
+    }
+
+    public boolean isSimple() {
+        return Asn1Simple.isSimple(tag());
+    }
+
+    public boolean isCollection() {
+        return Asn1Collection.isCollection(tag());
+    }
+
+    protected abstract int getHeaderLength() throws IOException;
+
+    protected abstract int getBodyLength() throws IOException;
+
+    protected String simpleInfo() {
+        String simpleInfo = tag().typeStr();
+
+        try {
+            simpleInfo += " ["
+                + "tag=" + tag()
+                + ", len=" + getHeaderLength() + "+" + getBodyLength()
+                + "] ";
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        return simpleInfo;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java
new file mode 100644
index 0000000..9c4a9f7
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java
@@ -0,0 +1,168 @@
+/**
+ *  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.math.BigInteger;
+import java.nio.ByteBuffer;
+
+/**
+ * ASN1 object identifier.
+ */
+public class Asn1ObjectIdentifier extends Asn1Simple<String> {
+    public Asn1ObjectIdentifier() {
+        this(null);
+    }
+
+    public Asn1ObjectIdentifier(String value) {
+        super(UniversalTag.OBJECT_IDENTIFIER, value);
+    }
+
+    @Override
+    protected void toBytes() {
+        byte[][] bytesArr = convert(getValue());
+        int allLen = 0;
+        for (byte[] bytes : bytesArr) {
+            allLen += bytes.length;
+        }
+        ByteBuffer buffer = ByteBuffer.allocate(allLen);
+        for (byte[] bytes : bytesArr) {
+            buffer.put(bytes);
+        }
+        setBytes(buffer.array());
+    }
+
+    protected void toValue() {
+        StringBuilder sb = new StringBuilder();
+
+        byte[] bytes = getBytes();
+        byte[][] bytesGroups = group(bytes);
+        BigInteger[] coms = convert(bytesGroups);
+
+        long first = coms[0].longValue();
+        sb.append(first / 40).append('.');
+        sb.append(first % 40);
+        if (coms.length > 1) {
+            sb.append('.');
+        }
+
+        for (int i = 1; i < coms.length; ++i) {
+            sb.append(coms[i].toString());
+            if (i != coms.length - 1) {
+                sb.append('.');
+            }
+        }
+
+        String value = sb.toString();
+        setValue(value);
+    }
+
+    private BigInteger[] convert(byte[][] bytesGroups) {
+        BigInteger[] comps = new BigInteger[bytesGroups.length];
+
+        for (int i = 0; i < bytesGroups.length; ++i) {
+            comps[i] = convert(bytesGroups[i]);
+        }
+
+        return comps;
+    }
+
+    private BigInteger convert(byte[] bytes) {
+        BigInteger value = BigInteger.valueOf(bytes[0] & 0x7f);
+        for (int i = 1; i < bytes.length; ++i) {
+            value = value.shiftLeft(7);
+            value = value.or(BigInteger.valueOf(bytes[i] & 0x7f));
+        }
+
+        return value;
+    }
+
+    /**
+     * divide and group bytes together belonging to each component
+     */
+    private byte[][] group(byte[] bytes) {
+        int count = 0, i, j;
+        int[] countArr = new int[bytes.length]; // how many bytes for each group
+        for (i = 0; i < countArr.length; ++i) {
+            countArr[i] = 0;
+        }
+
+        for (j = 0, i = 0; i < bytes.length; ++i) {
+            if ((bytes[i] & 0x80) != 0) {
+                countArr[j]++;
+            } else {
+                countArr[j++]++;
+            }
+        }
+        count = j;
+
+        byte[][] bytesGroups = new byte[count][];
+        for (i = 0; i < count; ++i) {
+            bytesGroups[i] = new byte[countArr[i]];
+        }
+
+        int k = 0;
+        for (j = 0, i = 0; i < bytes.length; ++i) {
+            bytesGroups[j][k++] = bytes[i];
+            if ((bytes[i] & 0x80) == 0) {
+                j++;
+                k = 0;
+            }
+        }
+
+        return bytesGroups;
+    }
+
+    private byte[][] convert(String oid) {
+        String[] parts = oid.split("\\.");
+        BigInteger[] coms = new BigInteger[parts.length - 1];
+        for (int i = 1; i < parts.length; ++i) {
+            coms[i - 1] = new BigInteger(parts[i]);
+        }
+        coms[0] = coms[0].add(BigInteger.valueOf(Integer.parseInt(parts[0]) * 40));
+
+        byte[][] bytesGroups = new byte[coms.length][];
+        for (int i = 0; i < coms.length; ++i) {
+            bytesGroups[i] = convert(coms[i]);
+        }
+
+        return bytesGroups;
+    }
+
+    private byte[] convert(BigInteger value) {
+        int bitLen = value.bitLength();
+
+        if (bitLen < 8) {
+            return new byte[] {value.byteValue()};
+        }
+
+        int len = (bitLen + 6) / 7;
+        byte[] bytes = new byte[len];
+        BigInteger tmpValue = value;
+        for (int i = len - 1; i >= 0; i--) {
+            bytes[i] = (byte) ((tmpValue.byteValue() & 0x7f) | 0x80);
+            tmpValue = tmpValue.shiftRight(7);
+        }
+        bytes[len - 1] &= 0x7f;
+
+        return bytes;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
new file mode 100644
index 0000000..e9de89a
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
@@ -0,0 +1,71 @@
+/**
+ *  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 org.apache.kerby.asn1.parse.Asn1Item;
+import org.apache.kerby.asn1.parse.Asn1ParseResult;
+
+import java.io.IOException;
+
+public class Asn1OctetString extends Asn1Simple<byte[]> {
+    public Asn1OctetString() {
+        this(null);
+    }
+
+    public Asn1OctetString(byte[] value) {
+        super(UniversalTag.OCTET_STRING, value);
+    }
+
+    @Override
+    protected byte[] encodeBody() {
+        return getValue();
+    }
+
+    @Override
+    protected int encodingBodyLength() {
+        if (getValue() != null) {
+            return getValue().length;
+        }
+        return 0;
+    }
+
+    @Override
+    protected void decodeBody(Asn1ParseResult parseResult) throws IOException {
+        Asn1Item item = (Asn1Item) parseResult;
+        setValue(item.readBodyBytes());
+    }
+
+    @Override
+    public String toString() {
+        String typeStr = tag().typeStr() + " ["
+            + "tag=" + tag()
+            + ", len=" + getHeaderLength() + "+" + getBodyLength()
+            + "] ";
+
+        byte[] valueBytes = getValue();
+        String valueStr = "<null>";
+        if (valueBytes != null) {
+            valueStr = "<" + valueBytes.length + " octets>";
+        }
+
+        return typeStr + valueStr;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java
new file mode 100644
index 0000000..0401757
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java
@@ -0,0 +1,32 @@
+/**
+ *  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;
+
+public class Asn1PrintableString extends Asn1String {
+    public Asn1PrintableString() {
+        this(null);
+    }
+
+    public Asn1PrintableString(String value) {
+        super(UniversalTag.PRINTABLE_STRING, value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java
new file mode 100644
index 0000000..c5a7dfc
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java
@@ -0,0 +1,28 @@
+/**
+ *  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;
+
+public class Asn1Sequence extends Asn1Collection {
+    public Asn1Sequence() {
+        super(UniversalTag.SEQUENCE);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.java
new file mode 100644
index 0000000..074a8b7
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.java
@@ -0,0 +1,36 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.kerby.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1SequenceOf<T extends Asn1Type> extends Asn1CollectionOf<T> {
+    public Asn1SequenceOf() {
+        super(UniversalTag.SEQUENCE_OF);
+    }
+
+    public boolean isEmpty() {
+        return getValue() == null || getElements().size() == 0;
+    }
+
+    public void add(T element) {
+        addElement(element);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java
new file mode 100644
index 0000000..85d2763
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java
@@ -0,0 +1,38 @@
+/**
+ *  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.Asn1FieldInfo;
+import org.apache.kerby.asn1.UniversalTag;
+
+/**
+ * For sequence type that consists of tagged fields
+ */
+public class Asn1SequenceType extends Asn1CollectionType {
+
+    public Asn1SequenceType(Asn1FieldInfo[] tags) {
+        super(UniversalTag.SEQUENCE, tags);
+    }
+
+    @Override
+    protected Asn1Collection createCollection() {
+        return new Asn1Sequence();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/9e4dbd6e/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java
----------------------------------------------------------------------
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java
new file mode 100644
index 0000000..c2cded4
--- /dev/null
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java
@@ -0,0 +1,28 @@
+/**
+ *  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;
+
+public class Asn1Set extends Asn1Collection {
+    public Asn1Set() {
+        super(UniversalTag.SET);
+    }
+}


Mime
View raw message