Table of Contents

Class TlvWriter

Namespace
Yubico.Core.Tlv
Assembly
Yubico.Core.dll

Use this class to build TLV (tag-length-value) constructions.

public sealed class TlvWriter
Inheritance
object
TlvWriter

Remarks

See the User's Manual entry on TLV for an in-depth discussion of what TLV is and a general description of how to use this class.

Constructors

TlvWriter()

Create a new TlvWriter object.

public TlvWriter()

Methods

Clear()

Clear any data that had been copied from input.

public void Clear()

Remarks

If any of the data to encode had been sensitive (such as private key material), then call the Clear method after encoding to make sure it is overwritten.

Call this only after the schema has been completely entered (the outermost NestedTlv has been closed). If you call this before the schema has been completely entered, it can throw an exception.

Exceptions

TlvException

The method is called before a schema has been completely entered.

Encode()

Write out the encoding of the structure defined, returning a new byte array containing the result.

public byte[] Encode()

Returns

byte[]

A new byte array containing the encoding.

Remarks

Call this only after the schema has been completely entered (the outermost Nested TLV has been closed). If you call this before the schema has been completely entered, it can throw an exception.

Exceptions

TlvException

The method is called before a schema has been completely entered.

GetEncodedLength()

Get the length the encoding will be.

public int GetEncodedLength()

Returns

int

The total length of the result of a call to Encode.

Remarks

Note that this will only return the length if a full schema has been entered. Otherwise it will thorw an exception.

Call this only after the schema has been completely entered (the outermost Nested TLV has been closed). If you call this before the schema has been completely entered, it can throw an exception.

Exceptions

TlvException

The method is called before a schema has been completely entered.

TryEncode(Span<byte>, out int)

Write out the encoding of the structure defined, placing the result into the destination.

public bool TryEncode(Span<byte> destination, out int bytesWritten)

Parameters

destination Span<byte>

The Span into which the encoding will be placed.

bytesWritten int

On success, receives the number of bytes written into the destination.

Returns

bool

A bool, true if the method successfully encoded, false otherwise.

Remarks

This will try to write out the encoding. If the destination buffer is not big enough, the method will return false (no data was written).

Call this only after the schema has been completely entered (the outermost Nested TLV has been closed). If you call this before the schema has been completely entered, it can throw an exception.

Exceptions

TlvException

The method is called before a schema has been completely entered.

WriteByte(int, byte)

Add a byte as the value to be written out.

public void WriteByte(int tag, byte value)

Parameters

tag int

The tag that will be written out when this TLV is encoded.

value byte

The byte to be converted into a byte array.

Exceptions

TlvException

The tag is invalid.

WriteEncoded(ReadOnlySpan<byte>)

Add an encoded byte array to be written out.

public void WriteEncoded(ReadOnlySpan<byte> encodedTlv)

Parameters

encodedTlv ReadOnlySpan<byte>

The encoded byte array that will be written out when this TLV is encoded.

Exceptions

TlvException

The length is unsupported.

WriteInt16(int, short, bool)

Add a 16-bit integer as the value to be written out.

public void WriteInt16(int tag, short value, bool bigEndian = true)

Parameters

tag int

The tag that will be written out when this TLV is encoded.

value short

The short to be converted into a byte array.

bigEndian bool

If true, write out the short as big endian, with the high order byte of the value in the left most position in the byte array. If false, write out the value as little endian, with the low order byte of the value in the left most position in the byte array. The default is true, so if no argument is given, the value will be written as big endian.

Exceptions

TlvException

The tag is invalid.

WriteInt32(int, int, bool)

Add a 32-bit integer as the value to be written out.

public void WriteInt32(int tag, int value, bool bigEndian = true)

Parameters

tag int

The tag that will be written out when this TLV is encoded.

value int

The int to be converted into a byte array.

bigEndian bool

If true, write out the int as big endian, with the high order byte of the value in the left most position in the byte array. If false, write out the value as little endian, with the low order byte of the value in the left most position in the byte array.

Exceptions

TlvException

The tag is invalid.

WriteNestedTlv(int)

Start a new Nested TLV.

public TlvWriter.TlvScope WriteNestedTlv(int tag)

Parameters

tag int

The tag that will be written out when encoding the TLV.

Returns

TlvWriter.TlvScope

