Java - generate machine specific encryption key
我正在编写一个将加密对象的映射序列化为文件的类,以维护用户登录数据等。
这个想法是能够始终在同一台机器上而不是其他机器上使用此类恢复和解密数据。
为此目的(如本SO帖子和其他文章中所建议),我遍历了网络接口的硬件地址,同时使用它们来哈希默认的常量密钥:
1 2 3 4 5 6 7 8 9
| byte[] key = getConstKey();
Enumeration<NetworkInterface> inters = networkInterface.getNetworkInterfaces();
while (inters.hasMoreElements()) {
NetworkInterface inter = inters.nextElement();
if (inter.getHardwareAddress() == null) {
continue;
}
hashKeyAccordingToAddress(key, inter.getHardwareAddress());
} |
此方法运行良好并通过了所有测试,直到有一天我将笔记本电脑带出办公室...
显然,当我更改网络时,某些网络地址已更改,或者已添加/删除了接口。我的假设是只有真正的硬件修改才能更改生成的密钥。我想我错了。
有没有办法使它更健壮,例如仅使用趋于更稳定的特定NetworkInterface?还是有更好的方法来生成机器的唯一持久密钥?
更新:更具体地说,当我从办公室外部连接到VPN服务时,问题就开始了。由于一些登录详细信息用于通过此VPN连接到服务,因此我的解决方案变得无用。.
- 您可以使用几乎没有变化的硬件信息,例如HD序列号,主板序列号...
-
java是否利用获取此类信息?我唯一可以获得的硬件信息是inet地址。
-
AFAIK没有API可以直接从Java来执行此操作,因此必须调用OS命令来执行此操作。例如,在Windows中,您可以使用WMI调用,例如:wmic diskdrive get serialnumber
-
Wmic仅在激活,运行WMI并具有相应信息的情况下才起作用-通常是使用Wmic的最糟糕的方法,而且:从网卡收集信息是一个非常糟糕的主意,因为可以完全配置和/或自行配置这些信息,这基本上意味着您的硬件数据可能随时更改。唯一稍微稳定的信息可能是CPU模型,主板模型甚至GPU,但是我要特别小心,因为可以很容易地交换GPU。
-
您可以尝试在添加哈希值之前检查接口的isVirtual是否为false。这样,您应该将自己限制在机器的物理接口上。
-
谢谢,看来我正在寻找解决方案!
-
@Will,我尝试过滤掉isVirtual()接口,但是没有帮助。当我连接到VPN时添加的接口是Microsoft ISATAP adapter,它不是虚拟的。我注意到它的地址值看起来像一个默认值({0,0,0,0,0,0,0,-32}),所以我将这些地址过滤掉了。现在工作正常。
-
Windows网络非常复杂-有时第三方驱动程序的实现非常有问题...甚至像Intel这样的主要NIC制造商在其驱动程序中都存在错误(甚至更糟:NIC属性丢失或错误)...所有这些问题都需要一旦开始过滤网络适配器就被认为是可悲的事实是:您将永远找不到完整,绝对可靠的解决方案。即使您想创建加密/解密密钥或计算机ID,也不要阅读网络适配器信息。多数民众赞成在设计缺陷。使用wmic和类似功能,只会使情况变得更糟。
您可以使用受信任的平台模块(TPM),大多数较新的系统均已提供一个。有关访问TPM的简便方法,请参见此库。将唯一密钥存储在TPM上。
- 看起来很有趣和有用。但是我不确定它能否解决我的所有用例,因为我经常需要序列化加密的复杂对象。而且most newer systems对我来说还不够。我无法保证我的用户系统。