forked from GitHub-Mirror/riotX-android
Fix issue with key importation
This commit is contained in:
parent
659ba34fb3
commit
191d80e5f5
@ -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)
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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)),
|
||||||
|
@ -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
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user