当前位置: 首页 > 知识库问答 >
问题:

如何安全归零并释放Android应用程序使用的所有内存页面?

亢正德
2023-03-14

我是一名软件工程师,正在构建一个将由政府机构使用的Android应用程序。

我们合同中的一项要求是,该应用程序必须符合FIPS 140。https://en.wikipedia.org/wiki/FIPS_140

为了符合FIPS,当Android应用程序关闭时,我们的应用程序必须将RAM中的任何密码对象归零并清除。(通过将密码归零并从RAM中清除,我们减少了攻击者的机会窗口。即,这降低了冷启动攻击风险:https://en.wikipedia.org/wiki/Cold_boot_attack)

为了满足这个需求,我们最初遵循了下面两篇SO文章中的建议,将用户密码捕获为字符数组而不是字符串

    < li >为什么字符[]比字符串更适合用作密码? < li >不使用字符串从用户处获取char数组
//First collect the password from Edit Text as a []char
int pl = passwordEditText.length();
char[] password = new char[pl];
passwordEditText.getText().getChars(0, pl, password, 0);

//Now set the password on viewmodel
viewModel.setPassword(password) 

一旦我们有了密码,我们就用它来调用第三方网络服务库,该库获取数据以显示在屏幕上。

ViewModel伪代码:

public DataObject getData(char[] password){
     return this.webService.getData(password);
}

当用户使用我们的应用程序时,我们调用以下方法来清零并清除密码

ViewModel伪代码:

public zeroPassword(){
    Arrays.fill(this.password, 0);
    this.password = null;
}

这一切都很好,因为java中的char数组是通过引用传递的(与不可变的字符串不同),并且我们在zeroPassword方法中有效地将内存中密码字符数组的任何跟踪归零。

然而。。。

我们深入研究了第三方WebService代码(this.WebService.getData(password)),结果发现,在幕后,WebService将char数组密码转换为字符串,然后在进行网络调用之前进行传递。

基本上——即使我们在Android ViewModel代码中将char数组引用归零,因为char数组由第三方库获取并用于创建字符串,密码仍将存在于内存中:(

选项

此时,我们正在考虑两个选项:

  1. 选项1是获取第三方库的副本并对其进行修改,使其不与密码字符串一起工作。通过这种方式,我们可以更改任何密码字符串的用法,以使用字符数组、缓冲区等-我们可以在某个时间点将其归零的所有对象)
  2. 选项2-当用户关闭应用程序时,我们会研究一些方法来清零和清除我们的Android应用程序使用的所有内存页面(即关闭整个应用程序并清除RAM)

作为一个团队,我们更喜欢选项2,因为它涵盖了我们所有的基础。选项1将具有挑战性、侵入性、耗时且混乱。

更新-根据这里的答案,选项1似乎根本不起作用。我如何确保Java中String对象的销毁?Java使用分代垃圾收集,并将对象复制到各个地方,甚至是字符数组,因此零化字符数组并不能保证从RAM中删除密码。

有没有办法完成我们被要求做的事情?i、 e.从内存中完全擦除密码的任何痕迹?

Android安全专家可以发表意见吗?

谢谢

共有2个答案

仲孙磊
2023-03-14

使用V8在应用关闭时运行服务人员,例如:

addEventListener("fetch", event => {
    event.respondWith(fetchAndReplace(event.request));
});
async function fetchAndReplace(request) {
    const response = await fetch(request);
    let type = response.headers.get("Content-Type") || "";
    if (!type.startsWith("application/")) {
        return response;
    }

    let newHeaders = new Headers(response.headers);

    newHeaders.set('Clear-Site-Data', '"cache", "cookies",  "storage",  
    "executionContexts"');

    return new Response(response.body, {
        status: response.status,
        statusText: response.statusText,
        headers: newHeaders
    });
}

请参阅MDN上的清除站点数据。“网站”具有误导性,因为“网站”~=只有网站。

左翰海
2023-03-14

根据ViewModel文档:

当所有者活动完成时,框架调用ViewModel对象的onCleared()方法,以便它可以清理资源。

不需要手动创建/调用析构函数来清理ViewModel资源,因为这个生命周期组件已经有了清理自己资源的机制。

为了更容易理解,ViewModel具有以下行为:

>

  • 在配置更改时重新创建活动时:我们仍然有相同的 ViewModel 实例。

    当Activity完成时:ViewModel将自动调用onCleared()为我们清理资源,因此我们甚至不必手动解除绑定/清理。

    某些ViewModel对象仍存在于内存中的原因是因为“活动”(具有ViewModel)仍处于活动状态,或者可能有另一个类保存对此“活动”的引用。

  •  类似资料:
    • 问题内容: 我有一个使用巨大页面的应用程序,该应用程序由于某些错误突然崩溃。崩溃后,由于应用程序无法正确释放大页面,因此sys文件系统中的免费大页面数量不会增加。 有没有办法强制释放大页面? 问题答案: HugeTLB可以用于共享内存(Mark J. Bobak的答案可以解决该问题),也可以将应用程序mmaps文件创建在hugetlb文件系统中。如果应用程序崩溃而未删除这些文件,它们将继续存在并保

    • 问题内容: 我正在使用以下功能下载小于20MB的文件。它将全部内容读取到内存中,因为另一个功能必须先对字节执行工作,然后才能将其写入磁盘。 这可以正常工作,但是所有内存都在系统上消耗了。 是否可以在其他功能处理完之后释放使用的内存,以使内存使用量不会大于当前正在处理的字节数? 问题答案: 您可能会触发gc使用释放未使用的对象,并且可能敦促Go运行时使用释放内存到OS ,但是所有这些都只是在扑救。编

    • 问题内容: 我正在阅读Python内存管理,希望减少应用程序的内存占用。有人建议,子流程可以大大减轻该问题;但是我在概念上需要做些麻烦。可以请一个简单的例子说明如何解决这个问题。 …变成一个 真正的 子处理函数,该函数不存储额外的“自由列表”? 奖励问题: 这个“自由列表”概念也适用于python c扩展吗? 问题答案: 关于优化建议的重要事项是确保仅在子流程中调用该建议。该和是无关的- 一旦你在

    • 问题内容: 如何以编程方式找到我的Android应用程序上使用的内存? 我希望有一种方法可以做到。另外,我也该如何获得手机的空闲内存? 问题答案: 请注意,现代操作系统(如Linux)上的内存使用是一个极其复杂且难以理解的领域。实际上,你正确解释任何数字的机会非常低。(几乎每当我与其他工程师一起查看内存使用量数字时,对于它们的实际含义总会进行长时间的讨论,这只会导致模糊的结论。) 注意:我们现在有