Remarks

The way the caller is supposed to build Nested schemas using TlvWriter is as follows.

var writer = new TlvWriter();
using (writer.WriteNestedTlv(tag0))
{
    writer.WriteValue(tag1, element1);
    writer.WriteValue(tag2, element2);
}
byte[] encoding = tlvWriter.Encode();

The using directive in this case means that when the variable goes out of scope, the Dispose method will be called immediately. Furthermore, when written this way (with the curly braces), the variable goes out of scope upon completion of the close curly brace.

The WriteNestedTlv method returns an instance of TlvWriter.TlvScope. So in the above construction, the variable for which the using is constructed is the TlvWriter.TlvScope returned by the method.

Normally, a Dispose method overwrites sensitive data or releases resources (files, internet connections, etc.). However, the Dispose in this class simply makes sure the Nested TLV is closed. Any new calls to Write will apply to the next level up.

There are certain calls you can make only after a schema has been completely entered. To be completely entered means the outermost Nested TLV has been closed (the closing curly brace).

WriteString(int, string, Encoding)

Add a string as the value to be written out.

public void WriteString(int tag, string value, Encoding encoding)

Parameters

tag int

The tag that will be written out when this TLV is encoded.

value string

The string to be converted into a byte array.

encoding Encoding

The encoding system to use to convert the string to a byte array, such as System.Text.Encoding.ASCII or UTF8.

Remarks

The C# String object is essentially a character array. However, each character is 16 bits. You can build strings using ASCII characters (each of which is 8 bits long, with the most significant bit 0). For example,

string someString = "ABCD"
represented internally as 00 41 00 42 00 43 00 44

But suppose you want to write out a TLV with the value being the byte array that is the ASCII character array.

 tag 04 41 42 43 44
You don't want to simply copy the internal array, otherwise you
would get
 tag 08 00 41 00 42 00 43 00 44

To get a byte array that returns each character as a single byte, you can use the System.Text.Encoding class. For the TlvWriter class, this method (WriteString) will call on the Encoding class to convert the input string into a byte array that will be the value in a TLV. You only need supply the encoding scheme. The scheme you specify must be in the form of a System.Text.Encoding object. It is easy to supply such and object, simply pass in Encoding.ASCII, Encoding.UTF8, or any of the other encoding schemes supported in that class (look at the documentation for System.Text.Encoding, there are several properties with the summary of "Gets an encoding for...").

For example:

string someString = "ABCD";
writer.WriteString(0x81, someString, Encoding.ASCII);

A string with non-ASCII characters will be stored internally with the 16-bit version of that character. For example, look at a string with the "plus-minus" character.

string someString = "A\u00B1B"; // this is A +or- B
represented internally as 00 41 00 B1 00 42
Encoding that using the ASCII encoding scheme will not produce the correct output. There are a couple of options:
writer.WriteString(tag, someString, Encoding.BigEndianUnicode);
  tag 06 00 41 00 B1 00 42
writer.WriteString(tag, someString, Encoding.UTF8);
  tag 04 41 C2 B1 42

Exceptions

ArgumentNullException

The encoding argument is null.

TlvException

The tag is invalid, or the length is unsupported.

WriteUInt16(int, ushort, bool)

Add an unsigned 16-bit integer as the value to be written out.

[CLSCompliant(false)]
public void WriteUInt16(int tag, ushort value, bool bigEndian = true)

Parameters

tag int

The tag that will be written out when this TLV is encoded.

value ushort

The unsigned short to be converted into a byte array.

bigEndian bool

If true, write out the short as big endian, with the high order byte of the value in the left most position in the byte array. If false, write out the value as little endian, with the low order byte of the value in the left most position in the byte array.

WriteValue(int, ReadOnlySpan<byte>)

Add a byte array as a value to be written out.

public void WriteValue(int tag, ReadOnlySpan<byte> value)

Parameters

tag int

The tag that will be written out when this TLV is encoded.

value ReadOnlySpan<byte>

The byte array that is the value.

Remarks

When an Encode method is called, the tag and value given will be written out as the T and V of the TLV.

If there is no data, pass an empty Span: ReadOnlySpan<byte>.Empty. In that case, what is written out is simply tag 00.

Exceptions

TlvException

The tag is invalid, or the length is unsupported.