You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android平台纯C++环境下不依赖JNI如何安全存储数据

可行性结论

完全可行,仅存在版本适配边界限制。
你不需要依赖JNI调用Java层逻辑:

  1. 所谓SharedPreferences本质就是应用私有目录下的普通XML文件,纯C++通过标准Linux文件IO就能直接读写应用私有目录,存储能力本身不需要依赖任何Java框架。
  2. Android KeyStore的核心能力从API 23(Android 6.0)开始就通过Native Binder服务对外暴露,直接链接系统库就能完成密钥生成、加解密全流程,不需要绕Java层。
    唯一的限制是API 23以下的系统版本,KeyStore的Native接口属于系统内部私有接口,没有兼容性承诺,不同版本、不同厂商的实现差异极大,纯C++对接没有稳定保障。
实现逻辑拆解

整个方案分两层,完全不需要Java代码参与:

  • 存储层:直接在应用私有目录(路径可以通过ANativeActivity的internalDataPath字段获取,属于NDK公开稳定接口)创建自定义存储文件,写入时设置文件权限为0600,保证其他应用无法读取,安全等级和SharedPreferences完全一致。
  • 加密层:链接系统自带的libkeystore_binder.so、libbinder.so,直接通过Binder调用系统Keystore服务,完成密钥生成、加密、解密操作,密钥本身存储在系统安全域,和Java层调用KeyStore的安全等级完全一致。
最小入门演示示例

前置编译配置:NDK最低编译版本设为API 23,编译时链接系统库libkeystore_binder.so、libbinder.so、libcrypto.so。

// 引入NDK公开的Binder和Keystore头文件
#include <binder/IServiceManager.h>
#include <keystore/IKeystoreService.h>
#include <fstream>
#include <string>
#include <sys/stat.h>

// 获取系统Keystore服务实例
sp<IKeystoreService> getKeystoreService() {
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
    return interface_cast<IKeystoreService>(binder);
}

// 实际使用时替换为应用internalDataPath下的自定义文件路径
constexpr const char* SECURE_STORE_PATH = "/data/data/[替换为你的应用包名]/files/secure_store.bin";

bool saveSecureStr(const std::string& keyAlias, const std::string& plainContent) {
    sp<IKeystoreService> keystore = getKeystoreService();
    if (keystore.get() == nullptr) return false;

    // 此处补全密钥生成、AES加密逻辑:接口参数和Java层KeyStore参数一一对应
    // 可以直接参考AOSP中IKeystoreService.h的接口定义,不需要查阅Java层实现
    std::string encryptedBytes;

    // 直接写入私有文件
    std::ofstream outFile(SECURE_STORE_PATH, std::ios::binary);
    if (!outFile.is_open()) return false;
    outFile.write(encryptedBytes.data(), encryptedBytes.size());
    outFile.close();
    // 强制设置文件权限:仅当前应用可读写
    chmod(SECURE_STORE_PATH, 0600);
    return true;
}

std::string loadSecureStr(const std::string& keyAlias) {
    sp<IKeystoreService> keystore = getKeystoreService();
    if (keystore.get() == nullptr) return "";

    // 读取本地加密文件
    std::ifstream inFile(SECURE_STORE_PATH, std::ios::binary);
    if (!inFile.is_open()) return "";
    std::string encryptedBytes((std::istreambuf_iterator<char>(inFile)), std::istreambuf_iterator<char>());
    inFile.close();

    // 此处补全Keystore解密逻辑,输出明文
    std::string plainContent;
    return plainContent;
}
落地注意事项
  • 上述示例仅演示框架可行性,实际使用时需要补全密钥参数配置(比如设置密钥不可导出、绑定用户锁屏认证等)、加解密的完整调用流程,接口定义全部在NDK暴露的头文件中,不需要深入翻全量AOSP源码。
  • 如果需要兼容API 23以下版本,没有稳定的纯C++对接系统KeyStore的方案,要么选择本地加密算法+代码混淆保护密钥的方案(安全性低于系统KeyStore),要么只需要写不到100行的JNI桥接代码就能对接Java层KeyStore,适配成本远低于你的预期。
  • 不要尝试调用系统私有库实现低版本兼容,不同厂商、不同系统版本的私有库签名和实现差异极大,上线后会出现大面积兼容性崩溃。

内容的提问来源于stack exchange,提问作者Oscar Franco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.07 16:15:41