Add new key agreement protocol
This commit is contained in:
parent
f47bef71a4
commit
e0977dd97b
|
@ -468,14 +468,19 @@ class SASTest : InstrumentedTest {
|
|||
|
||||
val aliceSASLatch = CountDownLatch(1)
|
||||
val aliceListener = object : VerificationService.Listener {
|
||||
var matchOnce = true
|
||||
override fun transactionUpdated(tx: VerificationTransaction) {
|
||||
val uxState = (tx as OutgoingSasVerificationTransaction).uxState
|
||||
Log.v("TEST", "== aliceState ${uxState.name}")
|
||||
when (uxState) {
|
||||
OutgoingSasVerificationTransaction.UxState.SHOW_SAS -> {
|
||||
tx.userHasVerifiedShortCode()
|
||||
}
|
||||
OutgoingSasVerificationTransaction.UxState.VERIFIED -> {
|
||||
aliceSASLatch.countDown()
|
||||
if (matchOnce) {
|
||||
matchOnce = false
|
||||
aliceSASLatch.countDown()
|
||||
}
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
|
@ -485,14 +490,23 @@ class SASTest : InstrumentedTest {
|
|||
|
||||
val bobSASLatch = CountDownLatch(1)
|
||||
val bobListener = object : VerificationService.Listener {
|
||||
var acceptOnce = true
|
||||
var matchOnce = true
|
||||
override fun transactionUpdated(tx: VerificationTransaction) {
|
||||
val uxState = (tx as IncomingSasVerificationTransaction).uxState
|
||||
Log.v("TEST", "== bobState ${uxState.name}")
|
||||
when (uxState) {
|
||||
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
|
||||
tx.performAccept()
|
||||
if (acceptOnce) {
|
||||
acceptOnce = false
|
||||
tx.performAccept()
|
||||
}
|
||||
}
|
||||
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
|
||||
tx.userHasVerifiedShortCode()
|
||||
if (matchOnce) {
|
||||
matchOnce = false
|
||||
tx.userHasVerifiedShortCode()
|
||||
}
|
||||
}
|
||||
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
|
||||
bobSASLatch.countDown()
|
||||
|
|
|
@ -198,18 +198,8 @@ internal class DefaultIncomingSASDefaultVerificationTransaction(
|
|||
// using the result as the shared secret.
|
||||
|
||||
getSAS().setTheirPublicKey(otherKey)
|
||||
// (Note: In all of the following HKDF is as defined in RFC 5869, and uses the previously agreed-on hash function as the hash function,
|
||||
// the shared secret as the input keying material, no salt, and with the input parameter set to the concatenation of:
|
||||
// - the string “MATRIX_KEY_VERIFICATION_SAS”,
|
||||
// - the Matrix ID of the user who sent the m.key.verification.start message,
|
||||
// - the device ID of the device that sent the m.key.verification.start message,
|
||||
// - the Matrix ID of the user who sent the m.key.verification.accept message,
|
||||
// - he device ID of the device that sent the m.key.verification.accept message
|
||||
// - the transaction ID.
|
||||
val sasInfo = "MATRIX_KEY_VERIFICATION_SAS$otherUserId$otherDeviceId$userId$deviceId$transactionId"
|
||||
// decimal: generate five bytes by using HKDF.
|
||||
// emoji: generate six bytes by using HKDF.
|
||||
shortCodeBytes = getSAS().generateShortCode(sasInfo, 6)
|
||||
|
||||
shortCodeBytes = calculateSASBytes()
|
||||
|
||||
if (BuildConfig.LOG_PRIVATE_DATA) {
|
||||
Timber.v("************ BOB CODE ${getDecimalCodeRepresentation(shortCodeBytes!!)}")
|
||||
|
@ -219,6 +209,35 @@ internal class DefaultIncomingSASDefaultVerificationTransaction(
|
|||
state = VerificationTxState.ShortCodeReady
|
||||
}
|
||||
|
||||
private fun calculateSASBytes(): ByteArray {
|
||||
when (accepted?.keyAgreementProtocol) {
|
||||
KEY_AGREEMENT_V1 -> {
|
||||
// (Note: In all of the following HKDF is as defined in RFC 5869, and uses the previously agreed-on hash function as the hash function,
|
||||
// the shared secret as the input keying material, no salt, and with the input parameter set to the concatenation of:
|
||||
// - the string “MATRIX_KEY_VERIFICATION_SAS”,
|
||||
// - the Matrix ID of the user who sent the m.key.verification.start message,
|
||||
// - the device ID of the device that sent the m.key.verification.start message,
|
||||
// - the Matrix ID of the user who sent the m.key.verification.accept message,
|
||||
// - he device ID of the device that sent the m.key.verification.accept message
|
||||
// - the transaction ID.
|
||||
val sasInfo = "MATRIX_KEY_VERIFICATION_SAS$otherUserId$otherDeviceId$userId$deviceId$transactionId"
|
||||
|
||||
// decimal: generate five bytes by using HKDF.
|
||||
// emoji: generate six bytes by using HKDF.
|
||||
return getSAS().generateShortCode(sasInfo, 6)
|
||||
}
|
||||
KEY_AGREEMENT_V2 -> {
|
||||
// Adds the SAS public key, and separate by |
|
||||
val sasInfo = "MATRIX_KEY_VERIFICATION_SAS|$otherUserId|$otherDeviceId|$otherKey|$userId|$deviceId|${getSAS().publicKey}|$transactionId"
|
||||
return getSAS().generateShortCode(sasInfo, 6)
|
||||
}
|
||||
else -> {
|
||||
// Protocol has been checked earlier
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onKeyVerificationMac(vMac: ValidVerificationInfoMac) {
|
||||
Timber.v("## SAS I: received mac for request id:$transactionId")
|
||||
// Check for state?
|
||||
|
|
|
@ -193,18 +193,7 @@ internal class DefaultOutgoingSASDefaultVerificationTransaction(
|
|||
|
||||
if (accepted!!.commitment.equals(otherCommitment)) {
|
||||
getSAS().setTheirPublicKey(otherKey)
|
||||
// (Note: In all of the following HKDF is as defined in RFC 5869, and uses the previously agreed-on hash function as the hash function,
|
||||
// the shared secret as the input keying material, no salt, and with the input parameter set to the concatenation of:
|
||||
// - the string “MATRIX_KEY_VERIFICATION_SAS”,
|
||||
// - the Matrix ID of the user who sent the m.key.verification.start message,
|
||||
// - the device ID of the device that sent the m.key.verification.start message,
|
||||
// - the Matrix ID of the user who sent the m.key.verification.accept message,
|
||||
// - he device ID of the device that sent the m.key.verification.accept message
|
||||
// - the transaction ID.
|
||||
val sasInfo = "MATRIX_KEY_VERIFICATION_SAS$userId$deviceId$otherUserId$otherDeviceId$transactionId"
|
||||
// decimal: generate five bytes by using HKDF.
|
||||
// emoji: generate six bytes by using HKDF.
|
||||
shortCodeBytes = getSAS().generateShortCode(sasInfo, 6)
|
||||
shortCodeBytes = calculateSASBytes()
|
||||
state = VerificationTxState.ShortCodeReady
|
||||
} else {
|
||||
// bad commitment
|
||||
|
@ -212,14 +201,45 @@ internal class DefaultOutgoingSASDefaultVerificationTransaction(
|
|||
}
|
||||
}
|
||||
|
||||
private fun calculateSASBytes(): ByteArray {
|
||||
when (accepted?.keyAgreementProtocol) {
|
||||
KEY_AGREEMENT_V1 -> {
|
||||
// (Note: In all of the following HKDF is as defined in RFC 5869, and uses the previously agreed-on hash function as the hash function,
|
||||
// the shared secret as the input keying material, no salt, and with the input parameter set to the concatenation of:
|
||||
// - the string “MATRIX_KEY_VERIFICATION_SAS”,
|
||||
// - the Matrix ID of the user who sent the m.key.verification.start message,
|
||||
// - the device ID of the device that sent the m.key.verification.start message,
|
||||
// - the Matrix ID of the user who sent the m.key.verification.accept message,
|
||||
// - he device ID of the device that sent the m.key.verification.accept message
|
||||
// - the transaction ID.
|
||||
val sasInfo = "MATRIX_KEY_VERIFICATION_SAS$userId$deviceId$otherUserId$otherDeviceId$transactionId"
|
||||
|
||||
// decimal: generate five bytes by using HKDF.
|
||||
// emoji: generate six bytes by using HKDF.
|
||||
return getSAS().generateShortCode(sasInfo, 6)
|
||||
}
|
||||
KEY_AGREEMENT_V2 -> {
|
||||
// Adds the SAS public key, and separate by |
|
||||
val sasInfo = "MATRIX_KEY_VERIFICATION_SAS|$userId|$deviceId|${getSAS().publicKey}|$otherUserId|$otherDeviceId|$otherKey|$transactionId"
|
||||
return getSAS().generateShortCode(sasInfo, 6)
|
||||
}
|
||||
else -> {
|
||||
// Protocol has been checked earlier
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onKeyVerificationMac(vMac: ValidVerificationInfoMac) {
|
||||
Timber.v("## SAS O: onKeyVerificationMac id:$transactionId")
|
||||
// There is starting to be a huge amount of state / race here :/
|
||||
if (state != VerificationTxState.OnKeyReceived
|
||||
&& state != VerificationTxState.ShortCodeReady
|
||||
&& state != VerificationTxState.ShortCodeAccepted
|
||||
&& state != VerificationTxState.KeySent
|
||||
&& state != VerificationTxState.SendingMac
|
||||
&& state != VerificationTxState.MacSent) {
|
||||
Timber.e("## SAS O: received key from invalid state $state")
|
||||
Timber.e("## SAS O: received mac from invalid state $state")
|
||||
cancel(CancelCode.UnexpectedMessage)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -611,7 +611,7 @@ internal class DefaultVerificationService @Inject constructor(
|
|||
|
||||
if (validCancelReq == null) {
|
||||
// ignore
|
||||
Timber.e("## SAS Received invalid key request")
|
||||
Timber.e("## SAS Received invalid cancelt request")
|
||||
// TODO should we cancel?
|
||||
return
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import im.vector.matrix.android.api.session.events.model.EventType
|
|||
import im.vector.matrix.android.internal.crypto.IncomingGossipingRequestManager
|
||||
import im.vector.matrix.android.internal.crypto.OutgoingGossipingRequestManager
|
||||
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
|
||||
import im.vector.matrix.android.internal.crypto.model.MXKey
|
||||
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
||||
import im.vector.matrix.android.internal.extensions.toUnsignedInt
|
||||
import im.vector.matrix.android.internal.util.withoutPrefix
|
||||
|
@ -66,8 +65,11 @@ internal abstract class SASDefaultVerificationTransaction(
|
|||
const val SAS_MAC_SHA256_LONGKDF = "hmac-sha256"
|
||||
const val SAS_MAC_SHA256 = "hkdf-hmac-sha256"
|
||||
|
||||
// Deprecated maybe removed later, use V2
|
||||
const val KEY_AGREEMENT_V1 = "curve25519"
|
||||
const val KEY_AGREEMENT_V2 = "curve25519-hkdf-sha256"
|
||||
// ordered by preferred order
|
||||
val KNOWN_AGREEMENT_PROTOCOLS = listOf(MXKey.KEY_CURVE_25519_TYPE)
|
||||
val KNOWN_AGREEMENT_PROTOCOLS = listOf(KEY_AGREEMENT_V2, KEY_AGREEMENT_V1)
|
||||
// ordered by preferred order
|
||||
val KNOWN_HASHES = listOf("sha256")
|
||||
// ordered by preferred order
|
||||
|
|
Loading…
Reference in New Issue