你无法阻止逆向工程,但你可以让逆向工程变得更加困难,包括并非每个人都能做到的更多工作和额外步骤。
将常量放入本机库可防止它们出现在反编译的 java 代码中。连接已编译库中的哪个字符串与最终应用程序中的哪个值匹配并非易事。一种常见的方法是只从本地库中导出所有字符串并通过上下文匹配它们——例如,寻找看起来像 API 密钥的东西。如果您加密这些常量并在应用程序本身中解密它们,这会为逆向工程增加另一个步骤,尽管由于加密密钥在应用程序中,攻击者最终当然可以自己完成。
要快速轻松地加密 NDK 中的值,请考虑使用基本的 salsa20 或 chacha20 实现 - 出于混淆目的,不需要身份验证,并且可以对密钥进行硬编码。
例如,使用this simple Salsa20 C implementation:
// hard-coded 128-bit key, can be anything
uint8_t k[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
// hard-coded nonce, can be anything
uint8_t n[8] = { 101, 102, 103, 104, 105, 106, 107, 108 };
// The s20_crypt() function encrypts/decrypts in place.
// During development, do this:
std::string myString = ...;
std::vector<uint8_t> vec(myString.begin(), myString.end());
s20_crypt(k, S20_KEYLEN_128, n, 0, vec.data(), vec.size());
// export the vector bytes somehow - you can run this on your computer and write then to a file or to stdout for example
// After you have the encrypted bytes:
Java_com_galaxy_mars_moon_MainActivity_getDefaultNegative(JNIEnv* env, jobject)
{
uint8_t[] defaultNegative = [...]; // the encrypted values
s20_crypt(k, S20_KEYLEN_128, n, 0, defaultNegative, sizeof(defaultNegative));
std::string decrypted(defaultNegative, defaultNegative+sizeof(defaultNegative));
return env->NewStringUTF(decrypted.c_str());
}