Fix issue with key importation

This commit is contained in:
Benoit Marty 2019-06-14 15:42:57 +02:00
parent 659ba34fb3
commit 191d80e5f5
6 changed files with 49 additions and 32 deletions

View File

@ -23,6 +23,7 @@ import android.os.Handler
import android.os.Looper import android.os.Looper
import android.text.TextUtils import android.text.TextUtils
import arrow.core.Try import arrow.core.Try
import com.squareup.moshi.Types
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.auth.data.Credentials
@ -810,8 +811,7 @@ internal class CryptoManager(
val adapter = MoshiProvider.providesMoshi() val adapter = MoshiProvider.providesMoshi()
.adapter(List::class.java) .adapter(List::class.java)


MXMegolmExportEncryption MXMegolmExportEncryption.encryptMegolmKeyFile(adapter.toJson(exportedSessions), password, iterationCount)
.encryptMegolmKeyFile(adapter.toJson(exportedSessions), password, iterationCount)
} }
}.foldToCallback(callback) }.foldToCallback(callback)
} }
@ -835,23 +835,23 @@ internal class CryptoManager(
Timber.v("## importRoomKeys starts") Timber.v("## importRoomKeys starts")


val t0 = System.currentTimeMillis() val t0 = System.currentTimeMillis()
val roomKeys: String = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password) val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password)

val importedSessions: List<MegolmSessionData>

val t1 = System.currentTimeMillis() val t1 = System.currentTimeMillis()


Timber.v("## importRoomKeys : decryptMegolmKeyFile done in " + (t1 - t0) + " ms") Timber.v("## importRoomKeys : decryptMegolmKeyFile done in " + (t1 - t0) + " ms")


val list = MoshiProvider.providesMoshi() val importedSessions = MoshiProvider.providesMoshi()
.adapter(List::class.java) .adapter<List<MegolmSessionData>>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java))
.fromJson(roomKeys) .fromJson(roomKeys)
importedSessions = list as List<MegolmSessionData>


val t2 = System.currentTimeMillis() val t2 = System.currentTimeMillis()


Timber.v("## importRoomKeys : JSON parsing " + (t2 - t1) + " ms") Timber.v("## importRoomKeys : JSON parsing " + (t2 - t1) + " ms")


if (importedSessions == null) {
throw Exception("Error")
}

megolmSessionDataImporter.handle(importedSessions, true, uiHandler, progressListener) megolmSessionDataImporter.handle(importedSessions, true, uiHandler, progressListener)
} }
}.foldToCallback(callback) }.foldToCallback(callback)

View File

@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.crypto


