Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix and beautify OCTET STRING class hierarchy #24

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -204,22 +204,32 @@ class Asn1Sequence(children: List<Asn1Element>) : Asn1Structure(DERTags.DER_SEQU
* ASN.1 OCTET STRING 0x04 ([BERTags.OCTET_STRING]) containing an [Asn1Element]
* @param children the elements to put into this sequence
*/
class Asn1EncapsulatingOctetString(children: List<Asn1Element>) : Asn1Structure(BERTags.OCTET_STRING, children) {
class Asn1EncapsulatingOctetString(children: List<Asn1Element>) : Asn1Structure(BERTags.OCTET_STRING, children),
Asn1OctetString<Asn1EncapsulatingOctetString> {
override val content: ByteArray by lazy {
children.fold(byteArrayOf()) { acc, asn1Element -> acc + asn1Element.derEncoded }
}

override fun unwrap() = this

override fun toString() = "OCTET STRING Encapsulating" + super.toString()


override fun prettyPrint(indent: Int) =
(" " * indent) + "OCTET STRING Encapsulating" + super.prettyPrint(indent + 2)


public override val content: ByteArray get() = super.content
}

/**
* ASN.1 OCTET STRING 0x04 ([BERTags.OCTET_STRING]) containing data, which does not decode to an [Asn1Element]
* @param content the data to hold
*/
class Asn1PrimitiveOctetString(content: ByteArray) : Asn1Primitive(BERTags.OCTET_STRING, content) {
class Asn1PrimitiveOctetString(content: ByteArray) : Asn1Primitive(BERTags.OCTET_STRING, content),
Asn1OctetString<Asn1PrimitiveOctetString> {

override val content: ByteArray get() = super.content

override fun unwrap() = this

override fun toString() = "OCTET STRING " + super.toString()

override fun prettyPrint(indent: Int) = (" " * indent) + "OCTET STRING Primitive" + tlv.toString().substring(3)
Expand Down Expand Up @@ -247,12 +257,40 @@ open class Asn1Primitive(tag: UByte, content: ByteArray) : Asn1Element(TLV(tag,
override fun prettyPrint(indent: Int) = (" " * indent) + "Primitive" + super.prettyPrint(indent)

/**
* Data contained in this ASN.1 primitive in its encoded form. Requires decoding to interpret it
* Raw data contained in this ASN.1 primitive in its encoded form. Requires decoding to interpret it
*/
public override val content: ByteArray
get() = super.content
}


/**
* Interface describing an ASN.1 OCTET STRING.
* This is really more of a crutch, since an octet string is either an
*
* * [Asn1Primitive] if it contains bytes, that cannot be interpreted as an ASN.1 Structure
* * [Asn1Structure] if it contains one or more valid [Asn1Element]s
*
* This interface is implemented by [Asn1PrimitiveOctetString] for the former case and by [Asn1EncapsulatingOctetString] to cover the latter case
* Hence, [T] will either be [Asn1Primitive]/[Asn1PrimitiveOctetString] or [Asn1Structure]/[Asn1EncapsulatingOctetString]
*/
interface Asn1OctetString<T : Asn1Element> {

/**
* Raw data contained in this ASN.1 primitive in its encoded form. Requires decoding to interpret it.
*
* It makes sense to have this for both kinds of octet strings, since many intermediate processing steps don't care about semantics.
*/
val content: ByteArray

/**
* Returns the actual type of this object inside the [Asn1Element] class hierarchy
* [T] will either be [Asn1Primitive]/[Asn1PrimitiveOctetString] or [Asn1Structure]/[Asn1EncapsulatingOctetString]
*/
fun unwrap(): T
}


data class TLV(val tag: UByte, val content: ByteArray) {

val encodedLength by lazy { length.encodeLength() }
Expand Down