DEV Community

SameX
SameX

Posted on

Code Obfuscation and Memory Security in Multi-platform Services: Security Optimization of ArkTS Applications

This article aims to deeply explore the technical details of the Huawei HarmonyOS Next system (up to API 12 as of now), and is summarized based on actual development practices.
It mainly serves as a vehicle for technical sharing and communication. Mistakes and omissions are inevitable. Colleagues are welcome to put forward valuable opinions and questions so that we can make progress together.
This article is original content, and any form of reprint must indicate the source and the original author.

When developing cross-platform applications, code security and memory management are important links to ensure the stability and security of the application. Especially for applications involving sensitive information (such as financial payments, enterprise-level services), preventing data leakage and code decompilation is one of the core issues. This article will explore how to ensure the security and performance of cross-platform applications on HarmonyOS Next, iOS, and Android through technologies such as code obfuscation, memory security optimization, and Heap space management.

Project Background

We will build a cross-platform ArkTS application that simulates a financial payment or enterprise-level service scenario. The application involves the storage and transmission of user-sensitive data, so data encryption, memory security, and code protection need to be implemented. The application supports running on multiple platforms, such as HarmonyOS, iOS, and Android, so the design of cross-platform components will also be an important part.

Architecture Design

1. Cross-platform Architecture Design

When building a cross-platform application in ArkTS, a reasonable architecture design can effectively deal with the differences in characteristics of different platforms and ensure that the application code can run on multiple platforms. We can encapsulate the differences related to the platform through an abstraction layer to simplify cross-platform development.

  • General Logic: Most of the business logic can be written in ArkTS and does not depend on platform characteristics.
  • Platform Feature Encapsulation: Use an abstraction layer to encapsulate platform-specific functions, such as the file system, network requests, etc. Achieve cross-platform compatibility through platform inspection and conditional compilation.

Code Example: Platform Inspection and Conditional Compilation

let platform = globalThis.__system.capability.os;

if (platform === "HarmonyOS") {
    console.info("Running on HarmonyOS");
    // Use HarmonyOS-specific APIs
} else if (platform === "Android") {
    console.info("Running on Android");
    // Use Android-specific APIs
} else if (platform === "iOS") {
    console.info("Running on iOS");
    // Use iOS-specific APIs
}
Enter fullscreen mode Exit fullscreen mode

2. Handling and Storage of Sensitive Data

For applications involving user-sensitive information (such as payment data, identity authentication information, etc.), a reliable encryption mechanism must be designed to prevent data leakage. Common ways to handle sensitive data include symmetric encryption and asymmetric encryption.

  • Symmetric Encryption: Used to encrypt locally stored data, such as user session information, cached data, etc.
  • Asymmetric Encryption: Usually used to encrypt sensitive data in transmission to ensure that the data is not stolen by a man-in-the-middle during network transmission.

Code Example: AES Encryption to Store User Sensitive Information

import { util } from '@kit.ArkTS';

const key = util.Crypto.generateKey('AES', { length: 256 });
const iv = util.Crypto.generateIV();

// Encrypt data
function encryptSensitiveData(data: string): string {
    const encrypted = util.Crypto.encrypt('AES-CBC', key, iv, new util.TextEncoder().encode(data));
    return util.TextDecoder.create().decode(encrypted);
}

// Decrypt data
function decryptSensitiveData(encryptedData: string): string {
    const decrypted = util.Crypto.decrypt('AES-CBC', key, iv, new util.TextEncoder().encode(encryptedData));
    return util.TextDecoder.create().decode(decrypted);
}
Enter fullscreen mode Exit fullscreen mode

3. Design of Cross-platform Components

To reuse components on multiple platforms, the platform-independent business logic and UI components can be separated, and the specific platform characteristics can be encapsulated through interfaces. This can ensure the maintainability of the code and does not require a large amount of code rewriting when supporting different platforms.

Code Example: Cross-platform Component Design

@Entry
@Component
struct CrossPlatformComponent {
    build() {
        Column() {
            Text("Welcome to Cross-Platform App!")
               .fontSize(24)
               .margin(Edge.All, 10);

            // Display platform-specific components
            if (platform === "HarmonyOS") {
                HarmonyOSComponent();
            } else if (platform === "Android") {
                AndroidComponent();
            } else if (platform === "iOS") {
                IOSComponent();
            }
        }
    }
}

@CustomComponent
struct HarmonyOSComponent {
    build() {
        Text("This is a HarmonyOS-specific component.")
           .fontSize(20)
           .margin(Edge.All, 10);
    }
}

// Similarly, Android and iOS-specific components can be defined
Enter fullscreen mode Exit fullscreen mode

Code Obfuscation and Memory Security

1. Strategies and Implementation of Code Obfuscation

