More cleanup/code lisibility

This commit is contained in:
Benoit Marty 2020-02-14 20:50:21 +01:00
parent 7ddea99fc6
commit 2d6f57e214
5 changed files with 61 additions and 65 deletions

View File

@ -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?

View File

@ -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")

View File

@ -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>)
}

View File

@ -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 {

View File

@ -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 {
// decrypt from recovery key
withOlmDecryption { olmPkDecryption ->
olmPkDecryption.setPrivateKey(keySpec.privateKey)
olmPkDecryption.decrypt(OlmPkMessage()
.apply {
mCipherText = secretContent.ciphertext
mEphemeralKey = secretContent.ephemeral
mMac = secretContent.mac
})
} catch (failure: Throwable) {
throw failure
} finally {
decryption.releaseDecryption()
}
)
}
}.foldToCallback(callback)
}