将明文存储在java 8闭包中

时间:2017-10-12 11:20:18

标签: java encryption

我曾经看过道格拉斯·克罗克福德的演讲,在javascript的背景下,他提到将秘密存储在封闭中可能很有用。

我想这可以像Java一样天真地实现:

select from V

我想知道:这样做有什么好处吗?它可能在某种程度上不那么安全吗?

2 个答案:

答案 0 :(得分:3)

没理由这样做。将密码存储在字符数组中,因为如果要将它们打印出来,必须将它们显式转换为String。

考虑以下示例:

String stringPassword = "password";
char[] charactersPassword = new char[]{'p','a','s','s','w','o', 'r', 'd'};

System.out.println("Password: " + stringPassword);     // Password: password
System.out.println("Password: " + charactersPassword); // Password: [C@6ce253f1

主要思想是你可以清除数组的项目,因为它不是不可变的(@Klitos Kyriacou)。

Arrays.fill(charactersPassword, '0');

此外,如果您将密码存储为纯文本 - 字符串,它是不可变的,它将在内存中可用很长时间(仍然以某种方式可访问),直到垃圾收集器处理它。

无论如何,强烈建议我们管理一些安全库,它可以处理的不仅仅是创造一种新的(通常仍然存在风险)方式。

答案 1 :(得分:0)

这是一个非常“工程化”的例子,所以不要在你的代码中使用

我认为使用谓词而非供应商可以更好地证明效果。

假设您按如下方式实施密码检查:

public class PasswordChecker {

    private final String secretPassword;

    public PasswordChecker(String secretPassword) {
        this.secretPassword = secretPassword;
    }

    public boolean test(String password) {
        return Objects.equals(this.secretPassword, password);
    }

}

然后你可以创建一个传递它的实例:

final PasswordChecker passwordChecker = new PasswordChecker("changeit");

在其他地方你可以用它来检查密码:

assertThat(passwordChecker.test("foobar")).isFalse();

但对于手头有PasswordChecker实例的客户端,用一些反射提取密码并不困难:

    Field secretPasswordField = passwordChecker.getClass().getDeclaredField("secretPassword");
    secretPasswordField.setAccessible(true);
    String secretPassword = (String) secretPasswordField.get(passwordChecker);
    System.out.print(secretPassword);

现在这里的闭包是一样的:

final String secretPassword = "changeit";
final Predicate<String> passwordChecker = password -> Objects.equals(secretPassword, password);

现在您无法从secretPassword中提取passwordChecker