I am trying to fix this issue Improper Verification of App Signature at Runtime. for my flutter app.
Description of this issue is
Android apps are digitally signed. A digital signature, in this context, is a cryptographic construct that a developer applies to a piece of software to prove he/she wrote it. If an attacker has modified something in the app and re-sign it with its own signature, the app should not be able to run. The application should check the current signature of the app with the developer’s signature at runtime.
So I have implemented the following code in my app
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:package_info_plus/package_info_plus.dart';
Future<void> verifyAppSignature() async {
if (kDebugMode) {
print('Skipping signature verification in debug mode.');
return;
}
if (kReleaseMode) {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String appSignature = await getPackageSignature(packageInfo.packageName);
String developerSignature = 'my_sha-1_key';
// storing the sha key in code is not recommended
if (appSignature != developerSignature) {
print("appSign: $appSignature");
// SystemNavigator.pop();
// throw Exception('Release signature verification failed');
}
}
}
Future<String> getPackageSignature(String packageName) async {
try {
const MethodChannel channel = MethodChannel('app-release');
final String signature = await channel.invokeMethod('getSignature');
return signature;
} on PlatformException catch (e) {
return e.toString();
}
}
Changes made to MainActivity.kt
package com.example.appname
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Build
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
private val CHANNEL = "app-release"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "getSignature") {
val signature = getSignature()
result.success(signature)
} else {
result.notImplemented()
}
}
}
private fun getSignature(): String {
return try {
val packageInfo: PackageInfo = packageManager.getPackageInfo(
packageName,
PackageManager.GET_SIGNATURES
)
val signature = packageInfo.signatures?.getOrNull(0)
signature?.let {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.toCharsString()
} else {
it.toString()
}
} ?: ""
} catch (e: Exception) {
e.printStackTrace()
""
}
}
}
But The problem here the appSignature returns a X.509 certificate fingerprint/hash and my developerSignature is a sha-1 fingerprint.
If there is a method to calculate the sha-1 fingerprint of X.509 certificate then it would be a big help.
I have figured it out.
Inside
MainActivity.ktI calculated thesha-1 fingerprintof theX.509 Certificate.imports
then inside
getSignature()Kotlin extension function to compute the SHA-1 hash of a ByteArray.
You can replace "SHA-1" with "SHA-256" or other algorithms if needed