Skip to content

Commit

Permalink
feat: Implement parcel delivery control messages
Browse files Browse the repository at this point in the history
  • Loading branch information
gnarea committed Aug 14, 2020
1 parent aae0c50 commit d534e42
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package tech.relaycorp.relaynet.messages.control

import org.bouncycastle.asn1.ASN1TaggedObject
import org.bouncycastle.asn1.DEROctetString
import org.bouncycastle.asn1.DERVisibleString
import tech.relaycorp.relaynet.messages.InvalidMessageException
import tech.relaycorp.relaynet.wrappers.asn1.ASN1Exception
import tech.relaycorp.relaynet.wrappers.asn1.ASN1Utils

/**
* Parcel delivery.
*/
class ParcelDelivery(val deliveryId: String, val parcelSerialized: ByteArray) {
/**
* Serialize delivery.
*/
fun serialize(): ByteArray = ASN1Utils.serializeSequence(
arrayOf(DERVisibleString(deliveryId), DEROctetString(parcelSerialized)),
false
)

companion object {
/**
* Deserialize delivery
*/
@Throws(InvalidMessageException::class)
fun deserialize(serialization: ByteArray): ParcelDelivery {
val sequence = try {
ASN1Utils.deserializeSequence(serialization)
} catch (exc: ASN1Exception) {
throw InvalidMessageException("Delivery is not a DER sequence", exc)
}
if (sequence.size < 2) {
throw InvalidMessageException(
"Delivery sequence should have at least 2 items (got ${sequence.size})"
)
}
val deliveryIdASN1 =
DERVisibleString.getInstance(sequence[0] as ASN1TaggedObject, false)
val parcelSerializedASN1 =
DEROctetString.getInstance(sequence[1] as ASN1TaggedObject, false)
return ParcelDelivery(deliveryIdASN1.string, parcelSerializedASN1.octets)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package tech.relaycorp.relaynet.messages.control

import org.bouncycastle.asn1.ASN1TaggedObject
import org.bouncycastle.asn1.DERNull
import org.bouncycastle.asn1.DEROctetString
import org.bouncycastle.asn1.DERVisibleString
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import tech.relaycorp.relaynet.messages.InvalidMessageException
import tech.relaycorp.relaynet.wrappers.asn1.ASN1Exception
import tech.relaycorp.relaynet.wrappers.asn1.ASN1Utils
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class ParcelDeliveryTest {
val deliveryId = "the id"
val parcelSerialized = "This appears to be a parcel".toByteArray()

@Nested
inner class Serialize {
@Test
fun `Delivery id should be serialized`() {
val delivery = ParcelDelivery(deliveryId, parcelSerialized)

val serialization = delivery.serialize()

val sequenceASN1 = ASN1Utils.deserializeSequence(serialization)
val deliveryIdASN1 =
DERVisibleString.getInstance(sequenceASN1.first() as ASN1TaggedObject, false)
assertEquals(deliveryId, deliveryIdASN1.string)
}

@Test
fun `Parcel should be serialized`() {
val delivery = ParcelDelivery(deliveryId, parcelSerialized)

val serialization = delivery.serialize()

val sequenceASN1 = ASN1Utils.deserializeSequence(serialization)
val parcelSerializedASN1 =
DEROctetString.getInstance(sequenceASN1[1] as ASN1TaggedObject, false)
assertEquals(
parcelSerialized.asList(),
parcelSerializedASN1.octets.asList()
)
}
}

@Nested
inner class Deserialize {
@Test
fun `Serialization should be a DER sequence`() {
val exception = assertThrows<InvalidMessageException> {
ParcelDelivery.deserialize(byteArrayOf(0))
}

assertEquals("Delivery is not a DER sequence", exception.message)
assertTrue(exception.cause is ASN1Exception)
}

@Test
fun `Sequence should have at lease two items`() {
val invalidSequence = ASN1Utils.serializeSequence(arrayOf(DERNull.INSTANCE), false)

val exception = assertThrows<InvalidMessageException> {
ParcelDelivery.deserialize(invalidSequence)
}

assertEquals(
"Delivery sequence should have at least 2 items (got 1)",
exception.message
)
}

@Test
fun `Valid deliveries should be accepted`() {
val delivery = ParcelDelivery(deliveryId, parcelSerialized)
val serialization = delivery.serialize()

val deliveryDeserialized = ParcelDelivery.deserialize(serialization)

assertEquals(deliveryId, deliveryDeserialized.deliveryId)
assertEquals(parcelSerialized.asList(), deliveryDeserialized.parcelSerialized.asList())
}
}
}

0 comments on commit d534e42

Please sign in to comment.