In cross-platform applications, code obfuscation is an important means to prevent decompilation and cracking. By obfuscating the code, the naming of variables, functions, classes, etc. in the application can be made unreadable, increasing the difficulty of reverse engineering. DevEco Studio provides support for obfuscating ArkTS code, and we can implement it by configuring the obfuscation-rules.txt file.

Code Obfuscation Configuration Example: obfuscation-rules.txt

-enable-property-obfuscation
-enable-toplevel-obfuscation
-enable-filename-obfuscation
-enable-export-obfuscation

# Keep the public interfaces that need to be exported to avoid obfuscation
-keep-global-name
myPublicAPI

-keep-property-name
userName
password
Enter fullscreen mode Exit fullscreen mode

With the above configuration, we can ensure the security of the application and prevent the core logic from being cracked by malicious users. At the same time, keep the public interfaces that need to be exported to ensure the normal operation of the function.

2. Memory Security and Tuning

In cross-platform applications, memory management is also crucial. Memory leaks will not only cause the application to crash but may also lead to security issues. We need to ensure that the resources that are no longer used are properly released in the application, especially in the code related to UI components, timers, and network requests.

  • Timer Management: Ensure that the timer is cleared when the component is destroyed to avoid occupying memory.
  • Cleanup of Event Listeners: Remove event listeners in time when they are no longer needed to prevent memory leaks.

Code Example: Cleaning up Timers and Event Listeners

@Entry
@Component
struct SafeComponent {
    private timer: any;

    build() {
        Text("This is a safe component.")
           .fontSize(24);
    }

    onAppear() {
        this.timer = setInterval(() => {
            console.info("Periodic task running...");
        }, 1000);
    }

    onDisappear() {
        clearInterval(this.timer);  // Ensure that the timer is cleaned up
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Heap Space Management

Heap space management is an important part to ensure that the application does not crash due to insufficient memory. We can control the maximum memory usage of the application and reasonably allocate the heap space by adjusting the HeapSize and other related parameters to avoid memory overflow.

Heap Space Configuration Example: build-profile.json

{
  "arkOptions": {
    "heapSize": 512,  // Set the Heap size in MB
    "gcOptions": {
      "gcThreadNum": 4,  // Set the number of GC threads to improve the recycling efficiency
      "heapExpandLimit": 128  // Set the Heap expansion limit
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Through reasonable Heap space management, the application can remain stable when processing large amounts of data and avoid frequent garbage collection affecting performance.

Case Practice

1. Implementation and Debugging of Code Obfuscation

By configuring the obfuscation-rules.txt file, we can implement the obfuscation of ArkTS code. Developers can enable code obfuscation in DevEco Studio and monitor the behavior of the obfuscated code through logs to ensure that the function is normal.

Operation Steps:

  1. Open the build-profile.json configuration file in DevEco Studio and enable code obfuscation.
  2. Configure obfuscation-rules.txt to define the parts of the code that need to be obfuscated and retained.
  3. Compile the project and check the effect of the obfuscated code.
  4. Debug through logs to verify whether the code obfuscation affects the function.

2. Memory Security Code Implementation

In the application, we can encrypt user-sensitive information with AES and combine Heap space management and memory cleanup strategies to ensure the security of sensitive data and the efficient use of application memory.

Code Example: Implementation of Memory Security and Sensitive Data Encryption

function handleSensitiveData() {
    const sensitiveInfo = "User Password";
    const encryptedData = encryptSensitiveData(sensitiveInfo);

    console.info("Encrypted Data:", encryptedData);

    // Decryption operation
    const decryptedData = decryptSensitiveData(encryptedData);
    console.info("Decrypted Data:", decryptedData);
}
Enter fullscreen mode Exit fullscreen mode

3. Debugging and Optimization

In cross-platform services, we can monitor the memory usage through performance monitoring tools and the log system and combine GC tuning strategies and Heap management for optimization to improve the overall performance and security.

Performance Monitoring Tools:

  • Use Profiler to check the memory usage of the application.
  • Monitor the memory recycling situation through GC logs and adjust the recycling strategy.

Architecture Considerations

Trade-offs between Security and Performance in Cross-platform Architectures

When designing cross-platform applications, security and performance are two important aspects that need to be balanced. Excessive security protection (such as complex encryption algorithms, frequent garbage collection) may affect the performance of the application, while ignoring security will bring potential risks. Therefore, when designing the architecture, we need to comprehensively consider the following points:

  • Balance between Performance and Security: Adopt encryption and obfuscation technologies to protect the code and data as much as possible under the condition that the performance allows.
  • Reasonable Resource Allocation: Adapt to the hardware and software characteristics of specific platforms on different platforms to optimize memory usage and processing efficiency.
  • Maintainability and Extensibility: Achieve cross-platform compatibility through the design of the abstraction layer and ensure the maintainability of the code when expanding functions in the future.

Top comments (0)