You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by dr...@apache.org on 2015/01/22 01:56:54 UTC
[30/50] [abbrv] directory-kerberos git commit: Many changes with
newname
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1FieldInfo.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1FieldInfo.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1FieldInfo.java
new file mode 100644
index 0000000..0647159
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1FieldInfo.java
@@ -0,0 +1,76 @@
+/**
+ * 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.TaggingOption;
+
+public class Asn1FieldInfo {
+ private int index;
+ private int tagNo;
+ private boolean isImplicit;
+ private Class<? extends Asn1Type> type;
+
+ public Asn1FieldInfo(int index, int tagNo, Class<? extends Asn1Type> type) {
+ this(index, tagNo, type, false);
+ }
+
+ public Asn1FieldInfo(int index, Class<? extends Asn1Type> type) {
+ this(index, index, type, false);
+ }
+
+ public Asn1FieldInfo(int index, Class<? extends Asn1Type> type, boolean isImplicit) {
+ this(index, index, type, isImplicit);
+ }
+
+ public Asn1FieldInfo(int index, int tagNo, Class<? extends Asn1Type> type, boolean isImplicit) {
+ this.index = index;
+ this.tagNo = tagNo;
+ this.type = type;
+ this.isImplicit = isImplicit;
+ }
+
+ public boolean isTagged() {
+ return tagNo != -1;
+ }
+
+ public TaggingOption getTaggingOption() {
+ if (isImplicit) {
+ return TaggingOption.newImplicitContextSpecific(tagNo);
+ } else {
+ return TaggingOption.newExplicitContextSpecific(tagNo);
+ }
+ }
+
+ public int getTagNo() {
+ return tagNo;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public boolean isImplicit() {
+ return isImplicit;
+ }
+
+ public Class<? extends Asn1Type> getType() {
+ return type;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java
new file mode 100644
index 0000000..19c6d40
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralString.java
@@ -0,0 +1,33 @@
+/**
+ * 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-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
new file mode 100644
index 0000000..9341f1a
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
@@ -0,0 +1,134 @@
+/**
+ * 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
+ */
+ public Asn1GeneralizedTime(long time) {
+ super(UniversalTag.GENERALIZED_TIME, new Date(time));
+ }
+
+ public Asn1GeneralizedTime(Date date) {
+ super(UniversalTag.UTC_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-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java
new file mode 100644
index 0000000..6f73c9f
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1IA5String.java
@@ -0,0 +1,33 @@
+/**
+ * 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-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java
new file mode 100644
index 0000000..b0893a0
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Integer.java
@@ -0,0 +1,46 @@
+/**
+ * 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<Integer>
+{
+ public Asn1Integer() {
+ this(null);
+ }
+
+ public Asn1Integer(Integer value) {
+ super(UniversalTag.INTEGER, value);
+ }
+
+ @Override
+ protected void toBytes() {
+ setBytes(BigInteger.valueOf(getValue()).toByteArray());
+ }
+
+ @Override
+ protected void toValue() throws IOException {
+ setValue(new BigInteger(getBytes()).intValue());
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Item.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Item.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Item.java
new file mode 100644
index 0000000..a18d135
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Item.java
@@ -0,0 +1,155 @@
+/**
+ * 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.Asn1Factory;
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.TaggingOption;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * Asn1Item serves two purposes:
+ * 1. Wrapping an existing Asn1Type value for Asn1Collection;
+ * 2. Wrapping a half decoded value whose body content is left to be decoded later when appropriate.
+ * Why not fully decoded at once? Lazy and decode on demand for collection, or impossible due to lacking
+ * key parameters, like implicit encoded value for tagged value.
+ *
+ * For not fully decoded value, you tell your case using isSimple/isCollection/isTagged/isContextSpecific etc.,
+ * then call decodeValueAsSimple/decodeValueAsCollection/decodeValueAsImplicitTagged/decodeValueAsExplicitTagged etc.
+ * to decode it fully. Or if you have already derived the value holder or the holder type, you can use decodeValueWith
+ * or decodeValueAs with your holder or hodler type.
+ */
+public class Asn1Item extends AbstractAsn1Type<Asn1Type>
+{
+ private LimitedByteBuffer bodyContent;
+
+ public Asn1Item(Asn1Type value) {
+ super(value.tagFlags(), value.tagNo(), value);
+ }
+
+ public Asn1Item(int tag, int tagNo, LimitedByteBuffer bodyContent) {
+ super(tag, tagNo);
+ this.bodyContent = bodyContent;
+ }
+
+ public LimitedByteBuffer getBodyContent() {
+ return bodyContent;
+ }
+
+ @Override
+ protected int encodingBodyLength() {
+ if (getValue() != null) {
+ return ((AbstractAsn1Type) getValue()).encodingBodyLength();
+ }
+ return (int) bodyContent.hasLeft();
+ }
+
+ @Override
+ protected void encodeBody(ByteBuffer buffer) {
+ if (getValue() != null) {
+ ((AbstractAsn1Type) getValue()).encodeBody(buffer);
+ } else {
+ try {
+ buffer.put(bodyContent.readAllLeftBytes());
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to read all left bytes from body content", e);
+ }
+ }
+ }
+
+ @Override
+ protected void decodeBody(LimitedByteBuffer bodyContent) throws IOException {
+ this.bodyContent = bodyContent;
+ }
+
+ public boolean isFullyDecoded() {
+ return getValue() != null;
+ }
+
+ public void decodeValueAsSimple() throws IOException {
+ if (getValue() != null) return;
+ if (! isSimple()) {
+ throw new IllegalArgumentException("Attempting to decode non-simple value as simple");
+ }
+
+ Asn1Type value = Asn1Factory.create(tagNo());
+ decodeValueWith(value);
+ }
+
+ public void decodeValueAsCollection() throws IOException {
+ if (getValue() != null) return;
+ if (! isCollection()) {
+ throw new IllegalArgumentException("Attempting to decode non-collection value as collection");
+ }
+
+ Asn1Type value = Asn1Factory.create(tagNo());
+ decodeValueWith(value);
+ }
+
+ public void decodeValueAs(Class<? extends Asn1Type> type) throws IOException {
+ Asn1Type value;
+ try {
+ value = type.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException("Invalid type: " + type.getCanonicalName(), e);
+ }
+ decodeValueWith(value);
+ }
+
+ public void decodeValueWith(Asn1Type value) throws IOException {
+ setValue(value);
+ ((AbstractAsn1Type) value).decode(tagFlags(), tagNo(), bodyContent);
+ }
+
+ public void decodeValueAsImplicitTagged(int originalTag, int originalTagNo) throws IOException {
+ if (! isTagged()) {
+ throw new IllegalArgumentException("Attempting to decode non-tagged value using tagging way");
+ }
+ Asn1Item taggedValue = new Asn1Item(originalTag, originalTagNo, getBodyContent());
+ decodeValueWith(taggedValue);
+ }
+
+ public void decodeValueAsExplicitTagged() throws IOException {
+ if (! isTagged()) {
+ throw new IllegalArgumentException("Attempting to decode non-tagged value using tagging way");
+ }
+ Asn1Item taggedValue = decodeOne(getBodyContent());
+ decodeValueWith(taggedValue);
+ }
+
+ private void decodeValueWith(Asn1Item taggedValue) throws IOException {
+ taggedValue.decodeValueAsSimple();
+ if (taggedValue.isFullyDecoded()) {
+ setValue(taggedValue.getValue());
+ } else {
+ setValue(taggedValue);
+ }
+ }
+
+ public void decodeValueWith(Asn1Type value, TaggingOption taggingOption) throws IOException {
+ if (! isTagged()) {
+ throw new IllegalArgumentException("Attempting to decode non-tagged value using tagging way");
+ }
+ ((AbstractAsn1Type) value).taggedDecode(tagFlags(), tagNo(), getBodyContent(), taggingOption);
+ setValue(value);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java
new file mode 100644
index 0000000..8cabc04
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Null.java
@@ -0,0 +1,52 @@
+/**
+ * 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.LimitedByteBuffer;
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+
+public class Asn1Null extends Asn1Simple<Object>
+{
+ public static final Asn1Null NULL = new Asn1Null();
+ private static final byte[] EMPTY_BYTES = new byte[0];
+
+ public Asn1Null() {
+ super(null, UniversalTag.NULL);
+ }
+
+ @Override
+ protected byte[] encodeBody() {
+ return EMPTY_BYTES;
+ }
+
+ @Override
+ protected int encodingBodyLength() {
+ return 0;
+ }
+
+ @Override
+ protected void decodeBody(LimitedByteBuffer content) throws IOException {
+ if (content.hasLeft() != 0) {
+ throw new IOException("Unexpected bytes found for NULL");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java
new file mode 100644
index 0000000..ea534ac
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1NumericsString.java
@@ -0,0 +1,50 @@
+/**
+ * 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) {
+ if (!isNumeric(value)) {
+ throw new IllegalArgumentException("Invalid numeric string");
+ }
+ }
+ }
+
+ public static boolean isNumeric(String s) {
+ char c;
+ for (int i = s.length() - 1; i >= 0; i--) {
+ c = s.charAt(i);
+ if ((c >= '0' && c <= '9') || c == ' ') {
+ continue;
+ }
+ return false;
+ }
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java
new file mode 100644
index 0000000..e6a49ec
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1ObjectIdentifier.java
@@ -0,0 +1,164 @@
+/**
+ * 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;
+
+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-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.java
new file mode 100644
index 0000000..72510a3
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1OctetString.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.LimitedByteBuffer;
+import org.apache.kerby.asn1.UniversalTag;
+
+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() {
+ return getValue().length;
+ }
+
+ @Override
+ protected void decodeBody(LimitedByteBuffer content) throws IOException {
+ setValue(content.readAllLeftBytes());
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java
new file mode 100644
index 0000000..78fdb10
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1PrintableString.java
@@ -0,0 +1,33 @@
+/**
+ * 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-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java
new file mode 100644
index 0000000..b9e374c
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Sequence.java
@@ -0,0 +1,30 @@
+/**
+ * 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.TagClass;
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1Sequence extends Asn1Collection
+{
+ public Asn1Sequence() {
+ super(TagClass.UNIVERSAL, UniversalTag.SEQUENCE.getValue());
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.java
new file mode 100644
index 0000000..dcf6356
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceOf.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.TagClass;
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1SequenceOf<T extends Asn1Type> extends Asn1CollectionOf<T>
+{
+ public Asn1SequenceOf() {
+ super(TagClass.UNIVERSAL, UniversalTag.SEQUENCE_OF.getValue());
+ }
+
+ public boolean isEmpty() {
+ return (getValue() == null || getElements().size() == 0);
+ }
+
+ public void add(T element) {
+ getElements().add(element);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java
new file mode 100644
index 0000000..bcbf715
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SequenceType.java
@@ -0,0 +1,37 @@
+/**
+ * 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;
+
+/**
+ * For sequence type that consists of tagged fields
+ */
+public class Asn1SequenceType extends Asn1CollectionType {
+
+ public Asn1SequenceType(Asn1FieldInfo[] tags) {
+ super(UniversalTag.SEQUENCE.getValue(), tags);
+ }
+
+ @Override
+ protected Asn1Collection createCollection() {
+ return new Asn1Sequence();
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java
new file mode 100644
index 0000000..3407e8c
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Set.java
@@ -0,0 +1,30 @@
+/**
+ * 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.TagClass;
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1Set extends Asn1Collection
+{
+ public Asn1Set() {
+ super(TagClass.UNIVERSAL, UniversalTag.SET.getValue());
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetOf.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetOf.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetOf.java
new file mode 100644
index 0000000..f91e241
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetOf.java
@@ -0,0 +1,30 @@
+/**
+ * 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.TagClass;
+import org.apache.kerby.asn1.UniversalTag;
+
+public class Asn1SetOf<T extends Asn1Type> extends Asn1CollectionOf<T>
+{
+ public Asn1SetOf() {
+ super(TagClass.UNIVERSAL, UniversalTag.SET_OF.getValue());
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetType.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetType.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetType.java
new file mode 100644
index 0000000..4f13369
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1SetType.java
@@ -0,0 +1,37 @@
+/**
+ * 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;
+
+/**
+ * For set type that consists of tagged fields
+ */
+public class Asn1SetType extends Asn1CollectionType {
+
+ public Asn1SetType(Asn1FieldInfo[] tags) {
+ super(UniversalTag.SET.getValue(), tags);
+ }
+
+ @Override
+ protected Asn1Collection createCollection() {
+ return new Asn1Set();
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
new file mode 100644
index 0000000..c25309d
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Simple.java
@@ -0,0 +1,184 @@
+/**
+ * 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.EncodingOption;
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.TagClass;
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public abstract class Asn1Simple<T> extends AbstractAsn1Type<T> {
+ private byte[] bytes;
+
+ public Asn1Simple(UniversalTag tagNo) {
+ this(tagNo, null);
+ }
+
+ public Asn1Simple(UniversalTag tagNo, T value) {
+ super(TagClass.UNIVERSAL, tagNo.getValue(), value);
+ setEncodingOption(EncodingOption.PRIMITIVE);
+ }
+
+ protected byte[] getBytes() {
+ return bytes;
+ }
+
+ protected void setBytes(byte[] bytes) {
+ this.bytes = bytes;
+ }
+
+ @Override
+ public void encode(ByteBuffer buffer) {
+ encodeTag(buffer, tagFlags(), tagNo());
+ int bodyLen = encodingBodyLength();
+ encodeLength(buffer, bodyLen);
+ if (bodyLen > 0) {
+ buffer.put(encodeBody());
+ }
+ }
+
+ protected byte[] encodeBody() {
+ if (bytes == null) {
+ toBytes();
+ }
+ return bytes;
+ }
+
+ @Override
+ protected void encodeBody(ByteBuffer buffer) {
+ buffer.put(encodeBody());
+ }
+
+ @Override
+ protected int encodingBodyLength() {
+ if (getValue() == null) {
+ return 0;
+ }
+ if (bytes == null) {
+ toBytes();
+ }
+ return bytes.length;
+ }
+
+ @Override
+ protected void decodeBody(LimitedByteBuffer content) throws IOException {
+ byte[] leftBytes = content.readAllLeftBytes();
+ if (leftBytes.length > 0) {
+ setBytes(leftBytes);
+ toValue();
+ }
+ }
+
+ @Override
+ public boolean isConstructed() {
+ return false;
+ }
+
+ protected void toValue() throws IOException {}
+
+ protected void toBytes() {}
+
+ public static boolean isSimple(int tagNo) {
+ return isSimple(UniversalTag.fromValue(tagNo));
+ }
+
+ public static boolean isSimple(UniversalTag tagNo) {
+ switch (tagNo) {
+ case BIT_STRING:
+ case BMP_STRING:
+ case BOOLEAN:
+ case ENUMERATED:
+ case GENERALIZED_TIME:
+ case GENERAL_STRING:
+ case IA5_STRING:
+ case INTEGER:
+ case NULL:
+ case NUMERIC_STRING:
+ case OBJECT_IDENTIFIER:
+ case OCTET_STRING:
+ case PRINTABLE_STRING:
+ case T61_STRING:
+ case UNIVERSAL_STRING:
+ case UTC_TIME:
+ case UTF8_STRING:
+ case VISIBLE_STRING:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static Asn1Type createSimple(int tagNo) {
+ if (! isSimple(tagNo)) {
+ throw new IllegalArgumentException("Not simple type, tag: " + tagNo);
+ }
+ return createSimple(UniversalTag.fromValue(tagNo));
+ }
+
+ public static Asn1Type createSimple(UniversalTag tagNo) {
+ if (! isSimple(tagNo)) {
+ throw new IllegalArgumentException("Not simple type, tag: " + tagNo);
+ }
+
+ switch (tagNo) {
+ case BIT_STRING:
+ return new Asn1BitString();
+ case BMP_STRING:
+ return new Asn1BmpString();
+ case BOOLEAN:
+ return new Asn1Boolean();
+ case ENUMERATED:
+ return null;
+ case GENERALIZED_TIME:
+ return new Asn1GeneralizedTime();
+ case GENERAL_STRING:
+ return new Asn1GeneralString();
+ case IA5_STRING:
+ return new Asn1IA5String();
+ case INTEGER:
+ return new Asn1Integer();
+ case NULL:
+ return new Asn1Null();
+ case NUMERIC_STRING:
+ return new Asn1NumericsString();
+ case OBJECT_IDENTIFIER:
+ return new Asn1ObjectIdentifier();
+ case OCTET_STRING:
+ return new Asn1OctetString();
+ case PRINTABLE_STRING:
+ return new Asn1PrintableString();
+ case T61_STRING:
+ return new Asn1T61String();
+ case UNIVERSAL_STRING:
+ return new Asn1UniversalString();
+ case UTC_TIME:
+ return new Asn1UtcTime();
+ case UTF8_STRING:
+ return new Asn1Utf8String();
+ case VISIBLE_STRING:
+ return new Asn1VisibleString();
+ default:
+ throw new IllegalArgumentException("Unexpected tag " + tagNo.getValue());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1String.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1String.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1String.java
new file mode 100644
index 0000000..3f75d07
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1String.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.UniversalTag;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class Asn1String extends Asn1Simple<String>
+{
+ public Asn1String(UniversalTag tagNo) {
+ super(tagNo, null);
+ }
+
+ public Asn1String(UniversalTag tagNo, String value) {
+ super(tagNo, value);
+ }
+
+ @Override
+ protected void toBytes() {
+ byte[] bytes = getValue().getBytes(StandardCharsets.US_ASCII);
+ setBytes(bytes);
+ }
+
+ @Override
+ protected int encodingBodyLength() {
+ if (getValue() != null) {
+ return getValue().length();
+ }
+ return 0;
+ }
+
+ protected void toValue() throws IOException {
+ byte[] bytes = getBytes();
+ setValue(new String(bytes, StandardCharsets.US_ASCII));
+ }
+
+ public static String fromUTF8ByteArray(byte[] bytes) {
+ int i = 0;
+ int length = 0;
+
+ while (i < bytes.length) {
+ length++;
+ if ((bytes[i] & 0xf0) == 0xf0) {
+ // surrogate pair
+ length++;
+ i += 4;
+ } else if ((bytes[i] & 0xe0) == 0xe0) {
+ i += 3;
+ } else if ((bytes[i] & 0xc0) == 0xc0) {
+ i += 2;
+ } else {
+ i += 1;
+ }
+ }
+
+ char[] cs = new char[length];
+ i = 0;
+ length = 0;
+
+ while (i < bytes.length) {
+ char ch;
+
+ if ((bytes[i] & 0xf0) == 0xf0) {
+ int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F);
+ int U = codePoint - 0x10000;
+ char W1 = (char)(0xD800 | (U >> 10));
+ char W2 = (char)(0xDC00 | (U & 0x3FF));
+ cs[length++] = W1;
+ ch = W2;
+ i += 4;
+ } else if ((bytes[i] & 0xe0) == 0xe0) {
+ ch = (char)(((bytes[i] & 0x0f) << 12)
+ | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f));
+ i += 3;
+ } else if ((bytes[i] & 0xd0) == 0xd0) {
+ ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
+ i += 2;
+ } else if ((bytes[i] & 0xc0) == 0xc0) {
+ ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
+ i += 2;
+ } else {
+ ch = (char)(bytes[i] & 0xff);
+ i += 1;
+ }
+
+ cs[length++] = ch;
+ }
+
+ return new String(cs);
+ }
+
+ public static byte[] toUTF8ByteArray(String string) {
+ return toUTF8ByteArray(string.toCharArray());
+ }
+
+ public static byte[] toUTF8ByteArray(char[] string) {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try {
+ toUTF8ByteArray(string, bOut);
+ } catch (IOException e) {
+ throw new IllegalStateException("cannot encode string to byte array!");
+ }
+
+ return bOut.toByteArray();
+ }
+
+ public static void toUTF8ByteArray(char[] string, OutputStream sOut) throws IOException {
+ char[] c = string;
+ int i = 0;
+
+ while (i < c.length) {
+ char ch = c[i];
+
+ if (ch < 0x0080) {
+ sOut.write(ch);
+ } else if (ch < 0x0800) {
+ sOut.write(0xc0 | (ch >> 6));
+ sOut.write(0x80 | (ch & 0x3f));
+ }
+ // surrogate pair
+ else if (ch >= 0xD800 && ch <= 0xDFFF) {
+ // in error - can only happen, if the Java String class has a
+ // bug.
+ if (i + 1 >= c.length) {
+ throw new IllegalStateException("invalid UTF-16 codepoint");
+ }
+ char W1 = ch;
+ ch = c[++i];
+ char W2 = ch;
+ // in error - can only happen, if the Java String class has a
+ // bug.
+ if (W1 > 0xDBFF) {
+ throw new IllegalStateException("invalid UTF-16 codepoint");
+ }
+ int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000;
+ sOut.write(0xf0 | (codePoint >> 18));
+ sOut.write(0x80 | ((codePoint >> 12) & 0x3F));
+ sOut.write(0x80 | ((codePoint >> 6) & 0x3F));
+ sOut.write(0x80 | (codePoint & 0x3F));
+ } else {
+ sOut.write(0xe0 | (ch >> 12));
+ sOut.write(0x80 | ((ch >> 6) & 0x3F));
+ sOut.write(0x80 | (ch & 0x3F));
+ }
+
+ i++;
+ }
+ }
+
+ /**
+ * A locale independent version of toUpperCase.
+ *
+ * @param string input to be converted
+ * @return a US Ascii uppercase version
+ */
+ public static String toUpperCase(String string) {
+ boolean changed = false;
+ char[] chars = string.toCharArray();
+
+ for (int i = 0; i != chars.length; i++) {
+ char ch = chars[i];
+ if ('a' <= ch && 'z' >= ch) {
+ changed = true;
+ chars[i] = (char)(ch - 'a' + 'A');
+ }
+ }
+
+ if (changed) {
+ return new String(chars);
+ }
+
+ return string;
+ }
+
+ /**
+ * A locale independent version of toLowerCase.
+ *
+ * @param string input to be converted
+ * @return a US ASCII lowercase version
+ */
+ public static String toLowerCase(String string) {
+ boolean changed = false;
+ char[] chars = string.toCharArray();
+
+ for (int i = 0; i != chars.length; i++) {
+ char ch = chars[i];
+ if ('A' <= ch && 'Z' >= ch) {
+ changed = true;
+ chars[i] = (char)(ch - 'A' + 'a');
+ }
+ }
+
+ if (changed) {
+ return new String(chars);
+ }
+
+ return string;
+ }
+
+ public static byte[] toByteArray(char[] chars) {
+ byte[] bytes = new byte[chars.length];
+
+ for (int i = 0; i != bytes.length; i++) {
+ bytes[i] = (byte)chars[i];
+ }
+
+ return bytes;
+ }
+
+ public static byte[] toByteArray(String string) {
+ byte[] bytes = new byte[string.length()];
+
+ for (int i = 0; i != bytes.length; i++) {
+ char ch = string.charAt(i);
+
+ bytes[i] = (byte)ch;
+ }
+
+ return bytes;
+ }
+
+ /**
+ * Convert an array of 8 bit characters into a string.
+ *
+ * @param bytes 8 bit characters.
+ * @return resulting String.
+ */
+ public static String fromByteArray(byte[] bytes) {
+ return new String(asCharArray(bytes));
+ }
+
+ /**
+ * Do a simple conversion of an array of 8 bit characters into a string.
+ *
+ * @param bytes 8 bit characters.
+ * @return resulting String.
+ */
+ public static char[] asCharArray(byte[] bytes) {
+ char[] chars = new char[bytes.length];
+
+ for (int i = 0; i != chars.length; i++) {
+ chars[i] = (char)(bytes[i] & 0xff);
+ }
+
+ return chars;
+ }
+
+ public static String[] split(String input, char delimiter) {
+ List<String> v = new ArrayList<String>();
+ boolean moreTokens = true;
+ String subString;
+
+ while (moreTokens) {
+ int tokenLocation = input.indexOf(delimiter);
+ if (tokenLocation > 0) {
+ subString = input.substring(0, tokenLocation);
+ v.add(subString);
+ input = input.substring(tokenLocation + 1);
+ } else {
+ moreTokens = false;
+ v.add(input);
+ }
+ }
+
+ return v.toArray(new String[v.size()]);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1T61String.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1T61String.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1T61String.java
new file mode 100644
index 0000000..2b8e92b
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1T61String.java
@@ -0,0 +1,33 @@
+/**
+ * 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 Asn1T61String extends Asn1String
+{
+ public Asn1T61String() {
+ this(null);
+ }
+
+ public Asn1T61String(String value) {
+ super(UniversalTag.T61_STRING, value);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1T61Utf8String.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1T61Utf8String.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1T61Utf8String.java
new file mode 100644
index 0000000..5e0d9da
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1T61Utf8String.java
@@ -0,0 +1,43 @@
+/**
+ * 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.nio.charset.StandardCharsets;
+
+public class Asn1T61Utf8String extends Asn1String
+{
+ public Asn1T61Utf8String() {
+ this(null);
+ }
+
+ public Asn1T61Utf8String(String value) {
+ super(UniversalTag.T61_STRING, value);
+ }
+
+ protected void toBytes() {
+ setBytes(getValue().getBytes(StandardCharsets.UTF_8));
+ }
+
+ protected void toValue() {
+ setValue(new String(getBytes(), StandardCharsets.UTF_8));
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Tagging.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..2b2b97f
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Tagging.java
@@ -0,0 +1,104 @@
+/**
+ * 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.EncodingOption;
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.TagClass;
+
+import java.io.IOException;
+import java.lang.reflect.ParameterizedType;
+import java.nio.ByteBuffer;
+
+/**
+ * For tagging any Asn1Type with a tagNo
+ */
+public class Asn1Tagging<T extends Asn1Type> extends AbstractAsn1Type<T> {
+
+ public Asn1Tagging(boolean isAppSpecific) {
+ this(-1, null, isAppSpecific);
+ }
+
+ public Asn1Tagging(int tagNo, T value, boolean isAppSpecific) {
+ super(isAppSpecific ? TagClass.APPLICATION : TagClass.CONTEXT_SPECIFIC, tagNo, value);
+ setEncodingOption(EncodingOption.EXPLICIT);
+ if (value == null) {
+ initValue();
+ }
+ }
+
+ @Override
+ protected int encodingBodyLength() {
+ AbstractAsn1Type value = (AbstractAsn1Type) getValue();
+ if (encodingOption.isExplicit()) {
+ return value.encodingLength();
+ } else if (encodingOption.isImplicit()) {
+ return value.encodingBodyLength();
+ } else {
+ throw new RuntimeException("Invalid util option, only allowing explicit/implicit");
+ }
+ }
+
+ @Override
+ public boolean isConstructed() {
+ if (encodingOption.isExplicit()) {
+ return true;
+ } else if (encodingOption.isImplicit()) {
+ AbstractAsn1Type value = (AbstractAsn1Type) getValue();
+ return value.isConstructed();
+ }
+ return false;
+ }
+
+ @Override
+ protected void encodeBody(ByteBuffer buffer) {
+ AbstractAsn1Type value = (AbstractAsn1Type) getValue();
+ if (encodingOption.isExplicit()) {
+ value.encode(buffer);
+ } else if (encodingOption.isImplicit()) {
+ value.encodeBody(buffer);
+ } else {
+ throw new RuntimeException("Invalid util option, only allowing explicit/implicit");
+ }
+ }
+
+ @Override
+ protected void decodeBody(LimitedByteBuffer content) throws IOException {
+ AbstractAsn1Type value = (AbstractAsn1Type) getValue();
+ if (encodingOption.isExplicit()) {
+ value.decode(content);
+ } else if (encodingOption.isImplicit()) {
+ value.decodeBody(content);
+ } else {
+ throw new RuntimeException("Invalid util option, only allowing explicit/implicit");
+ }
+ }
+
+ private void initValue() {
+ Class<? extends Asn1Type> valueType = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
+ AbstractAsn1Type value = null;
+ try {
+ value = (AbstractAsn1Type) valueType.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to create tagged value", e);
+ }
+ setValue((T) value);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Type.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..48f0d26
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Type.java
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.kerby.asn1.type;
+
+import org.apache.kerby.asn1.EncodingOption;
+import org.apache.kerby.asn1.TaggingOption;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public interface Asn1Type {
+ public int tagFlags();
+ public int tagNo();
+ public void setEncodingOption(EncodingOption encodingOption);
+ public int encodingLength();
+ public byte[] encode();
+ public void encode(ByteBuffer buffer);
+ public void decode(byte[] content) throws IOException;
+ public void decode(ByteBuffer content) throws IOException;
+ public byte[] taggedEncode(TaggingOption taggingOption);
+ public void taggedEncode(ByteBuffer buffer, TaggingOption taggingOption);
+ public void taggedDecode(ByteBuffer content, TaggingOption taggingOption) throws IOException;
+ public void taggedDecode(byte[] content, TaggingOption taggingOption) throws IOException;
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UniversalString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UniversalString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UniversalString.java
new file mode 100644
index 0000000..104c707
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UniversalString.java
@@ -0,0 +1,33 @@
+/**
+ * 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 Asn1UniversalString extends Asn1String
+{
+ public Asn1UniversalString() {
+ this(null);
+ }
+
+ public Asn1UniversalString(String value) {
+ super(UniversalTag.UNIVERSAL_STRING, value);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UtcTime.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UtcTime.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UtcTime.java
new file mode 100644
index 0000000..c39dcdc
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UtcTime.java
@@ -0,0 +1,89 @@
+/**
+ * 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;
+
+public class Asn1UtcTime extends Asn1Simple<Date>
+{
+ public Asn1UtcTime() {
+ this(null);
+ }
+
+ public Asn1UtcTime(long time) {
+ super(UniversalTag.UTC_TIME, new Date(time * 1000L));
+ }
+
+ public Asn1UtcTime(Date date) {
+ super(UniversalTag.UTC_TIME, date);
+ }
+
+ protected void toValue() throws IOException {
+ String dateStr = new String(getBytes(), StandardCharsets.US_ASCII);
+ String fixedDateStr = dateStr;
+
+ /*
+ * Make sure fixed date str be of the complete pattern 'YYMMDDhhmmss+/-hhmm'
+ */
+ int strLen = fixedDateStr.length();
+ if (strLen == 6) { // YYMMDD
+ fixedDateStr += "000000+0000";
+ } else if (strLen == 7) { // YYMMDDZ
+ fixedDateStr = fixedDateStr.replace("Z", "000000+0000");
+ } else if (strLen == 10) { // YYMMDDhhmm
+ fixedDateStr += "00+0000";
+ } else if (strLen == 11) { // YYMMDDhhmmZ
+ fixedDateStr = fixedDateStr.replace("Z", "00+0000");
+ } else if (strLen == 12) { // YYMMDDhhmmss
+ fixedDateStr += "+0000";
+ } else if (strLen == 13) { // YYMMDDhhmmZ
+ fixedDateStr = fixedDateStr.replace("Z", "+0000");
+ } else if (strLen != 17) {
+ throw new IllegalArgumentException("Bad utc time string " + dateStr);
+ }
+
+ SimpleDateFormat sdf;
+ sdf = new SimpleDateFormat("yyMMddHHmmssZ");
+ sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
+ try {
+ setValue(sdf.parse(fixedDateStr));
+ } catch (ParseException e) {
+ throw new IOException("Failed to parse " + dateStr + " as utc time", e);
+ }
+ }
+
+ @Override
+ protected void toBytes() {
+ Date date = getValue();
+ SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss'Z'");
+ sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+ String str = sdf.format(date);
+ byte[] bytes = str.getBytes(StandardCharsets.US_ASCII);
+ setBytes(bytes);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Utf8String.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Utf8String.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Utf8String.java
new file mode 100644
index 0000000..bfa2c57
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1Utf8String.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.kerby.asn1.type;
+
+import org.apache.kerby.asn1.UniversalTag;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+public class Asn1Utf8String extends Asn1String
+{
+ public Asn1Utf8String() {
+ this(null);
+ }
+
+ public Asn1Utf8String(String value) {
+ super(UniversalTag.UTF8_STRING, value);
+ }
+
+ @Override
+ protected void toBytes() {
+ byte[] bytes = getValue().getBytes(StandardCharsets.UTF_8);
+ setBytes(bytes);
+ }
+
+ protected void toValue() throws IOException {
+ byte[] bytes = getBytes();
+ setValue(new String(bytes, StandardCharsets.UTF_8));
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1VisibleString.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1VisibleString.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1VisibleString.java
new file mode 100644
index 0000000..c4e0f16
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1VisibleString.java
@@ -0,0 +1,33 @@
+/**
+ * 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 Asn1VisibleString extends Asn1String
+{
+ public Asn1VisibleString() {
+ this(null);
+ }
+
+ public Asn1VisibleString(String value) {
+ super(UniversalTag.VISIBLE_STRING, value);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingCollection.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingCollection.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingCollection.java
new file mode 100644
index 0000000..48a815c
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingCollection.java
@@ -0,0 +1,105 @@
+/**
+ * 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.EncodingOption;
+import org.apache.kerby.asn1.LimitedByteBuffer;
+import org.apache.kerby.asn1.TagClass;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * For tagging a collection type with tagNo, either application specific or context specific class
+ */
+public abstract class TaggingCollection extends AbstractAsn1Type<Asn1CollectionType> {
+ private Asn1Tagging<Asn1CollectionType> tagging;
+ private Asn1CollectionType tagged;
+
+ public TaggingCollection(int taggingTagNo, Asn1FieldInfo[] tags, boolean isAppSpecific) {
+ super(isAppSpecific ? TagClass.APPLICATION : TagClass.CONTEXT_SPECIFIC, taggingTagNo);
+ this.tagged = createTaggedCollection(tags);
+ setValue(tagged);
+ this.tagging = new Asn1Tagging<Asn1CollectionType>(taggingTagNo, tagged, isAppSpecific);
+ setEncodingOption(EncodingOption.EXPLICIT);
+ }
+
+ protected abstract Asn1CollectionType createTaggedCollection(Asn1FieldInfo[] tags);
+
+ public void setEncodingOption(EncodingOption encodingOption) {
+ tagging.setEncodingOption(encodingOption);
+ }
+
+ @Override
+ public boolean isConstructed() {
+ return tagging.isConstructed();
+ }
+
+ @Override
+ protected int encodingBodyLength() {
+ return tagging.encodingBodyLength();
+ }
+
+ @Override
+ protected void encodeBody(ByteBuffer buffer) {
+ tagging.encodeBody(buffer);
+ }
+
+ @Override
+ protected void decodeBody(LimitedByteBuffer content) throws IOException {
+ tagging.decodeBody(content);
+ }
+
+ protected <T extends Asn1Type> T getFieldAs(int index, Class<T> t) {
+ return tagged.getFieldAs(index, t);
+ }
+
+ protected void setFieldAs(int index, Asn1Type value) {
+ tagged.setFieldAs(index, value);
+ }
+
+ protected String getFieldAsString(int index) {
+ return tagged.getFieldAsString(index);
+ }
+
+ protected byte[] getFieldAsOctets(int index) {
+ return tagged.getFieldAsOctets(index);
+ }
+
+ protected void setFieldAsOctets(int index, byte[] bytes) {
+ tagged.setFieldAsOctets(index, bytes);
+ }
+
+ protected Integer getFieldAsInteger(int index) {
+ return tagged.getFieldAsInteger(index);
+ }
+
+ protected void setFieldAsInt(int index, int value) {
+ tagged.setFieldAsInt(index, value);
+ }
+
+ protected byte[] getFieldAsOctetBytes(int index) {
+ return tagged.getFieldAsOctets(index);
+ }
+
+ protected void setFieldAsOctetBytes(int index, byte[] value) {
+ tagged.setFieldAsOctets(index, value);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSequence.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSequence.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSequence.java
new file mode 100644
index 0000000..90ecaed
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSequence.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.kerby.asn1.type;
+
+/**
+ * For tagging a sequence type with tagNo, either application specific or context specific class
+ */
+public class TaggingSequence extends TaggingCollection {
+
+ public TaggingSequence(int taggingTagNo, Asn1FieldInfo[] tags, boolean isAppSpecific) {
+ super(taggingTagNo, tags, isAppSpecific);
+ }
+
+ @Override
+ protected Asn1CollectionType createTaggedCollection(Asn1FieldInfo[] tags) {
+ return new Asn1SequenceType(tags);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSet.java
----------------------------------------------------------------------
diff --git a/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSet.java b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSet.java
new file mode 100644
index 0000000..c4807d0
--- /dev/null
+++ b/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/TaggingSet.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.kerby.asn1.type;
+
+/**
+ * For tagging a sequence type with tagNo, either application specific or context specific class
+ */
+public class TaggingSet extends TaggingCollection {
+
+ public TaggingSet(int taggingTagNo, Asn1FieldInfo[] tags, boolean isAppSpecific) {
+ super(taggingTagNo, tags, isAppSpecific);
+ }
+
+ @Override
+ protected Asn1CollectionType createTaggedCollection(Asn1FieldInfo[] tags) {
+ return new Asn1SetType(tags);
+ }
+}