refactor into reusable static method for checking file hashes
This takes the APK file hash checker and turns it into a generic static utility method for checking that a given file matches a given hash. This will be needed as F-Droid handles other file types, like OBB and media.
This commit is contained in:
parent
a5e6dad9bf
commit
4c4aef5314
@ -97,6 +97,21 @@ public class Hasher {
|
|||||||
return hashCache.equals(otherHash.toLowerCase(Locale.ENGLISH));
|
return hashCache.equals(otherHash.toLowerCase(Locale.ENGLISH));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the file against the provided hash, returning whether it is a match.
|
||||||
|
*/
|
||||||
|
public static boolean isFileMatchingHash(File file, String hash, String hashType) {
|
||||||
|
if (!file.exists()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Hasher hasher = new Hasher(hashType, file);
|
||||||
|
return hasher.match(hash);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static String hex(Certificate cert) {
|
public static String hex(Certificate cert) {
|
||||||
byte[] encoded;
|
byte[] encoded;
|
||||||
try {
|
try {
|
||||||
|
@ -31,7 +31,6 @@ import org.fdroid.fdroid.data.SanitizedFile;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
|
|
||||||
public class ApkCache {
|
public class ApkCache {
|
||||||
|
|
||||||
@ -45,23 +44,16 @@ public class ApkCache {
|
|||||||
*/
|
*/
|
||||||
public static SanitizedFile copyApkFromCacheToFiles(Context context, File apkFile, Apk expectedApk)
|
public static SanitizedFile copyApkFromCacheToFiles(Context context, File apkFile, Apk expectedApk)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
SanitizedFile sanitizedApkFile = null;
|
SanitizedFile sanitizedApkFile = SanitizedFile.knownSanitized(
|
||||||
|
|
||||||
try {
|
|
||||||
sanitizedApkFile = SanitizedFile.knownSanitized(
|
|
||||||
File.createTempFile("install-", ".apk", context.getFilesDir()));
|
File.createTempFile("install-", ".apk", context.getFilesDir()));
|
||||||
FileUtils.copyFile(apkFile, sanitizedApkFile);
|
FileUtils.copyFile(apkFile, sanitizedApkFile);
|
||||||
|
|
||||||
// verify copied file's hash with expected hash from Apk class
|
// verify copied file's hash with expected hash from Apk class
|
||||||
if (!verifyApkFile(sanitizedApkFile, expectedApk.hash, expectedApk.hashType)) {
|
if (!Hasher.isFileMatchingHash(sanitizedApkFile, expectedApk.hash, expectedApk.hashType)) {
|
||||||
FileUtils.deleteQuietly(apkFile);
|
FileUtils.deleteQuietly(apkFile);
|
||||||
throw new IOException(apkFile + " failed to verify!");
|
throw new IOException(apkFile + " failed to verify!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return sanitizedApkFile;
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
|
||||||
// 20 minutes the start of the install process, delete the file
|
// 20 minutes the start of the install process, delete the file
|
||||||
final File apkToDelete = sanitizedApkFile;
|
final File apkToDelete = sanitizedApkFile;
|
||||||
new Thread() {
|
new Thread() {
|
||||||
@ -76,19 +68,8 @@ public class ApkCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return sanitizedApkFile;
|
||||||
* Checks the APK file against the provided hash, returning whether it is a match.
|
|
||||||
*/
|
|
||||||
private static boolean verifyApkFile(File apkFile, String hash, String hashType)
|
|
||||||
throws NoSuchAlgorithmException {
|
|
||||||
if (!apkFile.exists()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Hasher hasher = new Hasher(hashType, apkFile);
|
|
||||||
return hasher.match(hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,19 +89,15 @@ public class ApkCache {
|
|||||||
* Bails out if the file sizes don't match to prevent having to do the work of hashing the file.
|
* Bails out if the file sizes don't match to prevent having to do the work of hashing the file.
|
||||||
*/
|
*/
|
||||||
public static boolean apkIsCached(File apkFile, Apk apkToCheck) {
|
public static boolean apkIsCached(File apkFile, Apk apkToCheck) {
|
||||||
try {
|
|
||||||
return apkFile.length() == apkToCheck.size &&
|
return apkFile.length() == apkToCheck.size &&
|
||||||
verifyApkFile(apkFile, apkToCheck.hash, apkToCheck.hashType);
|
Hasher.isFileMatchingHash(apkFile, apkToCheck.hash, apkToCheck.hashType);
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This location is only for caching, do not install directly from this location
|
* This location is only for caching, do not install directly from this location
|
||||||
* because if the file is on the External Storage, any other app could swap out
|
* because if the file is on the External Storage, any other app could swap out
|
||||||
* the APK while the install was in process, allowing malware to install things.
|
* the APK while the install was in process, allowing malware to install things.
|
||||||
* Using {@link Installer#installPackage(Uri, Uri, Apk)}
|
* Using {@link Installer#installPackage(Uri, Uri)}
|
||||||
* is fine since that does the right thing.
|
* is fine since that does the right thing.
|
||||||
*/
|
*/
|
||||||
public static File getApkCacheDir(Context context) {
|
public static File getApkCacheDir(Context context) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user