iaik.asn1
Class CON_SPEC

java.lang.Object
  |
  +--iaik.asn1.ASN1Object
        |
        +--iaik.asn1.ConstructedType
              |
              +--iaik.asn1.CON_SPEC
All Implemented Interfaces:
Cloneable

public class CON_SPEC
extends ConstructedType

This class implements the tagged ASN.1 type "CONTEXT SPECIFIC". ASN.1 types are unequivocally identified by their tags. Every ASN.1 type - except for ANY and CHOICE types - is allocated a particular tag specifying the tag class to which this type belongs and the tag number which separates the current ASN.1 type from the other types belonging to the same tag class.

ASN.1 defines four tag classes:

For BER (respectively DER) encoding a type which is derived from some underlying type, either EXPLICIT or IMPLICIT tagging may be used. The tag of the underlying type explicitely has to be encoded when EXPLICIT tagging is used. IMPLICIT tagging avoids the extra encoding of the tag of the underlying type and may be used when the actual tag can be derived from the context.
Explicit tagging always enforces constructed encoding, and the contents consists of the full encoding of the underlying base type. When implicit tagging is required, the kind of encoding (primitive or constructed) depends on the base type: if the base type is a simple type, the context specific is primitive encoded, but if the base type is constructed also the context specific has to be encoded constructed.
Since explicit tagging is the default value and requires constructed encoding, this CON_SPEC class inherits from the ConstructedType class. Implicit tagging may be enforced by setting the implicitlyTagged parameter to true when creating a new CON_SPEC object by means of the CON_SPEC(int conSpecTag, ASN1Object obj, boolean implicitlyTagged) constructor. The following example creates an ASN.1 SEQUENCE object consisting of two INTEGER components, and one OCTET_STRING component, which is tagged context specifiic implicit with tag number 0:
 INTEGER i1 = new INTEGER(1);
 OCTET_STRING oct = new OCTET_STRING(new byte[] {(byte)0xAB, (byte)0xCD});
 INTEGER i2 = new INTEGER(2);
 SEQUENCE seq = new SEQUENCE();
 seq.addComponent(i1);
 seq.addComponent(new CON_SPEC(0, oct, true));
 seq.addComponent(i2);
 
The example above will give the following DER encoding:
 30:0A:02:01:01:80:02:AB:CD:02:01:02
 
For comparison, if the cotext specific OCTET_STRING component of the SEQUENCE above is tagged explicitly, it will be encoded constructed and OCTET_STRING tag (0x04) and length are included in the encoding:
 30:0C:02:01:01:A0:04:04:02:AB:CD:02:01:02
 
Attention has to be paid when implicitly tagging a structured component, e.g. a SEQUENCE component. Since the SEQUENCE tag (0x30) is not included into the encoding, particular care has to be taken when decoding and parsing such a structure. Consider, for instance, two ASN.1 SEQUENCE structures, both containing a context specific tagged component with the same tag number 0. The context specific component of the first SEQUENCE shall be explicitly tagged and shall represent a simple OCTET_STRING component. The context specific component of the second SEQUENCE object shall be implicitly tagged and shall represent a SEQUENCE component containing one OCTET_STRING component with the same value as the OCTET_STRING component of the first SEQUENCE object:

First SEQUENCE:

 SEQUENCE[C] = 3 elements
  INTEGER = 1
  CONTEXTSPECIFIC[C] = [0] EXPLICIT
   OCTET STRING = 2 bytes: AB:CD
  INTEGER = 2
 
Second SEQUENCE:
 SEQUENCE[C] = 3 elements
  INTEGER = 1
  CONTEXTSPECIFIC[C] = [0] IMPLICIT
   SEQUENCE[C] = 1 elements
    OCTET STRING = 2 bytes: AB:CD
  INTEGER = 2
 
