More cleanup/code lisibility
This commit is contained in:
parent
7ddea99fc6
commit
2d6f57e214
|
@ -54,25 +54,28 @@ data class SecretStorageKeyContent(
|
|||
/** Currently support m.secret_storage.v1.curve25519-aes-sha2 */
|
||||
@Json(name = "algorithm") val algorithm: String? = null,
|
||||
@Json(name = "name") val name: String? = null,
|
||||
@Json(name = "passphrase") val passphrase: SSSSPassphrase? = null,
|
||||
@Json(name = "passphrase") val passphrase: SsssPassphrase? = null,
|
||||
@Json(name = "pubkey") val publicKey: String? = null,
|
||||
@Json(name = "signatures")
|
||||
var signatures: Map<String, Map<String, String>>? = null
|
||||
@Json(name = "signatures") val signatures: Map<String, Map<String, String>>? = null
|
||||
) {
|
||||
|
||||
private fun signalableJSONDictionary(): Map<String, Any> {
|
||||
val map = HashMap<String, Any>()
|
||||
algorithm?.let { map["algorithm"] = it }
|
||||
name?.let { map["name"] = it }
|
||||
publicKey?.let { map["pubkey"] = it }
|
||||
passphrase?.let { ssspp ->
|
||||
map["passphrase"] = mapOf(
|
||||
"algorithm" to ssspp.algorithm,
|
||||
"iterations" to ssspp.salt,
|
||||
"salt" to ssspp.salt
|
||||
)
|
||||
return mutableMapOf<String, Any>().apply {
|
||||
algorithm
|
||||
?.let { this["algorithm"] = it }
|
||||
name
|
||||
?.let { this["name"] = it }
|
||||
publicKey
|
||||
?.let { this["pubkey"] = it }
|
||||
passphrase
|
||||
?.let { ssssPassphrase ->
|
||||
this["passphrase"] = mapOf(
|
||||
"algorithm" to ssssPassphrase.algorithm,
|
||||
"iterations" to ssssPassphrase.salt,
|
||||
"salt" to ssssPassphrase.salt
|
||||
)
|
||||
}
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
fun canonicalSignable(): String {
|
||||
|
@ -93,7 +96,7 @@ data class SecretStorageKeyContent(
|
|||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class SSSSPassphrase(
|
||||
data class SsssPassphrase(
|
||||
@Json(name = "algorithm") val algorithm: String?,
|
||||
@Json(name = "iterations") val iterations: Int,
|
||||
@Json(name = "salt") val salt: String?
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package im.vector.matrix.android.api.session.securestorage
|
||||
|
||||
sealed class SharedSecretStorageError(message: String?) : Throwable(message) {
|
||||
|
||||
data class UnknownSecret(val secretName: String) : SharedSecretStorageError("Unknown Secret $secretName")
|
||||
data class UnknownKey(val keyId: String) : SharedSecretStorageError("Unknown key $keyId")
|
||||
data class UnknownAlgorithm(val keyId: String) : SharedSecretStorageError("Unknown algorithm $keyId")
|
||||
|
|
|
@ -108,5 +108,5 @@ interface SharedSecretStorageService {
|
|||
*
|
||||
*/
|
||||
@Throws
|
||||
fun getSecret(name: String, keyId: String?, secretKey: SSSSKeySpec, callback: MatrixCallback<String>)
|
||||
fun getSecret(name: String, keyId: String?, secretKey: SsssKeySpec, callback: MatrixCallback<String>)
|
||||
}
|
||||
|
|
|
@ -21,11 +21,11 @@ import im.vector.matrix.android.internal.crypto.keysbackup.deriveKey
|
|||
import im.vector.matrix.android.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey
|
||||
|
||||
/** Tag class */
|
||||
interface SSSSKeySpec
|
||||
interface SsssKeySpec
|
||||
|
||||
data class Curve25519AesSha2KeySpec(
|
||||
val privateKey: ByteArray
|
||||
) : SSSSKeySpec {
|
||||
) : SsssKeySpec {
|
||||
|
||||
companion object {
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@ import im.vector.matrix.android.api.session.securestorage.EncryptedSecretContent
|
|||
import im.vector.matrix.android.api.session.securestorage.KeyInfo
|
||||
import im.vector.matrix.android.api.session.securestorage.KeyInfoResult
|
||||
import im.vector.matrix.android.api.session.securestorage.KeySigner
|
||||
import im.vector.matrix.android.api.session.securestorage.SSSSKeySpec
|
||||
import im.vector.matrix.android.api.session.securestorage.SSSSPassphrase
|
||||
import im.vector.matrix.android.api.session.securestorage.SsssKeySpec
|
||||
import im.vector.matrix.android.api.session.securestorage.SsssPassphrase
|
||||
import im.vector.matrix.android.api.session.securestorage.SecretStorageKeyContent
|
||||
import im.vector.matrix.android.api.session.securestorage.SharedSecretStorageError
|
||||
import im.vector.matrix.android.api.session.securestorage.SharedSecretStorageService
|
||||
|
@ -34,15 +34,21 @@ import im.vector.matrix.android.api.session.securestorage.SsssKeyCreationInfo
|
|||
import im.vector.matrix.android.internal.crypto.SSSS_ALGORITHM_CURVE25519_AES_SHA2
|
||||
import im.vector.matrix.android.internal.crypto.keysbackup.generatePrivateKeyWithPassword
|
||||
import im.vector.matrix.android.internal.crypto.keysbackup.util.computeRecoveryKey
|
||||
import im.vector.matrix.android.internal.crypto.tools.withOlmDecryption
|
||||
import im.vector.matrix.android.internal.crypto.tools.withOlmEncryption
|
||||
import im.vector.matrix.android.internal.extensions.foldToCallback
|
||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.olm.OlmPkDecryption
|
||||
import org.matrix.olm.OlmPkMessage
|
||||
import javax.inject.Inject
|
||||
|
||||
private data class Key(
|
||||
val publicKey: String,
|
||||
@Suppress("ArrayInDataClass")
|
||||
val privateKey: ByteArray
|
||||
)
|
||||
|
||||
internal class DefaultSharedSecretStorageService @Inject constructor(
|
||||
private val accountDataService: AccountDataService,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
|
@ -54,25 +60,22 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
|||
keySigner: KeySigner,
|
||||
callback: MatrixCallback<SsssKeyCreationInfo>) {
|
||||
cryptoCoroutineScope.launch(coroutineDispatchers.main) {
|
||||
val pkDecryption = OlmPkDecryption()
|
||||
val pubKey: String
|
||||
val privateKey: ByteArray
|
||||
try {
|
||||
pubKey = pkDecryption.generateKey()
|
||||
privateKey = pkDecryption.privateKey()
|
||||
} catch (failure: Throwable) {
|
||||
return@launch Unit.also {
|
||||
callback.onFailure(failure)
|
||||
val key = try {
|
||||
withOlmDecryption { olmPkDecryption ->
|
||||
val pubKey = olmPkDecryption.generateKey()
|
||||
val privateKey = olmPkDecryption.privateKey()
|
||||
Key(pubKey, privateKey)
|
||||
}
|
||||
} finally {
|
||||
pkDecryption.releaseDecryption()
|
||||
} catch (failure: Throwable) {
|
||||
callback.onFailure(failure)
|
||||
return@launch
|
||||
}
|
||||
|
||||
val storageKeyContent = SecretStorageKeyContent(
|
||||
name = keyName,
|
||||
algorithm = SSSS_ALGORITHM_CURVE25519_AES_SHA2,
|
||||
passphrase = null,
|
||||
publicKey = pubKey
|
||||
publicKey = key.publicKey
|
||||
)
|
||||
|
||||
val signedContent = keySigner.sign(storageKeyContent.canonicalSignable())?.let {
|
||||
|
@ -93,7 +96,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
|||
callback.onSuccess(SsssKeyCreationInfo(
|
||||
keyId = keyId,
|
||||
content = storageKeyContent,
|
||||
recoveryKey = computeRecoveryKey(privateKey)
|
||||
recoveryKey = computeRecoveryKey(key.privateKey)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -110,21 +113,18 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
|||
cryptoCoroutineScope.launch(coroutineDispatchers.main) {
|
||||
val privatePart = generatePrivateKeyWithPassword(passphrase, progressListener)
|
||||
|
||||
val pkDecryption = OlmPkDecryption()
|
||||
val pubKey: String
|
||||
try {
|
||||
pubKey = pkDecryption.setPrivateKey(privatePart.privateKey)
|
||||
} catch (failure: Throwable) {
|
||||
return@launch Unit.also {
|
||||
callback.onFailure(failure)
|
||||
val pubKey = try {
|
||||
withOlmDecryption { olmPkDecryption ->
|
||||
olmPkDecryption.setPrivateKey(privatePart.privateKey)
|
||||
}
|
||||
} finally {
|
||||
pkDecryption.releaseDecryption()
|
||||
} catch (failure: Throwable) {
|
||||
callback.onFailure(failure)
|
||||
return@launch
|
||||
}
|
||||
|
||||
val storageKeyContent = SecretStorageKeyContent(
|
||||
algorithm = SSSS_ALGORITHM_CURVE25519_AES_SHA2,
|
||||
passphrase = SSSSPassphrase(algorithm = "m.pbkdf2", iterations = privatePart.iterations, salt = privatePart.salt),
|
||||
passphrase = SsssPassphrase(algorithm = "m.pbkdf2", iterations = privatePart.iterations, salt = privatePart.salt),
|
||||
publicKey = pubKey
|
||||
)
|
||||
|
||||
|
@ -192,10 +192,9 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
|||
cryptoCoroutineScope.launch(coroutineDispatchers.main) {
|
||||
val encryptedContents = HashMap<String, EncryptedSecretContent>()
|
||||
try {
|
||||
if (keys == null || keys.isEmpty()) {
|
||||
if (keys.isNullOrEmpty()) {
|
||||
// use default key
|
||||
val key = getDefaultKey()
|
||||
when (key) {
|
||||
when (val key = getDefaultKey()) {
|
||||
is KeyInfoResult.Success -> {
|
||||
if (key.keyInfo.content.algorithm == SSSS_ALGORITHM_CURVE25519_AES_SHA2) {
|
||||
val encryptedResult = withOlmEncryption { olmEncrypt ->
|
||||
|
@ -222,8 +221,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
|||
keys.forEach {
|
||||
val keyId = it
|
||||
// encrypt the content
|
||||
val key = getKey(keyId)
|
||||
when (key) {
|
||||
when (val key = getKey(keyId)) {
|
||||
is KeyInfoResult.Success -> {
|
||||
if (key.keyInfo.content.algorithm == SSSS_ALGORITHM_CURVE25519_AES_SHA2) {
|
||||
val encryptedResult = withOlmEncryption { olmEncrypt ->
|
||||
|
@ -279,7 +277,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
|||
return results
|
||||
}
|
||||
|
||||
override fun getSecret(name: String, keyId: String?, secretKey: SSSSKeySpec, callback: MatrixCallback<String>) {
|
||||
override fun getSecret(name: String, keyId: String?, secretKey: SsssKeySpec, callback: MatrixCallback<String>) {
|
||||
val accountData = accountDataService.getAccountDataEvent(name) ?: return Unit.also {
|
||||
callback.onFailure(SharedSecretStorageError.UnknownSecret(name))
|
||||
}
|
||||
|
@ -306,20 +304,16 @@ internal class DefaultSharedSecretStorageService @Inject constructor(
|
|||
}
|
||||
cryptoCoroutineScope.launch(coroutineDispatchers.main) {
|
||||
kotlin.runCatching {
|
||||
// decryt from recovery key
|
||||
val keyBytes = keySpec.privateKey
|
||||
val decryption = OlmPkDecryption()
|
||||
try {
|
||||
decryption.setPrivateKey(keyBytes)
|
||||
decryption.decrypt(OlmPkMessage().apply {
|
||||
mCipherText = secretContent.ciphertext
|
||||
mEphemeralKey = secretContent.ephemeral
|
||||
mMac = secretContent.mac
|
||||
})
|
||||
} catch (failure: Throwable) {
|
||||
throw failure
|
||||
} finally {
|
||||
decryption.releaseDecryption()
|
||||
// decrypt from recovery key
|
||||
withOlmDecryption { olmPkDecryption ->
|
||||
olmPkDecryption.setPrivateKey(keySpec.privateKey)
|
||||
olmPkDecryption.decrypt(OlmPkMessage()
|
||||
.apply {
|
||||
mCipherText = secretContent.ciphertext
|
||||
mEphemeralKey = secretContent.ephemeral
|
||||
mMac = secretContent.mac
|
||||
}
|
||||
)
|
||||
}
|
||||
}.foldToCallback(callback)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue