blob: eb35929d15bc88e91063df9ed0de78ae8fc255eb [file] [log] [blame] [view]
# 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.
haox-asn1
=========
### A ASN1 parser with easy and simple API
```
// encoding
Asn1Integer aValue = new Asn1Integer(8899);
byte[] encoded = aValue.encode();
// decoding
byte[] contentToDecode = ...
Asn1Integer decodedValue = new Asn1Integer();
decodedValue.decode(contentToDecode);
Integer value = decodedValue.getValue();
```
### Data-driven ASN1 encoding/decoding framework and parser
With the following definition from Kerberos protocol
```
AuthorizationData ::= SEQUENCE OF SEQUENCE {
ad-type [0] Int32,
ad-data [1] OCTET STRING
}
```
You can model AuthzDataEntry as follows
```java
public class AuthzDataEntry extends Asn1SequenceType {
static int AD_TYPE = 0;
static int AD_DATA = 1;
public AuthzDataEntry() {
super(new Asn1FieldInfo[] {
new Asn1FieldInfo(AD_TYPE, Asn1Integer.class),
new Asn1FieldInfo(AD_DATA, Asn1OctetString.class)
});
}
public int getAuthzType() {
Integer value = getFieldAsInteger(AD_TYPE);
return value;
}
public byte[] getAuthzData() {
return getFieldAsOctetBytes(AD_DATA);
}
}
```
And then define AuthorizationData simply
```java
public class AuthorizationData extends Asn1SequenceOf<AuthzDataEntry> {
}
```
Then you can process with above definitions, encode and decode, without caring about the details.
Think about how to implement the following more complex and pratical sample from [ITU-T Rec. X.680 ISO/IEC 8824-1](http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf):
```
A.1 ASN.1 description of the record structure
The structure of the hypothetical personnel record is formally described below using ASN.1 specified in
ITU-T Rec. X.680 | ISO/IEC 8824-1 for defining types.
PersonnelRecord ::= [APPLICATION 0] IMPLICIT SET {
Name Name,
title [0] VisibleString,
number EmployeeNumber,
dateOfHire [1] Date,
nameOfSpouse [2] Name,
children [3] IMPLICIT
SEQUENCE OF ChildInformation DEFAULT {}
}
ChildInformation ::= SET {
name Name,
dateOfBirth [0] Date
}
Name ::= [APPLICATION 1] IMPLICIT SEQUENCE {
givenName VisibleString,
initial VisibleString,
familyName VisibleString
}
EmployeeNumber ::= [APPLICATION 2] IMPLICIT INTEGER
Date ::= [APPLICATION 3] IMPLICIT VisibleString -- YYYYMMDD
```
Similarly as above, we can have (from the unit test codes):
```java
public class PersonnelRecord extends TaggingSet {
private static int NAME = 0;
private static int TITLE = 1;
private static int NUMBER = 2;
private static int DATEOFHIRE= 3;
private static int NAMEOFSPOUSE = 4;
private static int CHILDREN = 5;
static Asn1FieldInfo[] fieldInfos = new Asn1FieldInfo[] {
new Asn1FieldInfo(NAME, -1, Name.class),
new Asn1FieldInfo(TITLE, 0, Asn1VisibleString.class),
new Asn1FieldInfo(NUMBER, -1, EmployeeNumber.class),
new Asn1FieldInfo(DATEOFHIRE, 1, Date.class),
new Asn1FieldInfo(NAMEOFSPOUSE, 2, Name.class),
new Asn1FieldInfo(CHILDREN, 3, Children.class, true)
};
public PersonnelRecord() {
super(0, fieldInfos, true);
setEncodingOption(EncodingOption.IMPLICIT);
}
public void setName(Name name) {
setFieldAs(NAME, name);
}
public Name getName() {
return getFieldAs(NAME, Name.class);
}
public void setTitle(String title) {
setFieldAs(TITLE, new Asn1VisibleString(title));
}
public String getTitle() {
return getFieldAsString(TITLE);
}
public void setEmployeeNumber(EmployeeNumber employeeNumber) {
setFieldAs(NUMBER, employeeNumber);
}
public EmployeeNumber getEmployeeNumber() {
return getFieldAs(NUMBER, EmployeeNumber.class);
}
public void setDateOfHire(Date dateOfHire) {
setFieldAs(DATEOFHIRE, dateOfHire);
}
public Date getDateOfHire() {
return getFieldAs(DATEOFHIRE, Date.class);
}
public void setNameOfSpouse(Name spouse) {
setFieldAs(NAMEOFSPOUSE, spouse);
}
public Name getNameOfSpouse() {
return getFieldAs(NAMEOFSPOUSE, Name.class);
}
public void setChildren(Children children) {
setFieldAs(CHILDREN, children);
}
public Children getChildren() {
return getFieldAs(CHILDREN, Children.class);
}
public static class Children extends Asn1SequenceOf<ChildInformation> {
public Children(ChildInformation ... children) {
super();
for (ChildInformation child : children) {
addElement(child);
}
}
public Children() {
super();
}
}
public static class ChildInformation extends Asn1SetType {
private static int NAME = 0;
private static int DATEOFBIRTH = 1;
static Asn1FieldInfo[] tags = new Asn1FieldInfo[] {
new Asn1FieldInfo(NAME, -1, Name.class),
new Asn1FieldInfo(DATEOFBIRTH, 0, Date.class)
};
public ChildInformation() {
super(tags);
}
public void setName(Name name) {
setFieldAs(NAME, name);
}
public Name getName() {
return getFieldAs(NAME, Name.class);
}
public void setDateOfBirth(Date date) {
setFieldAs(DATEOFBIRTH, date);
}
public Date getDateOfBirth() {
return getFieldAs(DATEOFBIRTH, Date.class);
}
}
public static class Name extends TaggingSequence {
private static int GIVENNAME = 0;
private static int INITIAL = 1;
private static int FAMILYNAME = 2;
static Asn1FieldInfo[] tags = new Asn1FieldInfo[] {
new Asn1FieldInfo(GIVENNAME, -1, Asn1VisibleString.class),
new Asn1FieldInfo(INITIAL, -1, Asn1VisibleString.class),
new Asn1FieldInfo(FAMILYNAME, -1, Asn1VisibleString.class)
};
public Name() {
super(1, tags, true);
setEncodingOption(EncodingOption.IMPLICIT);
}
public Name(String givenName, String initial, String familyName) {
this();
setGivenName(givenName);
setInitial(initial);
setFamilyName(familyName);
}
public void setGivenName(String givenName) {
setFieldAs(GIVENNAME, new Asn1VisibleString(givenName));
}
public String getGivenName() {
return getFieldAsString(GIVENNAME);
}
public void setInitial(String initial) {
setFieldAs(INITIAL, new Asn1VisibleString(initial));
}
public String getInitial() {
return getFieldAsString(INITIAL);
}
public void setFamilyName(String familyName) {
setFieldAs(FAMILYNAME, new Asn1VisibleString(familyName));
}
public String getFamilyName() {
return getFieldAsString(FAMILYNAME);
}
}
public static class EmployeeNumber extends Asn1Tagging<Asn1Integer> {
public EmployeeNumber(Integer value) {
super(2, new Asn1Integer(value), true);
setEncodingOption(EncodingOption.IMPLICIT);
}
public EmployeeNumber() {
this(null);
}
}
public static class Date extends Asn1Tagging<Asn1VisibleString> {
public Date(String value) {
super(3, new Asn1VisibleString(value), true);
setEncodingOption(EncodingOption.IMPLICIT);
}
public Date() {
this(null);
}
}
}
```
### Notes
* 90% tests coverage for DER encoding
* For BER & CER encoding, to be fully supported
* No extra dependency
### License
Apache V2 License