Skip to content

Commit

Permalink
Implement unwrapping
Browse files Browse the repository at this point in the history
  • Loading branch information
gnarea committed Jul 17, 2020
1 parent 10c8556 commit d949dbf
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tech.relaycorp.relaynet.messages

import tech.relaycorp.relaynet.messages.payloads.EmptyPayloadPlaintext
import tech.relaycorp.relaynet.ramf.RAMFException
import tech.relaycorp.relaynet.ramf.RAMFMessage
import tech.relaycorp.relaynet.ramf.RAMFMessageCompanion
Expand All @@ -21,7 +22,7 @@ class CargoCollectionAuthorization(
creationDate: ZonedDateTime? = null,
ttl: Int? = null,
senderCertificateChain: Set<Certificate>? = null
) : RAMFMessage(
) : RAMFMessage<EmptyPayloadPlaintext>(
SERIALIZER,
recipientAddress,
payload,
Expand All @@ -31,6 +32,10 @@ class CargoCollectionAuthorization(
ttl,
senderCertificateChain
) {
override fun deserializePayload(payloadPlaintext: ByteArray): EmptyPayloadPlaintext {
TODO("Not yet implemented")
}

companion object : RAMFMessageCompanion<CargoCollectionAuthorization> {
/**
* Deserialize a CCA
Expand Down
7 changes: 6 additions & 1 deletion src/main/kotlin/tech/relaycorp/relaynet/messages/Parcel.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tech.relaycorp.relaynet.messages

import tech.relaycorp.relaynet.messages.payloads.ServiceMessage
import tech.relaycorp.relaynet.ramf.RAMFException
import tech.relaycorp.relaynet.ramf.RAMFMessage
import tech.relaycorp.relaynet.ramf.RAMFMessageCompanion
Expand All @@ -21,7 +22,7 @@ class Parcel(
creationDate: ZonedDateTime? = null,
ttl: Int? = null,
senderCertificateChain: Set<Certificate>? = null
) : RAMFMessage(
) : RAMFMessage<ServiceMessage>(
SERIALIZER,
recipientAddress,
payload,
Expand All @@ -31,6 +32,10 @@ class Parcel(
ttl,
senderCertificateChain
) {
override fun deserializePayload(payloadPlaintext: ByteArray): ServiceMessage {
TODO("Not yet implemented")
}

companion object : RAMFMessageCompanion<Parcel> {
/**
* Deserialize parcel
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package tech.relaycorp.relaynet.messages.payloads

class EmptyPayloadPlaintext : PayloadPlaintext {
override fun serialize(): ByteArray {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package tech.relaycorp.relaynet.messages.payloads

class ServiceMessage : PayloadPlaintext {
override fun serialize(): ByteArray {
TODO("Not yet implemented")
}
}
22 changes: 20 additions & 2 deletions src/main/kotlin/tech/relaycorp/relaynet/ramf/RAMFMessage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package tech.relaycorp.relaynet.ramf
import tech.relaycorp.relaynet.HashingAlgorithm
import tech.relaycorp.relaynet.dateToZonedDateTime
import tech.relaycorp.relaynet.messages.payloads.PayloadPlaintext
import tech.relaycorp.relaynet.wrappers.cms.EnvelopedData
import tech.relaycorp.relaynet.wrappers.cms.EnvelopedDataException
import tech.relaycorp.relaynet.wrappers.cms.SessionlessEnvelopedData
import tech.relaycorp.relaynet.wrappers.x509.Certificate
import tech.relaycorp.relaynet.wrappers.x509.CertificateException
import java.net.MalformedURLException
Expand Down Expand Up @@ -114,8 +117,6 @@ abstract class RAMFMessage<Payload : PayloadPlaintext> internal constructor(
return this.serializer.serialize(this, senderPrivateKey, hashingAlgorithm)
}

protected abstract fun deserializePayload(payloadPlaintext: ByteArray): Payload

/**
* Validate the message.
*
Expand All @@ -134,6 +135,23 @@ abstract class RAMFMessage<Payload : PayloadPlaintext> internal constructor(
validateRecipientAddress()
}

/**
* Decrypt and deserialize payload.
*
* @throws EnvelopedDataException if the CMS EnvelopedData value is invalid or the
* `privateKey` is invalid.
* @throws RAMFException if the plaintext is invalid.
*/
@Throws(RAMFException::class, EnvelopedDataException::class)
fun unwrapPayload(privateKey: PrivateKey): Payload {
val envelopedData = EnvelopedData.deserialize(payload) as SessionlessEnvelopedData
val plaintext = envelopedData.decrypt(privateKey)
return deserializePayload(plaintext)
}

@Throws(RAMFException::class)
protected abstract fun deserializePayload(payloadPlaintext: ByteArray): Payload

private fun validateTiming() {
val now = ZonedDateTime.now(UTC)
if (now < creationDate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package tech.relaycorp.relaynet.ramf

import java.io.InputStream

internal interface RAMFMessageCompanion<Message : RAMFMessage> {
internal interface RAMFMessageCompanion<Message : RAMFMessage<*>> {
fun deserialize(serialization: ByteArray): Message
fun deserialize(serialization: InputStream): Message
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ private data class FieldSet(

internal class RAMFSerializer(val concreteMessageType: Byte, val concreteMessageVersion: Byte) {
fun serialize(
message: RAMFMessage,
message: RAMFMessage<*>,
signerPrivateKey: PrivateKey,
hashingAlgorithm: HashingAlgorithm? = null
): ByteArray {
Expand All @@ -71,7 +71,7 @@ internal class RAMFSerializer(val concreteMessageType: Byte, val concreteMessage
}

@Throws(IOException::class)
private fun serializeMessage(message: RAMFMessage): ByteArray {
private fun serializeMessage(message: RAMFMessage<*>): ByteArray {
val reverseOS = ReverseByteArrayOutputStream(1000, true)
var codeLength = 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package tech.relaycorp.relaynet.wrappers.cms

import tech.relaycorp.relaynet.RelaynetException

internal class EnvelopedDataException(message: String, cause: Throwable? = null) :
class EnvelopedDataException internal constructor(message: String, cause: Throwable? = null) :
RelaynetException(message, cause)
20 changes: 20 additions & 0 deletions src/test/kotlin/tech/relaycorp/relaynet/ramf/RAMFMessageTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.junit.jupiter.api.assertThrows
import tech.relaycorp.relaynet.HashingAlgorithm
import tech.relaycorp.relaynet.issueStubCertificate
import tech.relaycorp.relaynet.wrappers.cms.HASHING_ALGORITHM_OIDS
import tech.relaycorp.relaynet.wrappers.cms.SessionlessEnvelopedData
import tech.relaycorp.relaynet.wrappers.cms.parseCmsSignedData
import tech.relaycorp.relaynet.wrappers.generateRSAKeyPair
import tech.relaycorp.relaynet.wrappers.x509.Certificate
Expand Down Expand Up @@ -464,6 +465,25 @@ class RAMFMessageTest {
}
}

@Nested
inner class UnwrapPayload {
@Test
fun `SessionlessEnvelopedData payload should be decrypted`() {
val payloadPlaintext = StubPayload("the payload")
val recipientKeyPair = generateRSAKeyPair()
val recipientCertificate =
issueStubCertificate(recipientKeyPair.public, recipientKeyPair.private)
val payloadCiphertext =
SessionlessEnvelopedData.encrypt(payloadPlaintext.serialize(), recipientCertificate)
val message =
StubRAMFMessage(recipientAddress, payloadCiphertext.serialize(), senderCertificate)

val plaintextDeserialized = message.unwrapPayload(recipientKeyPair.private)

assertEquals(payloadPlaintext.payload, plaintextDeserialized.payload)
}
}

@Nested
inner class IsRecipientAddressPrivate {
@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ private val senderCertificate = issueStubCertificate(keyPair.public, keyPair.pri

typealias MinimalRAMFMessageConstructor<M> = (String, ByteArray, Certificate) -> M

fun <M : RAMFMessage> makeRAMFMessageConstructorTests(
fun <M : RAMFMessage<*>> makeRAMFMessageConstructorTests(
messageConstructor: RAMFMessageConstructor<M>,
requiredParamsConstructor: MinimalRAMFMessageConstructor<M>,
expectedConcreteMessageType: Byte,
Expand Down Expand Up @@ -103,7 +103,7 @@ fun <M : RAMFMessage> makeRAMFMessageConstructorTests(
)
}

internal fun <M : RAMFMessage> makeRAMFMessageCompanionTests(
internal fun <M : RAMFMessage<*>> makeRAMFMessageCompanionTests(
companion: RAMFMessageCompanion<M>,
messageConstructor: RAMFMessageConstructor<M>
): Collection<DynamicTest> {
Expand Down
7 changes: 7 additions & 0 deletions src/test/kotlin/tech/relaycorp/relaynet/ramf/StubPayload.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package tech.relaycorp.relaynet.ramf

import tech.relaycorp.relaynet.messages.payloads.PayloadPlaintext

class StubPayload(val payload: String) : PayloadPlaintext {
override fun serialize() = payload.toByteArray()
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tech.relaycorp.relaynet.ramf

import tech.relaycorp.relaynet.wrappers.x509.Certificate
import java.io.InputStream
import java.nio.charset.Charset
import java.time.ZonedDateTime

internal val STUB_SERIALIZER = RAMFSerializer(32, 0)
Expand All @@ -14,7 +15,7 @@ internal class StubRAMFMessage(
creationDate: ZonedDateTime? = null,
ttl: Int? = null,
senderCertificateChain: Set<Certificate>? = null
) : RAMFMessage(
) : RAMFMessage<StubPayload>(
STUB_SERIALIZER,
recipientAddress,
payload,
Expand All @@ -24,6 +25,9 @@ internal class StubRAMFMessage(
ttl,
senderCertificateChain
) {
override fun deserializePayload(payloadPlaintext: ByteArray) =
StubPayload(payloadPlaintext.toString(Charset.forName("ASCII")))

companion object : RAMFMessageCompanion<StubRAMFMessage> {
override fun deserialize(serialization: ByteArray) =
STUB_SERIALIZER.deserialize(serialization, ::StubRAMFMessage)
Expand Down

0 comments on commit d949dbf

Please sign in to comment.