Security
Platform-specific security recommendations for applications embedding the Risk Management mobile SDK:
Android
Guidelines for tamper detection at host application
As a part of application security measures, the following code can be included to protect against tampering of the application.
This code must be inlined in a method that does a critical operation, such as triggering method calls in the Risk Management SDK.
The strings provided in this code snippet must be encrypted using Dexguard and the getPackageInfo() API has to be enabled with the accessthroughreflection setting in the Dexguard configuration.
The hash signature of the certificate can be obtained by executing the following commands in the command prompt:
cd <path to Java installation\bin>
keytool.exe -list -v –keystore <path to .keystore file> -alias androiddebugkey -storepass <storePassword> -keypass <keyPassword>
Replace the SIGNATURE = “” in the following snippet code with the signature obtained above.
boolean matches = false;
try {
// Get the APK signature
PackageManager packageManager = mContext.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(mContext.getPackageName(), PackageManager.GET_SIGNATURES);
Signature signature = packageInfo.signatures[0];
// Calculate hash of the signature
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
byte[] sigHash = md.digest();
// Declare the expected signature hash as a String
// Modify this value based on the hash generated from certificate you use so that DexGuard can obfuscate it
String SIGNATURE = "";
// Convert the expected signature hash String into a Byte Array
int len = SIGNATURE.length();
byte[] bytes = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
bytes[i / 2] = (byte) ((Character.digit(SIGNATURE.charAt(i), 16) << 4) + Character.digit(SIGNATURE.charAt(i + 1), 16));
}
// Compare the signature hashes, add necessary steps here if the signature does not match
matches = Arrays.equals(sigHash, bytes);
} catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) {
Log.d(TAG, "Exception in signature comparison");
}
Guidelines for obfuscation at host application
It is highly recommended that your application be obfuscated with ProGuard or DexGuard prior to delivery. The Risk Management SDK has applied basic obfuscation and advanced class and string encryption internally using DexGuard. To obfuscate your application on top of Risk Management SDK, include the following configuration files in your application obfuscation process:
- For ProGuard or R8: include "proguard/proguard-project.txt"
- For DexGuard: include "dexguard/dexguard-project.txt"
Both configuration files are available in the SDK delivery package. They are used on top of the obfuscation configurations specific to your application.
The configurations are validated with the following combination:
- DexGuard v9.1.1
It is recommended to add in your obfuscation configuration the following for troubleshooting purposes. Archive the mapping files for each of your application delivery.
Issue on Dexguard v9.1.1
GuardSquare confirms an issue with Dexguard obfuscating resources that contain Java class references. This impacts the BehavioSec integration. As a workaround, you might need to keep the related class and resource.
# Provide a custom path for mapping files
-printmapping obfuscation.map
-printseeds classes-processed.seeds
-printconfiguration obfuscation.config
In build.gradle (module level), the order of the Dexguard file configuration must be as follows:
android {
...
buildTypes {
release {
proguardFiles getDefaultDexGuardFile('dexguard-release.pro')
proguardFiles 'path to Thales SDK obfuscation configuration'
proguardFiles 'path to your app obfuscation configuration'
...
}
debug {
proguardFiles getDefaultDexGuardFile('dexguard-release.pro')
proguardFiles 'path to Thales SDK obfuscation configuration'
proguardFiles 'path to your app obfuscation configuration'
...
}
}
}
Encrypting native library projects
When encrypting native library projects, the code sets a temporary directory for maximum portability. One of the libraries integrated in the Risk Management SDK uses the native encryption feature from DexGuard.
DexGuard uses the environment variable java.io.tmpdir to create a temporary file when decrypting the native library during runtime. In the older versions of Android, this variable might point to a location that the application does not have the permission to modify, for example, /sdcard.
To ensure that there is a valid temporary directory at all times regardless of the Android version used, this variable must be defined and point to a location that exists and is writable.
To ensure that the device running the app has enough storage space, add this code snippet at the launch of the host application, as recommended by DexGuard:
System.setProperty("java.io.tmpdir",getDir("files", Context.MODE_PRIVATE).getPath());
Dexguard warning messages
Since SDK version 2.7.0, if the application is applying Dexguard (from version 9.0.22), there are following warning messages, which can be ignored:
- From D8/R8:
AGPBI: {"kind":"warning","text":"Expected stack map table for method with non-linear control flow.","sources":[{"file":"GAHRiskEngine.jar"}],"tool":"D8"}
- From Dexguard:
WARN: ignored invalid inner class name com/threatmetrix/TrustDefender/dddgdg$1, treating as anonymous inner class.
iOS
No recommendation for code obfuscation on the iOS platform.