Create asValidObject method - not compiling

This commit is contained in:
Benoit Marty 2020-03-05 12:06:19 +01:00
parent 36c52d24a7
commit 7b5a50ec6e
23 changed files with 189 additions and 149 deletions

View File

@ -37,19 +37,6 @@ internal data class MessageVerificationAcceptContent(
override val transactionID: String? override val transactionID: String?
get() = relatesTo?.eventId get() = relatesTo?.eventId
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank()
|| keyAgreementProtocol.isNullOrBlank()
|| hash.isNullOrBlank()
|| commitment.isNullOrBlank()
|| messageAuthenticationCode.isNullOrBlank()
|| shortAuthenticationStrings.isNullOrEmpty()) {
Timber.e("## received invalid verification request")
return false
}
return true
}
override fun toEventContent() = toContent() override fun toEventContent() = toContent()
companion object : VerificationInfoAcceptFactory { companion object : VerificationInfoAcceptFactory {

View File

@ -28,7 +28,6 @@ data class MessageVerificationCancelContent(
@Json(name = "code") override val code: String? = null, @Json(name = "code") override val code: String? = null,
@Json(name = "reason") override val reason: String? = null, @Json(name = "reason") override val reason: String? = null,
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?
) : VerificationInfoCancel { ) : VerificationInfoCancel {
override val transactionID: String? override val transactionID: String?
@ -36,13 +35,6 @@ data class MessageVerificationCancelContent(
override fun toEventContent() = toContent() override fun toEventContent() = toContent()
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || code.isNullOrBlank()) {
return false
}
return true
}
companion object { companion object {
fun create(transactionId: String, reason: CancelCode): MessageVerificationCancelContent { fun create(transactionId: String, reason: CancelCode): MessageVerificationCancelContent {
return MessageVerificationCancelContent( return MessageVerificationCancelContent(

View File

@ -25,12 +25,20 @@ import im.vector.matrix.android.internal.crypto.verification.VerificationInfo
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
internal data class MessageVerificationDoneContent( internal data class MessageVerificationDoneContent(
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? @Json(name = "m.relates_to") val relatesTo: RelationDefaultContent?
) : VerificationInfo { ) : VerificationInfo<ValidVerificationDone> {
override val transactionID: String? override val transactionID: String?
get() = relatesTo?.eventId get() = relatesTo?.eventId
override fun isValid() = transactionID?.isNotEmpty() == true
override fun toEventContent(): Content? = toContent() override fun toEventContent(): Content? = toContent()
override fun asValidObject(): ValidVerificationDone? {
if (transactionID.isNullOrEmpty()) {
return null
}
return ValidVerificationDone
}
} }
internal object ValidVerificationDone

View File

@ -22,7 +22,6 @@ import im.vector.matrix.android.api.session.events.model.toContent
import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent
import im.vector.matrix.android.internal.crypto.verification.VerificationInfoKey import im.vector.matrix.android.internal.crypto.verification.VerificationInfoKey
import im.vector.matrix.android.internal.crypto.verification.VerificationInfoKeyFactory import im.vector.matrix.android.internal.crypto.verification.VerificationInfoKeyFactory
import timber.log.Timber
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
internal data class MessageVerificationKeyContent( internal data class MessageVerificationKeyContent(
@ -36,14 +35,6 @@ internal data class MessageVerificationKeyContent(
override val transactionID: String? override val transactionID: String?
get() = relatesTo?.eventId get() = relatesTo?.eventId
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || key.isNullOrBlank()) {
Timber.e("## received invalid verification request")
return false
}
return true
}
override fun toEventContent() = toContent() override fun toEventContent() = toContent()
companion object : VerificationInfoKeyFactory { companion object : VerificationInfoKeyFactory {

View File

@ -35,13 +35,6 @@ internal data class MessageVerificationMacContent(
override fun toEventContent() = toContent() override fun toEventContent() = toContent()
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || keys.isNullOrBlank() || mac.isNullOrEmpty()) {
return false
}
return true
}
companion object : VerificationInfoMacFactory { companion object : VerificationInfoMacFactory {
override fun create(tid: String, mac: Map<String, String>, keys: String): VerificationInfoMac { override fun create(tid: String, mac: Map<String, String>, keys: String): VerificationInfoMac {
return MessageVerificationMacContent( return MessageVerificationMacContent(

View File

@ -35,13 +35,6 @@ internal data class MessageVerificationReadyContent(
override fun toEventContent() = toContent() override fun toEventContent() = toContent()
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || methods.isNullOrEmpty() || fromDevice.isNullOrEmpty()) {
return false
}
return true
}
companion object : MessageVerificationReadyFactory { companion object : MessageVerificationReadyFactory {
override fun create(tid: String, methods: List<String>, fromDevice: String): VerificationInfoReady { override fun create(tid: String, methods: List<String>, fromDevice: String): VerificationInfoReady {
return MessageVerificationReadyContent( return MessageVerificationReadyContent(

View File

@ -36,13 +36,6 @@ data class MessageVerificationRequestContent(
@Json(name = "m.new_content") override val newContent: Content? = null @Json(name = "m.new_content") override val newContent: Content? = null
) : MessageContent, VerificationInfoRequest { ) : MessageContent, VerificationInfoRequest {
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || methods.isNullOrEmpty() || fromDevice.isNullOrEmpty()) {
return false
}
return true
}
override val transactionID: String? override val transactionID: String?
get() = relatesTo?.eventId get() = relatesTo?.eventId

View File

@ -67,19 +67,6 @@ internal data class KeyVerificationAccept(
override var commitment: String? = null override var commitment: String? = null
) : SendToDeviceObject, VerificationInfoAccept { ) : SendToDeviceObject, VerificationInfoAccept {
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank()
|| keyAgreementProtocol.isNullOrBlank()
|| hash.isNullOrBlank()
|| commitment.isNullOrBlank()
|| messageAuthenticationCode.isNullOrBlank()
|| shortAuthenticationStrings.isNullOrEmpty()) {
Timber.e("## received invalid verification request")
return false
}
return true
}
override fun toSendToDeviceObject() = this override fun toSendToDeviceObject() = this
companion object : VerificationInfoAcceptFactory { companion object : VerificationInfoAcceptFactory {

View File

@ -53,11 +53,4 @@ internal data class KeyVerificationCancel(
} }
override fun toSendToDeviceObject() = this override fun toSendToDeviceObject() = this
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || code.isNullOrBlank()) {
return false
}
return true
}
} }

View File

@ -28,11 +28,4 @@ internal data class KeyVerificationDone(
) : SendToDeviceObject, VerificationInfoDone { ) : SendToDeviceObject, VerificationInfoDone {
override fun toSendToDeviceObject() = this override fun toSendToDeviceObject() = this
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank()) {
return false
}
return true
}
} }

View File

@ -44,11 +44,4 @@ internal data class KeyVerificationKey(
} }
override fun toSendToDeviceObject() = this override fun toSendToDeviceObject() = this
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || key.isNullOrBlank()) {
return false
}
return true
}
} }

View File

@ -31,13 +31,6 @@ internal data class KeyVerificationMac(
) : SendToDeviceObject, VerificationInfoMac { ) : SendToDeviceObject, VerificationInfoMac {
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || keys.isNullOrBlank() || mac.isNullOrEmpty()) {
return false
}
return true
}
override fun toSendToDeviceObject(): SendToDeviceObject? = this override fun toSendToDeviceObject(): SendToDeviceObject? = this
companion object : VerificationInfoMacFactory { companion object : VerificationInfoMacFactory {

View File

@ -30,8 +30,4 @@ internal data class KeyVerificationReady(
) : SendToDeviceObject, VerificationInfoReady { ) : SendToDeviceObject, VerificationInfoReady {
override fun toSendToDeviceObject() = this override fun toSendToDeviceObject() = this
override fun isValid(): Boolean {
return !transactionID.isNullOrBlank() && !fromDevice.isNullOrBlank() && !methods.isNullOrEmpty()
}
} }

View File

@ -32,11 +32,4 @@ internal data class KeyVerificationRequest(
) : SendToDeviceObject, VerificationInfoRequest { ) : SendToDeviceObject, VerificationInfoRequest {
override fun toSendToDeviceObject() = this override fun toSendToDeviceObject() = this
override fun isValid(): Boolean {
if (transactionID.isNullOrBlank() || methods.isNullOrEmpty() || fromDevice.isNullOrEmpty()) {
return false
}
return true
}
} }

View File

@ -18,10 +18,11 @@ package im.vector.matrix.android.internal.crypto.verification
import im.vector.matrix.android.api.session.events.model.Content import im.vector.matrix.android.api.session.events.model.Content
import im.vector.matrix.android.internal.crypto.model.rest.SendToDeviceObject import im.vector.matrix.android.internal.crypto.model.rest.SendToDeviceObject
interface VerificationInfo { interface VerificationInfo<ValidObject> {
fun toEventContent(): Content? = null fun toEventContent(): Content? = null
fun toSendToDeviceObject(): SendToDeviceObject? = null fun toSendToDeviceObject(): SendToDeviceObject? = null
fun isValid(): Boolean
fun asValidObject(): ValidObject?
/** /**
* String to identify the transaction. * String to identify the transaction.

View File

@ -15,7 +15,9 @@
*/ */
package im.vector.matrix.android.internal.crypto.verification package im.vector.matrix.android.internal.crypto.verification
internal interface VerificationInfoAccept : VerificationInfo { import timber.log.Timber
internal interface VerificationInfoAccept : VerificationInfo<ValidVerificationInfoAccept> {
/** /**
* The key agreement protocol that Bobs device has selected to use, out of the list proposed by Alices device * The key agreement protocol that Bobs device has selected to use, out of the list proposed by Alices device
*/ */
@ -41,6 +43,27 @@ internal interface VerificationInfoAccept : VerificationInfo {
* and the canonical JSON representation of the m.key.verification.start message. * and the canonical JSON representation of the m.key.verification.start message.
*/ */
var commitment: String? var commitment: String?
override fun asValidObject(): ValidVerificationInfoAccept? {
if (transactionID.isNullOrBlank()
|| keyAgreementProtocol.isNullOrBlank()
|| hash.isNullOrBlank()
|| commitment.isNullOrBlank()
|| messageAuthenticationCode.isNullOrBlank()
|| shortAuthenticationStrings.isNullOrEmpty()) {
Timber.e("## received invalid verification request")
return null
}
return ValidVerificationInfoAccept(
transactionID!!,
keyAgreementProtocol!!,
hash!!,
messageAuthenticationCode!!,
shortAuthenticationStrings!!,
commitment
)
}
} }
internal interface VerificationInfoAcceptFactory { internal interface VerificationInfoAcceptFactory {
@ -52,3 +75,12 @@ internal interface VerificationInfoAcceptFactory {
messageAuthenticationCode: String, messageAuthenticationCode: String,
shortAuthenticationStrings: List<String>): VerificationInfoAccept shortAuthenticationStrings: List<String>): VerificationInfoAccept
} }
internal data class ValidVerificationInfoAccept(
val transactionID: String,
val keyAgreementProtocol: String,
val hash: String,
val messageAuthenticationCode: String,
val shortAuthenticationStrings: List<String>,
var commitment: String?
)

View File

@ -15,7 +15,7 @@
*/ */
package im.vector.matrix.android.internal.crypto.verification package im.vector.matrix.android.internal.crypto.verification
internal interface VerificationInfoCancel : VerificationInfo { internal interface VerificationInfoCancel : VerificationInfo<ValidVerificationInfoCancel> {
/** /**
* machine-readable reason for cancelling, see [CancelCode] * machine-readable reason for cancelling, see [CancelCode]
*/ */
@ -25,4 +25,19 @@ internal interface VerificationInfoCancel : VerificationInfo {
* human-readable reason for cancelling. This should only be used if the receiving client does not understand the code given. * human-readable reason for cancelling. This should only be used if the receiving client does not understand the code given.
*/ */
val reason: String? val reason: String?
override fun asValidObject(): ValidVerificationInfoCancel? {
if (transactionID.isNullOrBlank() || code.isNullOrBlank()) {
return null
}
return ValidVerificationInfoCancel(
code!!,
reason
)
}
} }
internal data class ValidVerificationInfoCancel(
val code: String,
val reason: String?
)

View File

@ -15,4 +15,14 @@
*/ */
package im.vector.matrix.android.internal.crypto.verification package im.vector.matrix.android.internal.crypto.verification
interface VerificationInfoDone : VerificationInfo internal interface VerificationInfoDone : VerificationInfo<ValidVerificationInfoDone> {
override fun asValidObject(): ValidVerificationInfoDone? {
if (transactionID.isNullOrBlank()) {
return null
}
return ValidVerificationInfoDone
}
}
internal object ValidVerificationInfoDone

View File

@ -18,13 +18,26 @@ package im.vector.matrix.android.internal.crypto.verification
/** /**
* Sent by both devices to send their ephemeral Curve25519 public key to the other device. * Sent by both devices to send their ephemeral Curve25519 public key to the other device.
*/ */
internal interface VerificationInfoKey : VerificationInfo { internal interface VerificationInfoKey : VerificationInfo<ValidVerificationInfoKey> {
/** /**
* The devices ephemeral public key, as an unpadded base64 string * The devices ephemeral public key, as an unpadded base64 string
*/ */
val key: String? val key: String?
override fun asValidObject(): ValidVerificationInfoKey? {
if (transactionID.isNullOrBlank() || key.isNullOrBlank()) {
return null
}
return ValidVerificationInfoKey(
key!!
)
}
} }
internal interface VerificationInfoKeyFactory { internal interface VerificationInfoKeyFactory {
fun create(tid: String, pubKey: String): VerificationInfoKey fun create(tid: String, pubKey: String): VerificationInfoKey
} }
internal data class ValidVerificationInfoKey(
val key: String
)

View File

@ -15,7 +15,7 @@
*/ */
package im.vector.matrix.android.internal.crypto.verification package im.vector.matrix.android.internal.crypto.verification
internal interface VerificationInfoMac : VerificationInfo { internal interface VerificationInfoMac : VerificationInfo<ValidVerificationInfoMac> {
/** /**
* A map of key ID to the MAC of the key, as an unpadded base64 string, calculated using the MAC key * A map of key ID to the MAC of the key, as an unpadded base64 string, calculated using the MAC key
*/ */
@ -28,8 +28,23 @@ internal interface VerificationInfoMac : VerificationInfo {
* give the MAC of the string ed25519:ABCDEFG,ed25519:HIJKLMN. * give the MAC of the string ed25519:ABCDEFG,ed25519:HIJKLMN.
*/ */
val keys: String? val keys: String?
override fun asValidObject(): ValidVerificationInfoMac? {
if (transactionID.isNullOrBlank() || keys.isNullOrBlank() || mac.isNullOrEmpty()) {
return null
}
return ValidVerificationInfoMac(
mac!!,
keys!!
)
}
} }
internal interface VerificationInfoMacFactory { internal interface VerificationInfoMacFactory {
fun create(tid: String, mac: Map<String, String>, keys: String) : VerificationInfoMac fun create(tid: String, mac: Map<String, String>, keys: String): VerificationInfoMac
} }
internal data class ValidVerificationInfoMac(
val mac: Map<String, String>,
val keys: String
)

View File

@ -23,7 +23,7 @@ package im.vector.matrix.android.internal.crypto.verification
* with a m.key.verification.start event instead. * with a m.key.verification.start event instead.
*/ */
interface VerificationInfoReady : VerificationInfo { internal interface VerificationInfoReady : VerificationInfo<ValidVerificationInfoReady> {
/** /**
* The ID of the device that sent the m.key.verification.ready message * The ID of the device that sent the m.key.verification.ready message
*/ */
@ -33,8 +33,26 @@ interface VerificationInfoReady : VerificationInfo {
* An array of verification methods that the device supports * An array of verification methods that the device supports
*/ */
val methods: List<String>? val methods: List<String>?
override fun asValidObject(): ValidVerificationInfoReady? {
if (transactionID.isNullOrBlank()
|| fromDevice.isNullOrBlank()
|| methods.isNullOrEmpty()) {
return null
}
return ValidVerificationInfoReady(
fromDevice!!,
methods!!
)
}
} }
internal interface MessageVerificationReadyFactory { internal interface MessageVerificationReadyFactory {
fun create(tid: String, methods: List<String>, fromDevice: String): VerificationInfoReady fun create(tid: String, methods: List<String>, fromDevice: String): VerificationInfoReady
} }
internal data class ValidVerificationInfoReady(
val fromDevice: String,
val methods: List<String>
)

View File

@ -15,7 +15,7 @@
*/ */
package im.vector.matrix.android.internal.crypto.verification package im.vector.matrix.android.internal.crypto.verification
interface VerificationInfoRequest : VerificationInfo { internal interface VerificationInfoRequest : VerificationInfo<ValidVerificationInfoRequest> {
/** /**
* Required. The device ID which is initiating the request. * Required. The device ID which is initiating the request.
@ -33,4 +33,22 @@ interface VerificationInfoRequest : VerificationInfo {
* the message should be ignored by the receiver. * the message should be ignored by the receiver.
*/ */
val timestamp: Long? val timestamp: Long?
override fun asValidObject(): ValidVerificationInfoRequest? {
// FIXME No check on Timestamp?
if (transactionID.isNullOrBlank() || methods.isNullOrEmpty() || fromDevice.isNullOrEmpty()) {
return null
}
return ValidVerificationInfoRequest(
fromDevice!!,
methods!!,
timestamp
)
}
} }
internal data class ValidVerificationInfoRequest(
val fromDevice: String,
val methods: List<String>,
val timestamp: Long?
)

View File

@ -18,9 +18,8 @@ package im.vector.matrix.android.internal.crypto.verification
import im.vector.matrix.android.api.session.crypto.verification.SasMode import im.vector.matrix.android.api.session.crypto.verification.SasMode
import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_RECIPROCATE import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_RECIPROCATE
import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_SAS import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_SAS
import timber.log.Timber
internal interface VerificationInfoStart : VerificationInfo { internal interface VerificationInfoStart : VerificationInfo<ValidVerificationInfoStart> {
val method: String? val method: String?
@ -64,40 +63,54 @@ internal interface VerificationInfoStart : VerificationInfo {
fun toCanonicalJson(): String? fun toCanonicalJson(): String?
override fun isValid(): Boolean { override fun asValidObject(): ValidVerificationInfoStart? {
if (transactionID.isNullOrBlank() if (transactionID.isNullOrBlank()
|| fromDevice.isNullOrBlank() || fromDevice.isNullOrBlank()) {
|| (method == VERIFICATION_METHOD_SAS && !isValidSas()) return null
|| (method == VERIFICATION_METHOD_RECIPROCATE && !isValidReciprocate())) {
Timber.e("## received invalid verification request")
return false
}
return true
}
private fun isValidSas(): Boolean {
val myHashes = hashes
val myMessageAuthenticationCodes = messageAuthenticationCodes
val myShortAuthenticationStrings = shortAuthenticationStrings
if (keyAgreementProtocols.isNullOrEmpty()
|| myHashes.isNullOrEmpty()
|| !myHashes.contains("sha256") || myMessageAuthenticationCodes.isNullOrEmpty()
|| (!myMessageAuthenticationCodes.contains(SASDefaultVerificationTransaction.SAS_MAC_SHA256)
&& !myMessageAuthenticationCodes.contains(SASDefaultVerificationTransaction.SAS_MAC_SHA256_LONGKDF))
|| myShortAuthenticationStrings.isNullOrEmpty()
|| !myShortAuthenticationStrings.contains(SasMode.DECIMAL)) {
return false
} }
return true return when (method) {
} VERIFICATION_METHOD_SAS -> {
if (keyAgreementProtocols.isNullOrEmpty()
private fun isValidReciprocate(): Boolean { || hashes.isNullOrEmpty()
if (sharedSecret.isNullOrBlank()) { || !hashes!!.contains("sha256") || messageAuthenticationCodes.isNullOrEmpty()
return false || (!messageAuthenticationCodes!!.contains(SASDefaultVerificationTransaction.SAS_MAC_SHA256)
&& !messageAuthenticationCodes!!.contains(SASDefaultVerificationTransaction.SAS_MAC_SHA256_LONGKDF))
|| shortAuthenticationStrings.isNullOrEmpty()
|| !shortAuthenticationStrings!!.contains(SasMode.DECIMAL)) {
null
} else {
ValidVerificationInfoStart.SasVerificationInfoStart(
keyAgreementProtocols!!,
hashes!!,
messageAuthenticationCodes!!,
shortAuthenticationStrings!!
)
}
}
VERIFICATION_METHOD_RECIPROCATE -> {
if (sharedSecret.isNullOrBlank()) {
null
} else {
ValidVerificationInfoStart.ReciprocateVerificationInfoStart(
sharedSecret!!
)
}
}
else -> null
} }
return true
} }
} }
sealed class ValidVerificationInfoStart {
data class SasVerificationInfoStart(
val keyAgreementProtocols: List<String>,
val hashes: List<String>,
val messageAuthenticationCodes: List<String>,
val shortAuthenticationStrings: List<String>
) : ValidVerificationInfoStart()
data class ReciprocateVerificationInfoStart(
val sharedSecret: String
) : ValidVerificationInfoStart()
}