Error comparing APK Signature with original Signature - android

I am trying to compare Signature verification of my APK at run time with the original Signature key "The same one!", I follow that answer so it's mustn't kill my app because it's the same one!, but it's kills the app as it's not the same one and show the toast.
That's the code
public void checkSignature(final Context context) {
try {
signatures = context.getPackageManager()
.getPackageInfo(context.getPackageName(),
PackageManager.GET_SIGNATURES).signatures;
if (signatures[0].toString() != SIGNATURE_KEY) {
// Kill the process without warning. If someone changed the certificate
// is better not to give a hint about why the app stopped working
android.os.Process.killProcess(android.os.Process.myPid());
Toast.makeText(getApplicationContext(), "Not working", Toast.LENGTH_LONG).show();
}
} catch (PackageManager.NameNotFoundException ex) {
// Must never fail, so if it does, means someone played with the apk, so kill the process
android.os.Process.killProcess(android.os.Process.myPid());
}
}
I used that code to get the Signature code at runtime more than time and every time gives me the same! "it's happens when i tap on button"
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Release", signatures[0].toCharsString());
clipboard.setPrimaryClip(clip);
So What's wrong with that code makes the comparing process not working correctly?

You compare strings with using != operator. This compares strings as links, not objects. You should use .equals().
Edited:
Also for properly compare signatures :
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signatures[0].toByteArray());
String signature = Base64.encodeToString(md.digest(), Base64.DEFAULT);
if (!signature.equals(SIGNATURE_KEY)){
//do your logic
}

Related

Facebook login suddenly stopped in my facebook integrated android app since this morning

It was working fine till last night and I havent really made any change to my app. I now see a blank white screen with "facebook" written on top after I click on the auth/login button.
Heres what I have tried so far without any positive results.
Deleted my debug.keystore->regenerated it and updated the hash on
FB(just in case it has expired).
Changed DEFAULT_AUTH_ACTIVITY_CODE
in facebook.java(in the FB SDK) to -1.
Upgraded to the latest FB
SDK.(From 3.15 to 3.19)
FYI: I am seeing this issue with an app I am currently developing.
Would really appreciate any help.
Auth fragment:
View view = inflater.inflate(R.layout.fragment_sarthi_auth, container,
false);
LoginButton authButton = (LoginButton) view
.findViewById(R.id.loginButton);
if (Session.getActiveSession().isOpened() == false) {
authButton.setReadPermissions(Arrays
.asList(extended_read_permissions));
authButton.setReadPermissions(Arrays.asList(user_data_permissions));
PackageInfo info;
try {
info = getActivity().getPackageManager().getPackageInfo(
"com.you.name", PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md;
md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
String something = new String(Base64.encode(md.digest(), 0));
// String something = new
// String(Base64.encodeBytes(md.digest()));
Log.e("hash key", something);
}
} catch (NameNotFoundException e1) {
Log.e("name not found", e1.toString());
} catch (NoSuchAlgorithmException e) {
Log.e("no such an algorithm", e.toString());
} catch (Exception e) {
Log.e("exception", e.toString());
}
}
return view;
Restarting eclipse seemed to have magically fixed the issue(no amount of clean->rebuild helped)
The app now works with 3.15 and 3.19.
With and without DEFAULT_AUTH_ACTIVITY_CODE reset to -1 (/32665)
The only persistent change I have is the updated debug hash.
One of two things then:
1)The hash key had expired( in this case I expect some sort of msg being thrown like key mismatch or something.
2)It was a temporary issue with the FB backend that got fixed( I have seen multiple unresolved instances here where they suspected the same; in which case, not cool FB :/ )

Println needs a message, help decrypt log cat

