From e77bde2cfac45a22e020a3ed7c892365357cacd4 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 28 Jun 2016 00:10:04 +0200 Subject: [PATCH 1/2] standardize on lowercase SHA-256 hashes fdroidserver produces lowercase hashes, so its easiest to just mimic that. This makes hash comparisons easy. --- app/src/main/java/org/fdroid/fdroid/Utils.java | 2 +- app/src/main/java/org/fdroid/fdroid/data/Apk.java | 2 +- .../main/java/org/fdroid/fdroid/data/DBHelper.java | 12 +++++++++++- .../fdroid/fdroid/localrepo/LocalRepoManager.java | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/Utils.java b/app/src/main/java/org/fdroid/fdroid/Utils.java index 831ef1da2..c6bb9b571 100644 --- a/app/src/main/java/org/fdroid/fdroid/Utils.java +++ b/app/src/main/java/org/fdroid/fdroid/Utils.java @@ -386,7 +386,7 @@ public final class Utils { } byte[] mdbytes = md.digest(); - return toHexString(mdbytes); + return toHexString(mdbytes).toLowerCase(Locale.ENGLISH); } catch (IOException e) { Log.e(TAG, "Error reading \"" + apk.getAbsolutePath() + "\" to compute " + algo + " hash.", e); diff --git a/app/src/main/java/org/fdroid/fdroid/data/Apk.java b/app/src/main/java/org/fdroid/fdroid/data/Apk.java index 2dcb65273..1c74be277 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/Apk.java +++ b/app/src/main/java/org/fdroid/fdroid/data/Apk.java @@ -25,7 +25,7 @@ public class Apk extends ValueObject implements Comparable, Parcelable { public int versionCode; public int size; // Size in bytes - 0 means we don't know! public long repo; // ID of the repo it comes from - public String hash; + public String hash; // checksum of the APK, in lowercase hex public String hashType; public int minSdkVersion = SDK_VERSION_MIN_VALUE; // 0 if unknown public int targetSdkVersion = SDK_VERSION_MIN_VALUE; // 0 if unknown diff --git a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java index b352fee55..c92b32e17 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java +++ b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java @@ -120,7 +120,7 @@ class DBHelper extends SQLiteOpenHelper { + " );"; private static final String DROP_TABLE_INSTALLED_APP = "DROP TABLE " + InstalledAppTable.NAME + ";"; - private static final int DB_VERSION = 60; + private static final int DB_VERSION = 61; private final Context context; @@ -327,6 +327,16 @@ class DBHelper extends SQLiteOpenHelper { migrateAppPrimaryKeyToRowId(db, oldVersion); removeApkPackageNameColumn(db, oldVersion); addAppPrefsTable(db, oldVersion); + lowerCaseApkHashes(db, oldVersion); + } + + private void lowerCaseApkHashes(SQLiteDatabase db, int oldVersion) { + if (oldVersion >= 61) { + return; + } + Utils.debugLog(TAG, "Lowercasing all APK hashes"); + db.execSQL("UPDATE " + InstalledAppTable.NAME + " SET " + InstalledAppTable.Cols.HASH + + " = lower(" + InstalledAppTable.Cols.HASH + ")"); } private void addAppPrefsTable(SQLiteDatabase db, int oldVersion) { diff --git a/app/src/main/java/org/fdroid/fdroid/localrepo/LocalRepoManager.java b/app/src/main/java/org/fdroid/fdroid/localrepo/LocalRepoManager.java index 5cf5ca1fe..6e8db5e3d 100644 --- a/app/src/main/java/org/fdroid/fdroid/localrepo/LocalRepoManager.java +++ b/app/src/main/java/org/fdroid/fdroid/localrepo/LocalRepoManager.java @@ -470,7 +470,7 @@ public final class LocalRepoManager { private void tagHash(App app) throws IOException { serializer.startTag("", "hash"); serializer.attribute("", "type", app.installedApk.hashType); - serializer.text(app.installedApk.hash.toLowerCase(Locale.US)); + serializer.text(app.installedApk.hash); serializer.endTag("", "hash"); } } From 4907e0b2893f45baa077c9ee8e2dd26555963b29 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 28 Jun 2016 00:11:25 +0200 Subject: [PATCH 2/2] Utils.getBinaryHash() should not catch exceptions By catching the exception here and returning null, the problem is then passed on further down the line where it is harder to debug. The hash is required wherever this method is called, so this should fail immediately. #699 --- .../main/java/org/fdroid/fdroid/Utils.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/Utils.java b/app/src/main/java/org/fdroid/fdroid/Utils.java index c6bb9b571..1d66b371a 100644 --- a/app/src/main/java/org/fdroid/fdroid/Utils.java +++ b/app/src/main/java/org/fdroid/fdroid/Utils.java @@ -145,7 +145,7 @@ public final class Utils { InputStream input = null; OutputStream output = null; try { - input = new FileInputStream(inFile); + input = new FileInputStream(inFile); output = new FileOutputStream(outFile); Utils.copy(input, output); return true; @@ -372,6 +372,11 @@ public final class Utils { } } + /** + * Get the checksum hash of the file {@code apk} using the algorithm in {@code algo}. + * {@code apk} must exist on the filesystem and {@code algo} must be supported + * by this device, otherwise an {@link IllegalArgumentException} is thrown. + */ public static String getBinaryHash(File apk, String algo) { FileInputStream fis = null; try { @@ -387,13 +392,8 @@ public final class Utils { byte[] mdbytes = md.digest(); return toHexString(mdbytes).toLowerCase(Locale.ENGLISH); - } catch (IOException e) { - Log.e(TAG, "Error reading \"" + apk.getAbsolutePath() - + "\" to compute " + algo + " hash.", e); - return null; - } catch (NoSuchAlgorithmException e) { - Log.e(TAG, "Device does not support " + algo + " MessageDisgest algorithm"); - return null; + } catch (IOException | NoSuchAlgorithmException e) { + throw new IllegalArgumentException(e); } finally { closeQuietly(fis); } @@ -476,7 +476,7 @@ public final class Utils { @Override public void handleTag(boolean opening, String tag, Editable output, - XMLReader reader) { + XMLReader reader) { switch (tag) { case "ul": if (opening) { @@ -525,7 +525,7 @@ public final class Utils { String versionName = null; try { versionName = context.getPackageManager() - .getPackageInfo(context.getPackageName(), 0).versionName; + .getPackageInfo(context.getPackageName(), 0).versionName; } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Could not get client version name", e); }