提供自定义 N 因子身份验证机制怎么样?
在组合可用方法之前,假设我们可以执行以下操作:
1) Java 程序内部的硬代码
2) 存储在 .properties 文件中
3)要求用户从命令行输入密码
4) 要求用户从表单中输入密码
5) 要求用户从命令行或表单加载密码文件
6) 通过网络提供密码
7)许多替代品(例如Draw A Secret、Fingerprint、IP-specific、bla bla bla)
第一种选择:我们可以通过使用混淆使攻击者的事情变得更复杂,但这不是一个好的对策。如果他/她可以访问文件,一个好的编码人员可以很容易地理解它是如何工作的。我们甚至可以导出每个用户的二进制文件(或者只是混淆部分或密钥部分),因此攻击者必须有权访问这个用户特定的文件,而不是另一个发行版。同样,我们应该找到一种更改密码的方法,例如通过重新编译或使用反射来即时更改类行为。
第二种选择:我们可以将密码以加密格式存储在 .properties 文件中,因此攻击者无法直接看到它(就像jasypt一样)。如果我们需要一个密码管理器,我们也需要一个主密码,它应该被存储在某个地方——一个 .class 文件、密钥库、内核、另一个文件甚至内存中——它们各有利弊。
但是,现在用户只需编辑 .properties 文件即可更改密码。
第三个选项:从命令行运行时输入密码,例如java -jar /myprogram.jar -p sdflhjkiweHIUHIU8976hyd
。
这不需要存储密码并将保留在内存中。但是,history
命令和操作系统日志可能是您最大的敌人。要即时更改密码,您需要实现一些方法(例如监听控制台输入、RMI、套接字、REST bla bla bla),但密码将始终保留在内存中。
甚至可以仅在需要时对其进行临时解密->然后删除解密的内容,但始终将加密的密码保存在内存中。不幸的是,上述方法并没有增加针对未经授权的内存访问的安全性,因为实现这一点的人可能会访问算法、盐和任何其他正在使用的秘密。
第四个选项:从自定义表单而不是命令行提供密码。这将规避记录暴露的问题。
第 5 个选项:提供一个文件作为先前存储在另一个介质上的密码 -> 然后硬删除文件。这将再次规避记录暴露的问题,而且不需要打字,这可能会被偷走。当需要更改时,提供另一个文件,然后再次删除。
第 6 种选择:同样为了避免翻墙,可以实现 RMI 方法调用,以从另一设备(例如通过手机)提供密码(通过加密通道)。但是,您现在需要保护您的网络通道并访问其他设备。
我会选择上述方法的组合以实现最大的安全性,因此必须访问 .class 文件、属性文件、日志、网络通道、肩冲浪、中间人、其他文件 bla bla bla。这可以很容易地使用所有 sub_passwords 之间的 XOR 操作来生成实际密码来实现。
但是,我们无法保护我们免受未经授权的内存访问,这只能通过使用一些访问受限的硬件(例如智能卡、HSM、SGX)来实现,在这些硬件中,一切都被计算在内,没有任何人,甚至是合法的所有者能够访问解密密钥或算法。同样,人们也可以窃取此硬件,据报道,侧信道攻击可能有助于攻击者提取密钥,并且在某些情况下您需要信任另一方(例如,使用 SGX,您信任英特尔)。当然,当安全飞地克隆(拆卸)成为可能时,情况可能会恶化,但我想这需要几年时间才能实现。
此外,可以考虑一种密钥共享解决方案,其中完整密钥在不同服务器之间拆分。但是,在重建时,完整的密钥可能会被盗。缓解上述问题的唯一方法是通过安全多方计算。
我们应该始终牢记,无论使用哪种输入法,我们都需要确保我们不会受到网络嗅探(MITM 攻击)和/或键盘记录器的攻击。