java.lang.NullPointerException: println needs a message
at android.util.Log.println_native(Native Method)
at android.util.Log.e(Log.java:230)
at android.sec.clipboard.data.ClipboardDataMgr.addData(ClipboardDataMgr.java:166)
at com.android.server.sec.InternalClipboardExService.addData(InternalClipboardExService.java:438)
at com.android.server.sec.InternalClipboardExService.access$300(InternalClipboardExService.java:75)
at com.android.server.sec.InternalClipboardExService$1.run(InternalClipboardExService.java:389)
at java.lang.Thread.run(Thread.java:1019)
Seem to be getting this quite often in my crash reporting, i can't for the life of my understand how or why or even where its happening?
The only location im performing anything on the clipboard is to copy data to it, no logging or println of any kind, not to mention i'm choosing the correct methods for the version of OS at runtime so i didnt hit any compat issues.
oh, and the devices range from 2.2 right up to 4.0 OS version
Perhaps relevant code?
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {
try {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) acc
.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("", b);
clipboard.setPrimaryClip(clip);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
try {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) acc
.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(b);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
the error means that the second parameter of Log.* can not be null, otherwise a Nenter code herePE is thrown. That could happen, for instance, when you try to print the message returned by an exception (e.getMessage()).
String message = null;
Log.i("TAG", message);
that`s kind of situation are the cause of that exception. A possible workaround
String message = null;
Log.i("TAG", ((message == null) ? "string null" : message));
Anyway, your error is not there: It is not catched by your try...catch because it is happening on another thread as you can see in your stack trace.
According to the developers of Clipper - Clipboard Manager:
SAMSUNG USERS: Some devices have a randomly occurring bug that may cause the clipboard to crash in any application. This is unfortunately out of our control. If you are experiencing this problem with your device, please contact Samsung support for assistance.
This might be also caused (later on since you said up to 4.0) by version 4.3:
Copy crash in Android 4.3 when clipboard listener attached
Also read this guy's post (seems he experienced the issue): http://forum.xda-developers.com/showthread.php?t=2097929
In summary, I do not think this error is your responsibility.

Android: Facebook login cannot call the selection fragment (Facebook api 3.0)

I followed the tutorial of Facebook to create a login function with Facebook (
enter link). When running the example, I had problem: after authorizing the app, I cannot see the welcome Text (selection fragment), it just went back the login page(splash fragment).
As my debug, the Session of Facebook seems not to be opened. Please give me some advices. Thanks
Make sure you're providing the correct Key Hash.
Take your key with this method:
static final String GetKey(Context context)
{
String KeyHash = "";
PackageInfo info;
try {
info = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures)
{
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
KeyHash = Base64.encodeToString(md.digest(), Base64.DEFAULT);
}
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return KeyHash;
}
I had a similar problem and it was because I was not overriding the onActivityResult method, after I implemented that everything worked. Since it seems that your session is failing authentication have you updated your applicationId in the manifest? I'm not sure it really matters but there is also a section on the facebook app settings page that requires the name of your activity, make sure that matches your current app.

Android FacebookSDK gives me "is misconfigured for Facebook login"

I have searched for info on the "is misconfigured for Facebook login" error message but have found no working solution. I have set Util.ENABLE_LOG to true but I get no error message in my log at all and so I can not figure out what is causing this.
I am developing with Eclipse on a Mac.
I have generated a hash with the keygen tool.
It seems Eclipse is looking for the debug.keystore in the correct location.
I simply call facebookSDK.authorize(activity, this); where activity is my main activity holding a SurfaceView that draws my UI on canvas (its a game like app), and this opens the FacebookSDK login UI just fine and I can log in but it then gives me this "misconfigured" error message (but nothing in the logs).
The callback methods "onComplete, onFacebookError, onError, onCancel" never gets called.
So, Im stuck here! Any ideas to what I can do to figure out what the problem really is?
Thank you
Søren
Ah now I know what the problem was! When you generate the hash you must use "android" as the password, I did not catch that one.
Also make sure to use this code to get correct hash, instead of command, since it gives different hashes for pc, mac and linux:
PackageInfo info;
try {
info = getPackageManager().getPackageInfo("com.myname.lolo", PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md;
md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
//String something = new String(Base64.encode(md.digest(), 0));
* String something = new String(Base64.encodeBytes(md.digest()));
Log.e("hash key", something);
}
}
catch (NameNotFoundException e1) {
Log.e("name not found", e1.toString());
}
catch (NoSuchAlgorithmException e) {
Log.e("no such an algorithm", e.toString());
}
catch (Exception e){
Log.e("exception", e.toString());
}
And u can delete this code afterwards

Detect if App is Production/Release Version from Code

I have a home made logging system in my app. Of the things that it does is preform alot of logging (to file and logcat) while in development and can be turned off completely with one varible change. For a functionality example:
static public final boolean DEVELOPMENT_VERBOSE = true;
public static void developmentLogMessage(String message) {
if (DEVELOPMENT_VERBOSE)
Log.i("com.xxx.app", message);
}
The problem (maybe more an annoyance) I have is that I must remember to set DEVELOPMENT_VERBOSE = false for release. Is there a way in code to detect when the app is finalized for release (say checking for a signed apk for example) so I can set DEVELOPMENT_VERBOSE to false programmatically?
I looked at Detect if app was downloaded from Android Market but it seems my app has a signature even before signing it for the market.
try {
PackageManager manager = context.getPackageManager();
PackageInfo appInfo = manager.getPackageInfo(
"com.xxx.app", PackageManager.GET_SIGNATURES
);
System.out.println(appInfo.signatures[0].toCharsString());
} catch (NameNotFoundException e) {
}
I was hoping the signatures array would be empty and I could key of of that. But no go.
You can use ProGuard to completely turn appropriate logs off when building a release. ProGuard can do a lot of interesting stuff. Among other things it can shrink unneeded code during the building process. For example, if you use debug log (Log.d()) during development, but want to disable it in release then you can add these lines to your proguard.cfg:
-assumenosideeffects class android.util.Log {
public static int d(...);
}
To enable ProGuard, set the property
proguard.config=proguard.cfg
to your project.properties (if you use default locations). Be noted that ProGuard will also do some other things by default so you probably should take some additional steps when releasing your project. At least you certainly want to save generated mapping.txt file. See the ProGuard guide for more details.
You can look at which certificate was used to sign the app, and act accordingly.
For example:
for (Signature sig : getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures) {
// Get some (pseudo)uniqe value:
long sigHash = Arrays.hashCode(sig.toByteArray());
if (sigHash == releaseSigHash) DEVELOPMENT_VERBOSE = false;
}
Here is what I do for Google MapView, to decide which API Key to use, which is a similar problem
for (Signature sig : getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures) {
MessageDigest m = MessageDigest.getInstance("MD5");
m.update(sig.toByteArray());
md5 = new BigInteger(1, m.digest()).toString(16);
Log.d("findApiNøgle", "md5fingerprint: "+md5);
// Jacobs debug-nøgle
if (md5.equals("5fb3a9c4a1ebb853254fa1aebc37a89b")) return "0osb1BfVdrk1u8XJFAcAD0tA5hvcMFVbzInEgNQ";
// Jacobs officielle nøgle
if (md5.equals("d9a7385fd19107698149b7576fcb8b29")) return "0osb1BfVdrk3etct3WjSX-gUUayztcGvB51EMwg";
// indsæt din egen nøgle her:
}
After some research/work we can up with a solution that checks against the singed cert.
static public boolean DEVELOPMENT_VERBOSE = false;
static private final X500Principal RELEASE_DN = new X500Principal(
"CN=aaa,OU=bbb,O=ccc,L=ddd,ST=eee,C=fff"
);
// auto disable the development logs if the apk is signed with a cert
try {
PackageManager manager = context.getPackageManager();
PackageInfo appInfo = manager.getPackageInfo("com.xxx.app",
PackageManager.GET_SIGNATURES);
Signature raw = appInfo.signatures[0];
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray()));
//DEVELOPMENT_VERBOSE = cert.getSubjectX500Principal().equals(DEBUG_DN);
if (!cert.getSubjectX500Principal().equals(RELEASE_DN))
DEVELOPMENT_VERBOSE = true;
} catch (CertificateException e) {
}
} catch (NameNotFoundException e) {
}
As long as you use the same cert from version to version of the app this will always work.

Categories

Resources