Native Technologies
Android

Learn How to Enhance Android Security: Build Integrity Verification

people unlocking android phone

X min read

29.6.2020

article content

Advantages of Using the Build Integrity Verification

A build integrity verification brings many benefits to your project. Consider these advantages:

  • Standard attacks and tools like lucky patcher won’t be able to break your application
  • It’s easy to implement and maintain
  • It’s not used commonly. Hackers may not be familiar with this technique—they might struggle to break it
  • It’s reusable. Once implemented, it will be easy to use in your other applications

How Does the Build Integrity Verification Work?

We want to be able to detect changes to application source code and terminate the application once such changes occur. To do this, we can implement a cyclic redundancy check on the application’s bytecode. We will calculate the hash of the classes.dex file and then store it in strings.xml. Then at some point when the application is running, we can invoke the isCodeModified() function.

fun isCodeModified(): Boolean {
      val hash = getString(R.string.crc)
      val entry = ZipFile(app.packageCodePath).getEntry("classes.dex")
      val classesCrc = Long.toHexString(entry.crc)
      return classesCrc != hash
}


This function will retrieve the previously cached checksum and then compare it with the current classes.dex checksum value. If those values differ, then we know that the source code was modified and we can terminate the application process. One important point here is that the cached checksum should be stored in application resources, not directly in the source code. Otherwise the classes.dex checksum would change when you modify the cached crc value.

How to Automate the Caching Checksum Value?

Now that we know how to implement the build integrity verification one question remains: how and when should we store the checksum in strings.xml? Once we are ready for an application release, we could use this simplistic algorithm:

  1. Build apk like we normally would.
  2. Retrieve classes.dex file from apk file and calculate the checksum for that.
  3. Store calculated checksum in strings.xml file and then build application once again.


This process would be cumbersome if we had to perform these steps every time we want to release a new update to Google Play Store. Also, it’s common these days to use a continuous integration system to automate application builds. To address these issues, we will create two gradle tasks:

static def getChecksum() {
  def command = "crc32 PATH_TO_CLASSES_DEX"
  return command.execute().text
}

def getCachedChecksum() {
  //retrieve cached checksum in strings.xml and return it
}


task verifyChecksum() {
  doLast {
      if(getChecksum() != getCachedChecksum()) {
          throw new GradleException()
      }
  }
}

task updateChecksum() {
  doLast {
      //store currentChecksum in strings.xml

  }
}

We left out certain implementation details as an exercise for you.

Now that we have those gradle tasks, we can utilize them in the bash script that will be executed by the CI system:

set -e
./gradlew clean
./gradlew app:assembleRelease
set +e
if ./gradlew verifyChecksum ; then
  echo "Checksum valid"
else
  set -e
  ./gradlew updateChecksum
  ./gradlew clean
  ./gradlew app:assembleRelease
  ./gradlew verifyChecksum
fi


Here we simply build an application and then verify the checksum. If the checksum is incorrect, then we update it and then build apk once again. Now the checksum should be correct, and we can safely distribute the build to our users.

It’s important to notice that we execute a “clean” task before each build. Otherwise the calculated checksums would differ and our algorithm wouldn’t work correctly.

The Build Integrity Verification Can Fortify Your Application

Unfortunately, the nature of mobile applications renders them impossible to be resilient to every attack. Potential attackers will always have a possibility to decompile your code and modify it. However, the build integrity verification will make potential attacks much more difficult. Hopefully this article will prove valuable to you, and you will consider implementing this security measure in your future projects. Happy coding!

Related articles

Supporting companies in becoming category leaders. We deliver full-cycle solutions for businesses of all sizes.

woman presenting slide about mobile app
Native Technologies
Android

Android App Development: How to Build a Great Mobile Product

Ensuring your Android app development project is successful is easy when you know what’s involved in the process. Learn all about Android app development.

calling phone and film slate illustration
Android
Mobile Development

Android Animation Libraries You Should Know

In-app animations play a critical part in how users perceive apps. Check out some of the great animation libraries that we use for projects at Nomtek.

Cookie Consent

By clicking “Accept All Cookies,” you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.