Provide correct version to associated data
This commit is contained in:
parent
e7a8ad50e8
commit
0aee5cc2aa
4 changed files with 10 additions and 9 deletions
|
@ -1,7 +1,7 @@
|
||||||
package org.calyxos.backup.storage.crypto
|
package org.calyxos.backup.storage.crypto
|
||||||
|
|
||||||
import com.google.crypto.tink.subtle.AesGcmHkdfStreaming
|
import com.google.crypto.tink.subtle.AesGcmHkdfStreaming
|
||||||
import org.calyxos.backup.storage.backup.Backup
|
import org.calyxos.backup.storage.backup.Backup.Companion.VERSION
|
||||||
import org.calyxos.backup.storage.crypto.Hkdf.ALGORITHM_HMAC
|
import org.calyxos.backup.storage.crypto.Hkdf.ALGORITHM_HMAC
|
||||||
import org.calyxos.backup.storage.crypto.Hkdf.KEY_SIZE_BYTES
|
import org.calyxos.backup.storage.crypto.Hkdf.KEY_SIZE_BYTES
|
||||||
import org.calyxos.backup.storage.toByteArrayFromHex
|
import org.calyxos.backup.storage.toByteArrayFromHex
|
||||||
|
@ -29,16 +29,16 @@ public object StreamCrypto {
|
||||||
outLengthBytes = KEY_SIZE_BYTES
|
outLengthBytes = KEY_SIZE_BYTES
|
||||||
)
|
)
|
||||||
|
|
||||||
internal fun getAssociatedDataForChunk(chunkId: String): ByteArray =
|
internal fun getAssociatedDataForChunk(chunkId: String, version: Byte = VERSION): ByteArray =
|
||||||
ByteBuffer.allocate(2 + KEY_SIZE_BYTES)
|
ByteBuffer.allocate(2 + KEY_SIZE_BYTES)
|
||||||
.put(Backup.VERSION)
|
.put(version)
|
||||||
.put(TYPE_CHUNK) // type ID for chunks
|
.put(TYPE_CHUNK) // type ID for chunks
|
||||||
.put(chunkId.toByteArrayFromHex().apply { check(size == KEY_SIZE_BYTES) })
|
.put(chunkId.toByteArrayFromHex().apply { check(size == KEY_SIZE_BYTES) })
|
||||||
.array()
|
.array()
|
||||||
|
|
||||||
internal fun getAssociatedDataForSnapshot(timestamp: Long): ByteArray =
|
internal fun getAssociatedDataForSnapshot(timestamp: Long, version: Byte = VERSION): ByteArray =
|
||||||
ByteBuffer.allocate(2 + 8)
|
ByteBuffer.allocate(2 + 8)
|
||||||
.put(Backup.VERSION)
|
.put(version)
|
||||||
.put(TYPE_SNAPSHOT) // type ID for chunks
|
.put(TYPE_SNAPSHOT) // type ID for chunks
|
||||||
.put(timestamp.toByteArray())
|
.put(timestamp.toByteArray())
|
||||||
.array()
|
.array()
|
||||||
|
|
|
@ -16,8 +16,8 @@ internal class SnapshotRetriever(
|
||||||
@Throws(IOException::class, GeneralSecurityException::class)
|
@Throws(IOException::class, GeneralSecurityException::class)
|
||||||
suspend fun getSnapshot(streamKey: ByteArray, timestamp: Long): BackupSnapshot {
|
suspend fun getSnapshot(streamKey: ByteArray, timestamp: Long): BackupSnapshot {
|
||||||
return storagePlugin.getBackupSnapshotInputStream(timestamp).use { inputStream ->
|
return storagePlugin.getBackupSnapshotInputStream(timestamp).use { inputStream ->
|
||||||
inputStream.readVersion()
|
val version = inputStream.readVersion()
|
||||||
val ad = streamCrypto.getAssociatedDataForSnapshot(timestamp)
|
val ad = streamCrypto.getAssociatedDataForSnapshot(timestamp, version.toByte())
|
||||||
streamCrypto.newDecryptingStream(streamKey, inputStream, ad).use { decryptedStream ->
|
streamCrypto.newDecryptingStream(streamKey, inputStream, ad).use { decryptedStream ->
|
||||||
BackupSnapshot.parseFrom(decryptedStream)
|
BackupSnapshot.parseFrom(decryptedStream)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ internal abstract class AbstractChunkRestore(
|
||||||
) {
|
) {
|
||||||
storagePlugin.getChunkInputStream(chunkId).use { inputStream ->
|
storagePlugin.getChunkInputStream(chunkId).use { inputStream ->
|
||||||
inputStream.readVersion(version)
|
inputStream.readVersion(version)
|
||||||
val ad = streamCrypto.getAssociatedDataForChunk(chunkId)
|
val ad = streamCrypto.getAssociatedDataForChunk(chunkId, version.toByte())
|
||||||
streamCrypto.newDecryptingStream(streamKey, inputStream, ad).use { decryptedStream ->
|
streamCrypto.newDecryptingStream(streamKey, inputStream, ad).use { decryptedStream ->
|
||||||
streamReader(decryptedStream)
|
streamReader(decryptedStream)
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ internal class Restore(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, GeneralSecurityException::class)
|
@Throws(IOException::class, GeneralSecurityException::class)
|
||||||
internal fun InputStream.readVersion(expectedVersion: Int? = null) {
|
internal fun InputStream.readVersion(expectedVersion: Int? = null): Int {
|
||||||
val version = read()
|
val version = read()
|
||||||
if (version == -1) throw IOException()
|
if (version == -1) throw IOException()
|
||||||
if (expectedVersion != null && version != expectedVersion) {
|
if (expectedVersion != null && version != expectedVersion) {
|
||||||
|
@ -126,4 +126,5 @@ internal fun InputStream.readVersion(expectedVersion: Int? = null) {
|
||||||
// TODO maybe throw a different exception here and tell the user?
|
// TODO maybe throw a different exception here and tell the user?
|
||||||
throw IOException()
|
throw IOException()
|
||||||
}
|
}
|
||||||
|
return version
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue