Move cipher logic out of backup and restore components

This commit is contained in:
Steve Soltys 2019-02-21 21:51:46 -05:00
parent b182e743e8
commit 9b979b3693
4 changed files with 68 additions and 21 deletions

View file

@ -0,0 +1,57 @@
package com.stevesoltys.backup.security;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
/**
* A utility class for encrypting and decrypting data using a {@link Cipher}.
*
* @author Steve Soltys
*/
public class CipherUtil {
/**
* The cipher algorithm.
*/
public static final String CIPHER_ALGORITHM = "AES/CFB/PKCS5Padding";
/**
* Encrypts the given payload using a key generated from the provided password and salt.
*
* @param payload The payload.
* @param password The password.
* @param salt The salt.
*/
public static byte[] encrypt(byte[] payload, String password, byte[] salt) throws NoSuchPaddingException,
NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, IllegalBlockSizeException,
InvalidAlgorithmParameterException, InvalidKeyException {
SecretKey secretKey = KeyGenerator.generate(password, salt);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(salt));
return cipher.doFinal(payload);
}
/**
* Decrypts the given payload using a key generated from the provided password and salt.
*
* @param payload The payload.
* @param password The password.
* @param salt The salt.
*/
public static byte[] decrypt(byte[] payload, String password, byte[] salt) throws NoSuchPaddingException,
NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, IllegalBlockSizeException,
InvalidAlgorithmParameterException, InvalidKeyException {
SecretKey secretKey = KeyGenerator.generate(password, salt);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(salt));
return cipher.doFinal(payload);
}
}

View file

@ -6,19 +6,15 @@ import android.content.pm.PackageInfo;
import android.os.ParcelFileDescriptor;
import android.util.Base64;
import android.util.Log;
import com.stevesoltys.backup.security.KeyGenerator;
import com.stevesoltys.backup.security.CipherUtil;
import com.stevesoltys.backup.transport.component.BackupComponent;
import libcore.io.IoUtils;
import org.apache.commons.io.IOUtils;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@ -262,14 +258,12 @@ public class ContentProviderBackupComponent implements BackupComponent {
try {
if (configuration.getPassword() != null && !configuration.getPassword().isEmpty()) {
SecretKey secretKey = KeyGenerator.generate(configuration.getPassword(), backupState.getSalt());
Cipher cipher = Cipher.getInstance(ContentProviderBackupConstants.CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(backupState.getSalt()));
byte[] payload = Arrays.copyOfRange(buffer, 0, dataSize);
byte[] encryptedBuffer = cipher.doFinal(payload);
outputStream.write(encryptedBuffer);
String password = configuration.getPassword();
byte[] salt = backupState.getSalt();
outputStream.write(CipherUtil.encrypt(payload, password, salt));
} else {
outputStream.write(buffer, 0, dataSize);

View file

@ -3,9 +3,7 @@ package com.stevesoltys.backup.transport.component.provider;
/**
* @author Steve Soltys
*/
public class ContentProviderBackupConstants {
static final String CIPHER_ALGORITHM = "AES/CFB/PKCS5Padding";
class ContentProviderBackupConstants {
static final String SALT_FILE_PATH = "salt";
}

View file

@ -9,6 +9,7 @@ import android.os.ParcelFileDescriptor;
import android.util.Base64;
import android.util.Log;
import com.android.internal.util.Preconditions;
import com.stevesoltys.backup.security.CipherUtil;
import com.stevesoltys.backup.security.KeyGenerator;
import com.stevesoltys.backup.transport.component.RestoreComponent;
import libcore.io.IoUtils;
@ -179,14 +180,11 @@ public class ContentProviderRestoreComponent implements RestoreComponent {
private byte[] readBackupData(ZipInputStream inputStream) throws Exception {
byte[] backupData = Streams.readFullyNoClose(inputStream);
if (configuration.getPassword() != null && !configuration.getPassword().isEmpty() &&
restoreState.getSalt() != null) {
String password = configuration.getPassword();
byte[] salt = restoreState.getSalt();
SecretKey secretKey = KeyGenerator.generate(configuration.getPassword(), restoreState.getSalt());
Cipher cipher = Cipher.getInstance(ContentProviderBackupConstants.CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(restoreState.getSalt()));
backupData = cipher.doFinal(backupData);
if (password != null && !password.isEmpty() && salt != null) {
backupData = CipherUtil.decrypt(backupData, password, salt);
}
return backupData;