Merge branch 'encryption-provider-split' into 'master'

Encryption provider split.

See merge request videostreaming/grayjay!2
This commit is contained in:
Koen 2023-11-08 15:06:29 +00:00
commit 00e40e8cd6
5 changed files with 90 additions and 32 deletions

View file

@ -36,23 +36,6 @@ class EncryptionProviderTests {
assertArrayEquals(bytes, decrypted);
}
@Test
fun testEncryptDecryptBytesPassword() {
val encryptionProvider = EncryptionProvider.instance
val bytes = "This is a test string.".toByteArray();
val password = "1234".padStart(32, '9');
// Encrypt the plaintext
val ciphertext = encryptionProvider.encrypt(bytes, password)
// Decrypt the ciphertext
val decrypted = encryptionProvider.decrypt(ciphertext, password)
// The decrypted string should be equal to the original plaintext
assertArrayEquals(bytes, decrypted);
}
private fun assertArrayEquals(a: ByteArray, b: ByteArray) {
assertEquals(a.size, b.size);
for(i in 0 until a.size) {

View file

@ -0,0 +1,31 @@
package com.futo.platformplayer
import com.futo.platformplayer.encryption.EncryptionProvider
import com.futo.platformplayer.encryption.PasswordEncryptionProvider
import junit.framework.TestCase.assertEquals
import org.junit.Test
class PasswordEncryptionProviderTests {
@Test
fun testEncryptDecryptBytesPassword() {
val password = "1234".padStart(32, '9');
val encryptionProvider = PasswordEncryptionProvider(password);
val bytes = "This is a test string.".toByteArray();
// Encrypt the plaintext
val ciphertext = encryptionProvider.encrypt(bytes)
// Decrypt the ciphertext
val decrypted = encryptionProvider.decrypt(ciphertext)
// The decrypted string should be equal to the original plaintext
assertArrayEquals(bytes, decrypted);
}
private fun assertArrayEquals(a: ByteArray, b: ByteArray) {
assertEquals(a.size, b.size);
for(i in 0 until a.size) {
assertEquals(a[i], b[i]);
}
}
}

View file

@ -3,6 +3,7 @@ package com.futo.platformplayer.encryption
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import android.util.Base64
import com.futo.polycentric.core.EncryptionProvider
import java.security.Key
import java.security.KeyStore
import javax.crypto.Cipher
@ -25,35 +26,32 @@ class EncryptionProvider {
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setRandomizedEncryptionRequired(false)
.build());
keyGenerator.generateKey();
}
}
fun encrypt(decrypted: String, password: String? = null): String {
val encodedBytes = encrypt(decrypted.toByteArray(), password);
fun encrypt(decrypted: String): String {
val encodedBytes = encrypt(decrypted.toByteArray());
val encrypted = Base64.encodeToString(encodedBytes, Base64.DEFAULT);
return encrypted;
}
fun encrypt(decrypted: ByteArray, password: String? = null): ByteArray {
fun encrypt(decrypted: ByteArray): ByteArray {
val c: Cipher = Cipher.getInstance(AES_MODE);
val keyToUse = if(password == null) secretKey else SecretKeySpec(password.toByteArray(), "AES");
c.init(Cipher.ENCRYPT_MODE, keyToUse, GCMParameterSpec(128, FIXED_IV));
c.init(Cipher.ENCRYPT_MODE, secretKey, GCMParameterSpec(128, FIXED_IV));
val encodedBytes: ByteArray = c.doFinal(decrypted);
return encodedBytes;
}
fun decrypt(encrypted: String, password: String? = null): String {
fun decrypt(encrypted: String): String {
val c = Cipher.getInstance(AES_MODE);
val keyToUse = if(password == null) secretKey else SecretKeySpec(password.toByteArray(), "AES");
c.init(Cipher.DECRYPT_MODE, keyToUse, GCMParameterSpec(128, FIXED_IV));
c.init(Cipher.DECRYPT_MODE, secretKey, GCMParameterSpec(128, FIXED_IV));
val decrypted = String(c.doFinal(Base64.decode(encrypted, Base64.DEFAULT)));
return decrypted;
}
fun decrypt(encrypted: ByteArray, password: String? = null): ByteArray {
fun decrypt(encrypted: ByteArray): ByteArray {
val c = Cipher.getInstance(AES_MODE);
val keyToUse = if(password == null) secretKey else SecretKeySpec(password.toByteArray(), "AES");
c.init(Cipher.DECRYPT_MODE, keyToUse, GCMParameterSpec(128, FIXED_IV));
c.init(Cipher.DECRYPT_MODE, secretKey, GCMParameterSpec(128, FIXED_IV));
return c.doFinal(encrypted);
}

View file

@ -0,0 +1,45 @@
package com.futo.platformplayer.encryption
import android.util.Base64
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec
class PasswordEncryptionProvider {
private val _key: SecretKeySpec;
constructor(password: String) {
_key = SecretKeySpec(password.toByteArray(), "AES");
}
fun encrypt(decrypted: String): String {
val encodedBytes = encrypt(decrypted.toByteArray());
val encrypted = Base64.encodeToString(encodedBytes, Base64.DEFAULT);
return encrypted;
}
fun encrypt(decrypted: ByteArray): ByteArray {
val c: Cipher = Cipher.getInstance(AES_MODE);
c.init(Cipher.ENCRYPT_MODE, _key, GCMParameterSpec(128, FIXED_IV));
val encodedBytes: ByteArray = c.doFinal(decrypted);
return encodedBytes;
}
fun decrypt(encrypted: String): String {
val c = Cipher.getInstance(AES_MODE);
c.init(Cipher.DECRYPT_MODE, _key, GCMParameterSpec(128, FIXED_IV));
val decrypted = String(c.doFinal(Base64.decode(encrypted, Base64.DEFAULT)));
return decrypted;
}
fun decrypt(encrypted: ByteArray): ByteArray {
val c = Cipher.getInstance(AES_MODE);
c.init(Cipher.DECRYPT_MODE, _key, GCMParameterSpec(128, FIXED_IV));
return c.doFinal(encrypted);
}
companion object {
private val FIXED_IV = byteArrayOf(12, 43, 127, 2, 99, 22, 6, 78, 24, 53, 8, 101);
private const val AES_MODE = "AES/GCM/NoPadding";
private val TAG = "PasswordEncryptionProvider";
}
}

View file

@ -20,6 +20,7 @@ import com.futo.platformplayer.api.media.models.video.SerializedPlatformVideo
import com.futo.platformplayer.copyTo
import com.futo.platformplayer.copyToOutputStream
import com.futo.platformplayer.encryption.EncryptionProvider
import com.futo.platformplayer.encryption.PasswordEncryptionProvider
import com.futo.platformplayer.getInputStream
import com.futo.platformplayer.getNowDiffHours
import com.futo.platformplayer.getOutputStream
@ -106,7 +107,7 @@ class StateBackup {
val data = export();
val zip = data.asZip();
val encryptedZip = EncryptionProvider.instance.encrypt(zip, getAutomaticBackupPassword());
val encryptedZip = PasswordEncryptionProvider(getAutomaticBackupPassword()).encrypt(zip);
if(!Settings.instance.storage.isStorageMainValid(context)) {
StateApp.instance.scopeOrNull?.launch(Dispatchers.Main) {
@ -151,7 +152,7 @@ class StateBackup {
throw IllegalStateException("Backup file does not exist");
val backupBytesEncrypted = backupFiles.first!!.readBytes(context) ?: throw IllegalStateException("Could not read stream of [${backupFiles.first?.uri}]");
val backupBytes = EncryptionProvider.instance.decrypt(backupBytesEncrypted, getAutomaticBackupPassword(password));
val backupBytes = PasswordEncryptionProvider(getAutomaticBackupPassword(password)).decrypt(backupBytesEncrypted);
importZipBytes(context, scope, backupBytes);
Logger.i(TAG, "Finished AutoBackup restore");
}
@ -179,7 +180,7 @@ class StateBackup {
throw ex;
val backupBytesEncrypted = backupFiles.second!!.readBytes(context) ?: throw IllegalStateException("Could not read stream of [${backupFiles.second?.uri}]");
val backupBytes = EncryptionProvider.instance.decrypt(backupBytesEncrypted, getAutomaticBackupPassword(password));
val backupBytes = PasswordEncryptionProvider(getAutomaticBackupPassword(password)).decrypt(backupBytesEncrypted);
importZipBytes(context, scope, backupBytes);
Logger.i(TAG, "Finished AutoBackup restore");
}