The encoding will be the same, since the context specific component of the first SEQUENCE object is explicitly tagged and therefore constructed encoded giving a tag of 0xA0 (10100000: tag class: context specific (10), encoding type: constrcuted (1), tag number: 0 (00000). The context specific component of the second SEQUENCE object is implicitly tagged and therefore the encoding type (primitive or constructed) is derived from the base type, which is a SEQUENCE and therefore gives the same context specific tag as in the first example: 0xA0. Since implicit tagging does not encode the tag of the base type (SEQUENCE 0x30), the encoding result is the same for both SEQUENCE objects:
 30:0C:02:01:01:A0:04:04:02:AB:CD:02:01:02
 
However the application that parses the received SEQUENCE object knows that implictly tagging has been used and therefore can recognize the right encoding by using the forceImplicitlyTagged method:
 SEQUENCE obtained_sequence = (SEQUENCE)DerCoder.decode(encoding);
 CON_SPEC cs = (CON_SPEC)obtained_sequnce.getComponentAt(1);
 cs.forceImplicitlyTagged(ASN.SEQUENCE);
 SEQUENCE seq_component = (SEQUENCE)cs.getValue();
 OCTET_STRING oct = (OCTET_STRING)seq_component.getComponentAt(0);
 

Version:
File Revision 25
See Also:
ASN1Object, ASN, DerCoder

Fields inherited from class iaik.asn1.ConstructedType
content_count, content_data
 
Fields inherited from class iaik.asn1.ASN1Object
asnType, constructed, encode_listener, indefinite_length, isStringType, stream_mode
 
Constructor Summary
protected CON_SPEC()
          Creates an empty CON_SPEC object.
  CON_SPEC(int conSpecTag, ASN1Object obj)
          Creates a new explicitly tagged context specific ASN.1 type.
  CON_SPEC(int conSpecTag, ASN1Object obj, boolean implicitlyTagged)
          Creates a new context specific ASN.1 type.
 
Method Summary
 Object clone()
          Returns a clone of this CON_SPEC.
protected  void decode(int length, InputStream is)
          Decodes the next available data from the InputStream.
protected  void encode(OutputStream os)
          DER encodes this CON_SPEC ASN1Object and writes the result to the given output stream.
 void forceImplicitlyTagged(ASN type)
          Forces a CONTEX SPECIFIC ASN.1 object to be implicitly tagged.
 Object getValue()
          Returns the value of this CON_SPEC as an ASN1Object.
 boolean isImplicitlyTagged()
          Returns true if this Context Specific ASN1Object is implicitly tagged.
 String toString()
          Returns a string that represents the contents of this CON_SPEC ASN1Object.
 
Methods inherited from class iaik.asn1.ConstructedType
addComponent, addComponent, addEncodeListener, countComponents, getComponentAt, getComponents, removeComponent, removeComponent, setComponent, setValue
 
Methods inherited from class iaik.asn1.ASN1Object
addEncodeListener, encodeObject, getAsnType, indefiniteLength, isA, isConstructed, isStringType, setIndefiniteLength
 
Methods inherited from class java.lang.Object
equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

CON_SPEC

protected CON_SPEC()
Creates an empty CON_SPEC object.

CON_SPEC

public CON_SPEC(int conSpecTag,
                ASN1Object obj)
Creates a new explicitly tagged context specific ASN.1 type. Use the #CON_SPEC(int, ASN1Object, boolean) constructor for enforcing implicit tagging.
Parameters:
conSpecTag - the context specific tag number
obj - the underlying ASN1Object

CON_SPEC

public CON_SPEC(int conSpecTag,
                ASN1Object obj,
                boolean implicitlyTagged)
Creates a new context specific ASN.1 type. The calling application decides if implicit or explicit tagging is to be used.
Parameters:
conSpecTag - the context specific tag number
obj - the underlying ASN1Object
implicitlyTagged - true if creating an implicitly tagged object, false if creating an explicitly tagged object
Method Detail

clone

public Object clone()
Returns a clone of this CON_SPEC.
Overrides:
clone in class ConstructedType
Returns:
a clone of this CON_SPEC

getValue

public Object getValue()
Returns the value of this CON_SPEC as an ASN1Object.
Overrides:
getValue in class ConstructedType
Returns:
the value of this CON_SPEC as an ASN1Object

isImplicitlyTagged

public boolean isImplicitlyTagged()
Returns true if this Context Specific ASN1Object is implicitly tagged.
Returns:
true if implicitly tagged, false if explicitly tagged

forceImplicitlyTagged

public void forceImplicitlyTagged(ASN type)
                           throws CodingException
Forces a CONTEX SPECIFIC ASN.1 object to be implicitly tagged.

There is no way for the DER decoder to detect if an context specific ASN.1 object is

Example:

 problem [0] EXPLICIT InnerObject;
 InnerObject ::= INTEGER;
 

problem [0] IMPLICIT InnerObject; InnerObject ::= SEQUENCE { test INTEGER; }

Both examples lead to the same ASN.1 DER encoding:
 A0 03 02 01 01   if test = 1
 
Only the application which parses the ASN1Object knows if an implicitly or an explicitly tagged context specific was defined.

The solution for this problem looks like:

 ASN1Object problem = ...;

 problem.forceImplicitlyTagged(ASN.SEQUENCE);
 
Constructed context specific ASN.1 objects are always decoded as explicitly tagged per default.
Parameters:
type - the type of the lost implicitly tagged type
Throws:
CodingException - if no instance of the type can be created

encode

protected void encode(OutputStream os)
               throws IOException
DER encodes this CON_SPEC ASN1Object and writes the result to the given output stream. This is a protected method and will not be used by an application for DER encoding an CON_SPEC object. An application will call one of the encode methods of the DerCoder class for performing the encoding. The encode method of this CON_SPEC class will be called internally from the DerCoder.
Overrides:
encode in class ConstructedType
Parameters:
os - the output stream to which to write the data
Throws:
IOException - if an error occurs while writing to the stream

decode

protected void decode(int length,
                      InputStream is)
               throws IOException,
                      CodingException
Decodes the next available data from the InputStream. The supplied input stream carries DER encoded data. The next length bytes represent the encoding of this CON_SPEC object to be decoded. If length < 0, the supplied CON_SPEC has been encoded by means of the indefinite length encoding method, and so the encoding has to be parsed for two consecutive EOC octets of all zeros. Indefinite length encoding only is appropriate (and therefore allowed) for constructed ASN.1 types.

This is a protected method and will not be used by an application for DER decoding an encoded CON_SPEC. An application will call one of the decode methods of the DerCoder class for performing the decoding. The DerCoder then determines the number of bytes (length) obtained by the particular CON_SPEC and internally calls the decode method of that CON_SPEC instance.

Overrides:
decode in class ConstructedType
Parameters:
length - the length, i.e. number of the bytes representing the ASN1Object to be decoded
is - the input stream from which the DER encoded data is read in
Throws:
IOException - if there is a problem with the InputStream
CodingException - if the bytes from is cannot be decoded

toString

public String toString()
Returns a string that represents the contents of this CON_SPEC ASN1Object.
Overrides:
toString in class ASN1Object
Returns:
the string representation
See Also:
ASN1Object.toString()

This Javadoc may contain text parts from Internet Standard specifications (RFC 2459, 3280, 3039, 2560, 1521, 821, 822, 2253, 1319, 1321, ,2630, 2631, 2268, 3058, 2984, 2104, 2144, 2040, 2311, 2279, see copyright note) and RSA Data Security Public-Key Cryptography Standards (PKCS#1,3,5,7,8,9,10,12, see copyright note).

IAIK-JCE 3.1 with IAIK-JCE CC Core 3.1, (c) 1997-2004 IAIK