Factor getting secure random bytes into Crypto interface

This commit is contained in:
Torsten Grote 2021-09-16 15:14:51 +02:00 committed by Chirayu Desai
parent a77d927624
commit 39cb0c6443
3 changed files with 23 additions and 3 deletions

View file

@ -13,6 +13,7 @@ import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.security.GeneralSecurityException
import java.security.SecureRandom
import javax.crypto.spec.SecretKeySpec
/**
@ -33,6 +34,11 @@ import javax.crypto.spec.SecretKeySpec
*/
internal interface Crypto {
/**
* Returns a ByteArray with bytes retrieved from [SecureRandom].
*/
fun getRandomBytes(size: Int): ByteArray
/**
* Returns a [AesGcmHkdfStreaming] encrypting stream
* that gets encrypted and authenticated the given associated data.
@ -107,6 +113,11 @@ internal class CryptoImpl(
private val key: ByteArray by lazy {
deriveStreamKey(keyManager.getMainKey(), "app data key".toByteArray())
}
private val secureRandom: SecureRandom by lazy { SecureRandom() }
override fun getRandomBytes(size: Int) = ByteArray(size).apply {
secureRandom.nextBytes(this)
}
@Throws(IOException::class, GeneralSecurityException::class)
override fun newEncryptingStream(

View file

@ -22,7 +22,6 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.calyxos.backup.storage.api.StorageBackup
import java.io.IOException
import java.security.SecureRandom
internal const val WORD_NUM = 12
@ -40,8 +39,7 @@ internal class RecoveryCodeViewModel(
internal val wordList: List<CharArray> by lazy {
// we use our own entropy to not having to trust the library to use SecureRandom
val entropy = ByteArray(Mnemonics.WordCount.COUNT_12.bitLength / 8)
SecureRandom().nextBytes(entropy)
val entropy = crypto.getRandomBytes(Mnemonics.WordCount.COUNT_12.bitLength / 8)
// create the words from the entropy
Mnemonics.MnemonicCode(entropy).words
}

View file

@ -2,6 +2,9 @@ package com.stevesoltys.seedvault.crypto
import com.stevesoltys.seedvault.assertReadEquals
import com.stevesoltys.seedvault.header.HeaderReaderImpl
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
import org.hamcrest.Matchers.not
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
@ -21,6 +24,14 @@ class CryptoIntegrationTest {
private val cleartext = Random.nextBytes(Random.nextInt(1, 422300))
@Test
fun `sanity check for getRandomBytes()`() {
assertThat(crypto.getRandomBytes(42), not(equalTo(crypto.getRandomBytes(42))))
assertThat(crypto.getRandomBytes(42), not(equalTo(crypto.getRandomBytes(42))))
assertThat(crypto.getRandomBytes(42), not(equalTo(crypto.getRandomBytes(42))))
assertThat(crypto.getRandomBytes(42), not(equalTo(crypto.getRandomBytes(42))))
}
@Test
fun `decrypting encrypted cleartext works`() {
val ad = Random.nextBytes(42)