在java中,如何清除每个方法中的字节[]数组以保护值免受内存转储?

Posted

技术标签:

【中文标题】在java中,如何清除每个方法中的字节[]数组以保护值免受内存转储?【英文标题】:In java, how to clear byte[] array inside every method to protect the value from memory dump? 【发布时间】:2018-05-21 07:51:19 【问题描述】:

在java中,

如果我在下面运行代码,pwd 值存在于整个内存中,因为字节数组值被复制到摘要方法,该方法也将值复制到其他一些方法。

    import java.security.MessageDigest

    byte[] pwd = "some_pwd".getBytes();
    MessageDigest md = MessageDigest.getInstance("SHA");
    for (int i = 0; i < 100; i++) 
        byte[] hash = md.digest(pwd);
    

内存转储软件显示我的客户不喜欢的密码值。

我检查了 byte[] 是按值从一个方法复制到另一个方法。

有没有办法保护重要的字节数组值?

【问题讨论】:

没有。您的代码确实处理了密码值(甚至只是散列它),因此它必须出现在程序 RAM 中。您唯一的选择是使保存密码的变量尽可能短(限制其范围)。 想一想,即使您可以将数组作为引用传递,如果您在使用此数组时转储内存,您将能够看到该值(不经常,但仍然至少1次) 【参考方案1】:

密码文本最好不要作为字符串传递,但我们假设这是一个示例:

然后确保字节不会出现在测试字符串中。

byte[] pwd = "rnld^ovc".getBytes(StandardCharsets.UTF_8); // "some_pwd"
for (int i = 0; i < pwd.length; ++i) 
    pwd[i]++;

然后解决办法:

MessageDigest md = MessageDigest.getInstance("SHA");
for (int i = 0; i < 100; i++) 
    //byte[] hash = md.digest(pwd);
    for (byte b : pwd) 
        md.update(b - 1); // Maybe -1 if the string was the real password
    
    byte[] hash = md.digest();

Arrays.fill(pwd, (byte)0);

现在 MessageDigest 无法在调用摘要时维护数组的副本。

如果您甚至不想拥有 pwd 数组,则只需从密码字段中一次获取一个字符/字节。

【讨论】:

我想你忘了b -1,否则你计算一个不同值的哈希 嗯,我不知道,我仍然不是 100% 满意 :) 但我认为这是你能做的最好的...... @JohnnyAW 我的意思是字符串包含廉价的 -1 加密,因此内存转储不会显示它,并且 pwd 包含真实密码;但除此之外 - 确实需要 1。 具有讽刺意味的是,最终的实际密码可能是“秘密”或“12345678”。 好一个,让 123456 尽可能安全:)

以上是关于在java中,如何清除每个方法中的字节[]数组以保护值免受内存转储?的主要内容,如果未能解决你的问题,请参考以下文章

java怎么 清除数组数据?

Java 迭代字节数组中的位

JAVA里String数组在内存分配中分配的空间每个占几个字节?

如何检查字节数组是不是包含 Java 中的 Unicode 字符串?

在java中如何把字节数组存储到数据库?

如何检查字节数组是否包含Java中的Unicode字符串?