[jcifs] ASN.1

Michael B Allen mba2000 at ioplex.com
Fri Apr 22 07:24:46 GMT 2005


I'm sort of just emailing this to myself for later but if anyone out
there's an ASN.1 expert let me share my pain... I need some limited ASN.1
/ DER code for SPNEGO. Decoding this stuff is pretty easy but I've been
thinking all night about how to *encode* it.

The problem is (assuming a little knowledge of DER encoding here) that you
can't encode an object until you know the size of it's payload and you
don't know the size of the payload until you encode it. Well obviously
that's not entirely true or it quite simply wouldn't be possible to do
this at all.  Rather what you must do is first traverse the entire tree
of objects from the leaves up just to add up the sizes. Then you can
recur again to encode everything.

What an inelegant pain in the ass. It's ironic that the standard is
so miserly about saving every little byte in encoding lengths because
doing so incurs this inefficent encoding requirement. And what's even
more inefficient are all the Java implementations out there that create
an Object for every tag. Arg. OOP is just a tool, and it's not the right
tool for decoding/encoding ASN.1!

Anyway, here's my pseudocode for how I think I'm going to handle this. I
think I have it figure'd out but any input or anecdotes about ASN.1,
SPNEGO, extended security, etc is welcome.

Mike

Record ::= SEQUENCE {
   name [0] Name OPTIONAL,
   oid  [1] OBJECT IDENTIFER
}

The above shoddy ASN.1 might be encoded/decoded in DER w/ something like:

class Record extends ASN1Object {

    private int size = -1;

	/* The idea here is that Name and OID are also ASN1Objects
	 * that have similar encode and decode methods. So we
	 * demonstrate recursion with one node.
     */
    Name name;
    OID oid;

    int size() {
        if (size > 0) return size;
        int n = 0;
        if (name != null) {
            int m = name.size();
            n += 1 + lenlen( m ) + m;
				/* lenlen computes the number of bytes required
				 * to encode the length of the object
				 */
        }       
        if (oid != null)
            n += oid.size();
        return 1 + lenlen(n) + n;
    }

    void encode( ASN1Buffer dst ) { 
        dst.enc_intn( 0x60, 1 );
        dst.enc_length( size() );
        if (name != null) { 
            int n = name.size();
            dst.enc_intn( 0xA0, 1 );
            dst.enc_length( n );
            name.encode( dst );
        }
        if (oid != null) { 
            int n = oid.size();
            dst.enc_intn( 0xA1, 1 );
            dst.enc_length( n );
            oid.encode( dst );
        }
    }
    void decode( ASN1Buffer src ) {  /* decoding is easy */
        src.dec_intn( 1 );
        src.dec_length();
        for ( ;; ) {
            int tag = src.dec_intn( 1 ) & 0xF;
            src.dec_length();
            switch (tag) { 
                case 0: 
                    name = new Name(); 
                    name.decode( src );
                    break;  
                case 1: 
                    ...
            }       
        }       
    }
}

call() {
    Record r = new Record();
    r.name = new Name(); 
    r.name....set name members 
    r.oid = SPNEGO.MECHANISM_KERBEROS;
    r.encode( dst );

    OR to decode

    Record r = new Record();
    r.decode( src );
}

-- 
IRC - where men are men, women are men, and the boys are FBI agents.


More information about the jcifs mailing list