import android.text.TextUtils import android.text.TextUtils
import android.util.Base64 import android.util.Base64
import im.vector.matrix.android.internal.extensions.toUnsignedInt
import timber.log.Timber import timber.log.Timber
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.nio.charset.Charset import java.nio.charset.Charset
@ -43,16 +44,6 @@ object MXMegolmExportEncryption {
// default iteration count to export the e2e keys // default iteration count to export the e2e keys
const val DEFAULT_ITERATION_COUNT = 500000 const val DEFAULT_ITERATION_COUNT = 500000


/**
* Convert a signed byte to a int value
*
* @param bVal the byte value to convert
* @return the matched int value
*/
private fun byteToInt(bVal: Byte): Int {
return (bVal and 0xFF.toByte()).toInt()
}

/** /**
* Extract the AES key from the deriveKeys result. * Extract the AES key from the deriveKeys result.
* *
@ -108,7 +99,8 @@ object MXMegolmExportEncryption {


val salt = Arrays.copyOfRange(body, 1, 1 + 16) val salt = Arrays.copyOfRange(body, 1, 1 + 16)
val iv = Arrays.copyOfRange(body, 17, 17 + 16) val iv = Arrays.copyOfRange(body, 17, 17 + 16)
val iterations = byteToInt(body[33]) shl 24 or (byteToInt(body[34]) shl 16) or (byteToInt(body[35]) shl 8) or byteToInt(body[36]) val iterations =
(body[33].toUnsignedInt() shl 24) or (body[34].toUnsignedInt() shl 16) or (body[35].toUnsignedInt() shl 8) or body[36].toUnsignedInt()
val ciphertext = Arrays.copyOfRange(body, 37, 37 + ciphertextLength) val ciphertext = Arrays.copyOfRange(body, 37, 37 + ciphertextLength)
val hmac = Arrays.copyOfRange(body, body.size - 32, body.size) val hmac = Arrays.copyOfRange(body, body.size - 32, body.size)



View File

@ -30,6 +30,7 @@ import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
import im.vector.matrix.android.internal.crypto.model.rest.* import im.vector.matrix.android.internal.crypto.model.rest.*
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
import im.vector.matrix.android.internal.extensions.toUnsignedInt
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import org.matrix.olm.OlmSAS import org.matrix.olm.OlmSAS
@ -354,11 +355,11 @@ internal abstract class SASVerificationTransaction(
* or with the three numbers on separate lines. * or with the three numbers on separate lines.
*/ */
fun getDecimalCodeRepresentation(byteArray: ByteArray): String { fun getDecimalCodeRepresentation(byteArray: ByteArray): String {
val b0 = byteArray[0].toInt().and(0xff) //need unsigned byte val b0 = byteArray[0].toUnsignedInt() //need unsigned byte
val b1 = byteArray[1].toInt().and(0xff) //need unsigned byte val b1 = byteArray[1].toUnsignedInt() //need unsigned byte
val b2 = byteArray[2].toInt().and(0xff) //need unsigned byte val b2 = byteArray[2].toUnsignedInt() //need unsigned byte
val b3 = byteArray[3].toInt().and(0xff) //need unsigned byte val b3 = byteArray[3].toUnsignedInt() //need unsigned byte
val b4 = byteArray[4].toInt().and(0xff) //need unsigned byte val b4 = byteArray[4].toUnsignedInt() //need unsigned byte
//(B0 << 5 | B1 >> 3) + 1000 //(B0 << 5 | B1 >> 3) + 1000
val first = (b0.shl(5) or b1.shr(3)) + 1000 val first = (b0.shl(5) or b1.shr(3)) + 1000
//((B1 & 0x7) << 10 | B2 << 2 | B3 >> 6) + 1000 //((B1 & 0x7) << 10 | B2 << 2 | B3 >> 6) + 1000
@ -379,12 +380,12 @@ internal abstract class SASVerificationTransaction(
* to that number 7 emoji are selected from a list of 64 emoji (see Appendix A) * to that number 7 emoji are selected from a list of 64 emoji (see Appendix A)
*/ */
fun getEmojiCodeRepresentation(byteArray: ByteArray): List<EmojiRepresentation> { fun getEmojiCodeRepresentation(byteArray: ByteArray): List<EmojiRepresentation> {
val b0 = byteArray[0].toInt().and(0xff) val b0 = byteArray[0].toUnsignedInt()
val b1 = byteArray[1].toInt().and(0xff) val b1 = byteArray[1].toUnsignedInt()
val b2 = byteArray[2].toInt().and(0xff) val b2 = byteArray[2].toUnsignedInt()
val b3 = byteArray[3].toInt().and(0xff) val b3 = byteArray[3].toUnsignedInt()
val b4 = byteArray[4].toInt().and(0xff) val b4 = byteArray[4].toUnsignedInt()
val b5 = byteArray[5].toInt().and(0xff) val b5 = byteArray[5].toUnsignedInt()
return listOf( return listOf(
getEmojiForCode((b0 and 0xFC).shr(2)), getEmojiForCode((b0 and 0xFC).shr(2)),
getEmojiForCode((b0 and 0x3).shl(4) or (b1 and 0xF0).shr(4)), getEmojiForCode((b0 and 0x3).shl(4) or (b1 and 0xF0).shr(4)),

View File

@ -0,0 +1,22 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package im.vector.matrix.android.internal.extensions

/**
* Convert a signed byte to a int value
*/
fun Byte.toUnsignedInt() = toInt() and 0xff

View File

@ -33,7 +33,7 @@ import timber.log.Timber
class KeysImporter(private val session: Session) { class KeysImporter(private val session: Session) {


/** /**
* Export keys and return the file path with the callback * Import keys from provided Uri
*/ */
fun import(context: Context, fun import(context: Context,
uri: Uri, uri: Uri,

View File

@ -2702,6 +2702,8 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref
importButton.setOnClickListener(View.OnClickListener { importButton.setOnClickListener(View.OnClickListener {
val password = passPhraseEditText.text.toString() val password = passPhraseEditText.text.toString()


displayLoadingView()

KeysImporter(mSession) KeysImporter(mSession)
.import(requireContext(), .import(requireContext(),
uri, uri,