Skip to main content

Mobile Security Shield (OtaSecurityShield)

The lib/src/security/ota_security_shield.dart module protects your mobile application against three major attack vectors before any network request or OTA patch application occurs:

  1. APK Anti-Repackaging (cryptographic SHA-256 fingerprint verification of the installed APK signing certificate).
  2. Compromised Device Detection (root detection on Android and jailbreak detection on iOS).
  3. TLS Certificate Pinning SHA-256 (validation of raw DER bytes from the server X.509 certificate).

1. Configuring Policy (OtaSecurityPolicy)​

The security policy is defined using the OtaSecurityPolicy class and supplied to TkOtaPush.init(...):

final ota = TkOtaPush.init(
appReleaseVersion: '1.0.0+3',
securityPolicy: const OtaSecurityPolicy(
// 1. Authorized SHA-256 fingerprints of the official APK signing certificate
expectedApkSignaturesSha256: {
'A1:B2:C3:D4:E5:F6:01:02:03:04:05:06:07:08:09:10:11:12:13:14:15:16:17:18:19:20:21:22:23:24:25:26',
},
// 2. Block rooted or jailbroken devices
blockRootedOrJailbrokenDevices: true,
// 3. SHA-256 fingerprints of the OTA server TLS certificates (X.509 DER)
pinnedServerCertSha256Fingerprints: {
'42d889f8f4b6bf9d3abb767d3b5f215e0009e4d26cb7b958497e8b291e1b96dc',
},
),
onSecurityViolation: (OtaSecurityVerdict verdict) async {
debugPrint('Security violation (${verdict.violationType}): ${verdict.reason}');
},
);

Normalizing SHA-256 Fingerprints​

The helper method OtaSecurityPolicy.normalizeSha256(String fingerprint) automatically strips colons (:), dashes (-), and whitespace, converting the string to lowercase:

  • 'A1:B2:C3...' and 'a1b2c3...' are handled identically.

2. APK Anti-Repackaging vs Offline Peer-to-Peer Sharing (Xender / ShareIt)​

Across many emerging markets, users frequently share the raw .apk file between devices via offline peer-to-peer utilities (Xender, ShareIt, Bluetooth).

  • Official APK shared via Xender: the APK package is unmodified; its cryptographic signing certificate matches the publisher's official keystore. evaluatePolicy validates the fingerprint and 100% authorizes OTA updates.
  • Pirated APK decompiled and resigned: an attacker tampering with APK bytecode or assets must resign the bundle using their own private key. The observed SHA-256 fingerprint differs from expectedApkSignaturesSha256: the SDK immediately blocks all OTA operations with OtaSecurityViolationType.apkSignatureMismatch.

Feeding Native APK Signatures to DefaultOtaDeviceIntegrityInspector​

By default, DefaultOtaDeviceIntegrityInspector.readInstalledApkSignatureSha256():

  1. Calls the apkSignatureProvider callback if provided to the constructor.
  2. Otherwise, falls back to the Platform.environment['OTA_APK_SIGNATURE_SHA256'] variable.

To bridge Android native certificate inspection (PackageManager.GET_SIGNING_CERTIFICATES via a MethodChannel):

const platformChannel = MethodChannel('com.myapp/security');

final inspector = DefaultOtaDeviceIntegrityInspector(
apkSignatureProvider: () async {
return await platformChannel.invokeMethod<String>('getApkSignatureSha256');
},
);

final ota = TkOtaPush.init(
appReleaseVersion: '1.0.0+3',
deviceIntegrityInspector: inspector,
securityPolicy: const OtaSecurityPolicy(
expectedApkSignaturesSha256: {'6b6929c8ff345cf008496328d7bff081a8ccfb89498bf9916ed668be3c3dedcf'},
),
);

3. Root Detection (Android) and Jailbreak Detection (iOS)​

When blockRootedOrJailbrokenDevices: true, DefaultOtaDeviceIntegrityInspector.isDeviceRootedOrJailbroken() inspects Android and iOS filesystems (Platform.isAndroid || Platform.isIOS) for suspicious paths:

PlatformInspected Paths (_defaultSuspiciousPaths)
Android (Root)/system/app/Superuser.apk, /sbin/su, /system/bin/su, /system/xbin/su, /data/local/xbin/su, /data/local/bin/su, /system/sd/xbin/su, /sbin/magisk
iOS (Jailbreak)/Applications/Cydia.app, /Library/MobileSubstrate/MobileSubstrate.dylib, /private/var/lib/apt, /private/var/stash

You can supply your own path list via customSuspiciousPaths in DefaultOtaDeviceIntegrityInspector, or implement the OtaDeviceIntegrityInspector abstract class directly.

4. TLS Certificate Pinning SHA-256 (OtaCertificatePinner & OtaPinnedHttpOverrides)​

To safeguard asset downloads and Dart HTTPS network traffic against Man-in-the-Middle (MitM) attacks through rogue root certificates, the SDK exposes OtaCertificatePinner and OtaPinnedHttpOverrides.

How OtaCertificatePinner Works​

  • OtaCertificatePinner.computeDerSha256Hex(List<int> derBytes) calculates the lowercase SHA-256 hexadecimal digest of raw DER bytes (cert.der) from the server's X.509 certificate.
  • When pinnedSha256Fingerprints is empty, verifyCertificateDer returns true.
  • When enforcedHosts is populated (e.g., {'ota.saramoney.com'}), pinning is only enforced against those hosts; if left empty, pinning applies globally.

Global Setup with HttpOverrides.global​

import 'dart:io';
import 'package:tk_ota_push/tk_ota_push.dart';

void configureTlsPinning() {
final pinner = OtaCertificatePinner(
pinnedSha256Fingerprints: {
'42d889f8f4b6bf9d3abb767d3b5f215e0009e4d26cb7b958497e8b291e1b96dc',
},
enforcedHosts: {'ota.saramoney.internal'},
);

HttpOverrides.global = OtaPinnedHttpOverrides(pinner);
}

5. Security Failure Behaviors (OtaSecurityVerdict)​

During calls to ota.syncWithRemoteConfig(...), security verification executes at Step 0b, prior to querying RemoteConfigGatekeeper or the network:

Violation Type (OtaSecurityViolationType)CauseSDK Behavior
apkSignatureMismatchAPK SHA-256 signature missing or not listed in expectedApkSignaturesSha256.1. Calls onSecurityViolation(verdict) if configured.
2. Returns OtaSyncOutcome with executionMode: OtaUpdateExecutionMode.blockedBySecurityShield and networkCallPerformed: false.
deviceRootedOrJailbrokenblockRootedOrJailbrokenDevices == true and root/jailbreak binary/directory found.1. Calls onSecurityViolation(verdict) if configured.
2. Returns OtaSyncOutcome with executionMode: OtaUpdateExecutionMode.blockedBySecurityShield and networkCallPerformed: false.
tlsCertificatePinningMismatchServer X.509 certificate rejected during TLS handshake.HTTPS connection fails immediately before data exchange occurs.