From e909b6bb9d582dd2fec767410d039a0cf3189635 Mon Sep 17 00:00:00 2001 From: uberspot Date: Wed, 12 Mar 2014 18:48:17 +0200 Subject: [PATCH] change colorizing of fingerprint to use SHA1 based on apg's commit 67ffc24526 --- .../keychain/helper/OtherHelper.java | 22 +++++++++ .../keychain/ui/ViewKeyMainFragment.java | 46 +++++++++++++++---- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java index 34d90a17f..292b5bf3d 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java @@ -17,6 +17,9 @@ package org.sufficientlysecure.keychain.helper; +import java.security.DigestException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Iterator; import java.util.Set; @@ -58,4 +61,23 @@ public class OtherHelper { } } + /** + * Converts the given bytes to a unique RGB color using SHA1 algorithm + * @param bytes + * @return an integer array containing 3 numeric color representations (Red, Green, Black) + * @throws NoSuchAlgorithmException + * @throws DigestException + */ + public static int[] getRgbForData(byte[] bytes) throws NoSuchAlgorithmException, DigestException { + MessageDigest md = MessageDigest.getInstance("SHA1"); + + md.update(bytes); + byte[] digest = md.digest(); + + int[] result = {((int) digest[0] + 256) % 256, + ((int) digest[1] + 256) % 256, + ((int) digest[2] + 256) % 256}; + return result; + } + } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java index adb06a068..d223a259f 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -29,6 +29,7 @@ import android.support.v4.content.Loader; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.format.DateFormat; +import android.text.style.BackgroundColorSpan; import android.text.style.ForegroundColorSpan; import android.view.LayoutInflater; import android.view.View; @@ -40,6 +41,7 @@ import com.beardedhen.androidbootstrap.BootstrapButton; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; @@ -47,6 +49,8 @@ import org.sufficientlysecure.keychain.ui.adapter.ViewKeyKeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.ViewKeyUserIdsAdapter; import org.sufficientlysecure.keychain.util.Log; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Date; @@ -276,18 +280,40 @@ public class ViewKeyMainFragment extends Fragment implements private SpannableStringBuilder colorizeFingerprint(String fingerprint) { SpannableStringBuilder sb = new SpannableStringBuilder(fingerprint); - ForegroundColorSpan fcs = new ForegroundColorSpan(Color.BLACK); + try { + // for each 4 characters of the fingerprint + 1 space + for (int i = 0; i < fingerprint.length(); i += 5) { + int minFingLength = Math.min(i + 4, fingerprint.length()); + String fourChars = fingerprint.substring(i, minFingLength); - // for each 4 characters of the fingerprint + 1 space - for (int i = 0; i < fingerprint.length(); i += 5) { - int minFingLength = Math.min(i + 4, fingerprint.length()); - String fourChars = fingerprint.substring(i, minFingLength); + int raw = Integer.parseInt(fourChars, 16); + byte[] bytes = {(byte) ((raw >> 8) & 0xff - 128), (byte) (raw & 0xff - 128)}; + int[] color = OtherHelper.getRgbForData(bytes); - // Create a foreground color by converting the 4 fingerprint chars to an int hashcode - // and then converting that int to hex to use as a color - fcs = new ForegroundColorSpan( - Color.parseColor(String.format("#%06X", (0xFFFFFF & fourChars.hashCode())))); - sb.setSpan(fcs, i, minFingLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + // Convert rgb to brightness + int brightness = (int) (0.2126*color[0] + 0.7152*color[1] + 0.0722*color[2]); + + // Detect dark colors and invert their background to white to make them more distinguishable + if (brightness < 40) { + sb.setSpan(new BackgroundColorSpan(Color.WHITE), + i, minFingLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + + // Detect bright colors and invert their background to black to make them more distinguishable + } else if (brightness > 210) { + sb.setSpan(new BackgroundColorSpan(Color.BLACK), + i, minFingLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + } + + // Create a foreground color with the 3 digest integers as RGB + // and then converting that int to hex to use as a color + sb.setSpan(new ForegroundColorSpan(Color.rgb(color[0], color[1], color[2])), + i, minFingLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + } + } catch (Exception e) { + Log.e(Constants.TAG, "Colorization failed", e); + // if anything goes wrong, then just display the fingerprint without colour, + // instead of partially correct colour or wrong colours + return new SpannableStringBuilder(fingerprint); } return sb;