anchor.diff:      _tag = _encodedBytes[0];
       ASN1Length l = ASN1Length.decodeLength(_encodedBytes);
       valueByteLength = l.length;
  -    valueStartPosition = l.valueStartPosition;  
  -    _totalEncodedByteLength = valueStartPosition + valueByteLength;
  +    valueStartPosition = l.valueStartPosition;
     }
   
     /** The BER tag representing this object */
  
positive.code: /**
   * Holds the encoded  and decoded representation of an ASN1 object
   * Object are allocated in two ways:
   * 
   *  A value can be supplied representing the ASN1 Type for the object (Integer, String, etc.). The object can then be encoded
   *  to its BER byte stream representation. 
   *  
   *  Conversely, the object can be initialized from an incoming BER byte array. This byte stream can then be decoded to its correspoding 
   *  ASN1 type.
   *  
   *  
   */
  class ASN1Object {
  
    /** 
     *  The ASN1 encoded bytes. 
     *  If we are decoding a byte stream sent by another process (LDAP, for example), the
     *  decoder will parse the incoming bytes and set this array.
     *  Note that the encoded bytes could be part of another object (for example, sequence objects contain
     *  other sub objects). Care should be taken to not modify the bytes 
     *  The length of the encoded byte array could also be larger than the encoded bytes for this object
     *
     */
    Uint8List _encodedBytes;
    Uint8List get encodedBytes => _encodedBytes;
    /**
     * The setter is needed rarely - usually when dealing with CHOICE encoding
     * where the encoded object is supplied
     */
    set encodedBytes(Uint8List b) => _encodedBytes = b;
    
    int _totalEncodedByteLength = 0;
    
    /**
     * The total length of this object in bytes.
     * We need this if we are parsing a stream of bytes to know when the
     * next object starts in the stream.
     */
    get totalEncodedByteLength => _totalEncodedByteLength;
    
    ASN1Object() {
    }
    
    /**
     * Create an object that encapsulates a set of value bytes
     * This is used in LDAP (for example) to encode a CHOICE type
     * The supplied valBytes is the encoded value of the choice element
     * 
     * todo: rename this
     * 
     */
    ASN1Object.fromTag(this._tag,Uint8List valBytes) {
      valueByteLength = valBytes.length;
      encode();
      // copy in the valBytes into the encoded byte array
      _encodedBytes.setRange(valueStartPosition, valBytes.length, valBytes);
      
    }
    
    
    ASN1Object.fromBytes(this._encodedBytes) {
      _initFromBytes();
    }
    
    /**
     * Perform initial decoding common to all ASN1 Objects
     * Determines the length and where the value bytes start
  
negative.code: 
    int get tag => _tag;
    set tag(int v) => _tag = v;
  
    /**
     * Length of the encoded value in bytes. This does not include
     * the tag or the size of length field.
     */
    int valueByteLength;
    /**
     * The index where the value bytes start. This is the position after the tag + length bytes.
     * defaults to 2 - but encoding may change this value.
     */
    int valueStartPosition = 2;
  
    /**
     * This will encode the tag and the length bytes - which is all we can do right now
     * Subclasses may call super on this method - but they MUST set valueByteLength before
     * calling this. We use that to know how big to make the encoded object array. Subclasses are
     * responsible for encoding their value representations.
     */
    Uint8List encode() {
      if( _encodedBytes == null ) {
        Uint8List lenEnc= ASN1Length.encodeLength(valueByteLength);
        _encodedBytes = new Uint8List( 1 + lenEnc.length + valueByteLength);
        _encodedBytes[0] = tag;
        _encodedBytes.setRange(1,lenEnc.length , lenEnc, 0);
        valueStartPosition = 1 + lenEnc.length;
      }
      return _encodedBytes;
    }
  
    /**
     * Return just the value bytes.
     * This returns a view into the total bytes
  