This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SecurityWard { | |
private static final String CLASS_TAG = "SecurityWard"; | |
private static final String CERTIFICATE_SHA1 = ""; | |
/** | |
* Detect if Google Play Store was the installer | |
* @param context Current context | |
* @return true if was installed with Google Play Store | |
*/ | |
public static boolean checkGooglePlayStore (Context context) { | |
String installerPackageName = context.getPackageManager().getInstallerPackageName(context.getPackageName()); | |
return installerPackageName != null && installerPackageName.startsWith("com.google.android"); | |
} | |
/** | |
* Detect if it runs on an emulator | |
* @return true if the app it's running on a emulator | |
*/ | |
public static boolean isEmulator(){ | |
try { | |
Class systemPropetyClazz = Class.forName("android.os.SystemProperties"); | |
boolean kernelQemu = getProperty(systemPropetyClazz, "ro.kernel.qemu").length() > 0 ; | |
boolean hardwareGoldfish = getProperty(systemPropetyClazz, "ro.hardware").equals("goldfish"); | |
boolean modelSdk = getProperty(systemPropetyClazz, "ro.product.model").equals("sdk"); | |
if (kernelQemu || hardwareGoldfish || modelSdk){ | |
return true; | |
} | |
} catch (Exception e) { | |
LogManager.log(LogManager.ERROR,CLASS_TAG,"isEmulator",e.toString()); | |
} | |
return false; | |
} | |
private static String getProperty (Class clazz, String propertyName) throws Exception { | |
return (String) clazz.getMethod("get", new Class[] {String.class}).invoke(clazz, new Object[] {propertyName}); | |
} | |
/** | |
* Detect if the app has the debuggable flag enabled | |
* @param context Current context | |
* @return true if it's enabled | |
*/ | |
public static boolean isDebuggable (Context context){ | |
return (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; | |
} | |
/** | |
* Detects if the current signature matches the original one | |
* @param context Current context | |
* @return true if the signatures match each other | |
*/ | |
public static boolean validateAppSignature(Context context) { | |
try { | |
//get the signature from the package manager | |
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); | |
Signature[] appsSignatures = packageInfo.signatures; | |
//this sample only checks the first certificate | |
for (Signature signature : appsSignatures){ | |
byte[] singnatureBytes = signature.toByteArray(); | |
//calc sha1 in hex | |
String currentSignature = calcSHA1(singnatureBytes); | |
//compare signatures | |
return CERTIFICATE_SHA1.equalsIgnoreCase(currentSignature); | |
} | |
}catch (Exception e){ | |
LogManager.log(LogManager.ERROR,CLASS_TAG,"validateAppSignature",e.toString()); | |
} | |
return false; | |
} | |
private static String calcSHA1(byte[] signature) throws NoSuchAlgorithmException { | |
MessageDigest digest = MessageDigest.getInstance("SHA1"); | |
digest.update(signature); | |
byte[] signatureHash = digest.digest(); | |
return bytesToHex(signatureHash); | |
} | |
public static String bytesToHex (byte[] bytes){ | |
final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; | |
char[] hexChars = new char[bytes.length * 2]; | |
int v; | |
for (int j=0;j<bytes.length;j++){ | |
v = bytes[j] & 0xFF; | |
hexChars[j * 2] = hexArray[v >>> 4]; | |
hexChars[j * 2 + 1] = hexArray[v & 0x0F]; | |
} | |
return new String(hexChars); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment