将解密的密钥分配给应用程序中的变量是否安全?

信息安全 应用安全 密钥管理 记忆 钥匙
2021-08-27 12:40:54

假设我从服务器检索了一个加密的密钥。我解密它以获得实际的密钥,将解密的密钥分配给我的应用程序中的一个变量。沿着这个:

const encryptedKey = fetchKeyFromServer();
const secretKey = decrypt(encryptedKey);
//Now, the variable secretKey has the actual secret key in memory

现在,就安全性而言,这是一件易受攻击的事情吗?由于我已将解密的密钥存储在内存中,是否有人可以通过从应用程序的内存中读取来泄露密钥?

但是,如果我不将解密的密钥分配给变量,我应该如何使用密钥?我曾想过将加密密钥分配给变量并在每次需要使用它时对其进行解密。但我仍然不确定这是否是最好的做事方式。

1个回答

是的,这确实意味着密钥将存储在应用程序的内存中。是的,恶意软件(具有足够权限)可能会从那里读取它。这种风险是很难避免的——如果你想使用钥匙,你需要把它放在记忆中,就像你锁门后需要把你的房子钥匙放在口袋里一样。

出于一个原因,这通常被认为不是什么大问题——如果计算机上存在具有 root 权限的恶意软件,它无论如何都已经结束了。那时没有办法保证任何东西的安全。即使您不解密密钥,恶意软件也可以从存储的任何位置读取用于该解密的密钥。

您可以采取以下三项措施来降低风险:

  • 使用某种HSM(感谢DRF指出这一点。)这是最好的方法,但可行性取决于您正在使用的平台。但请注意,具有足够权限读取其他进程内存的恶意软件也可能使用 HSM。因此,这对于恶意软件感染并不是万无一失的。
  • 通过在完成后覆盖内存来最小化密钥在内存中的时间以缩小攻击窗口。(正如MSalters指出的那样,这可能不像听起来那么直接。例如,在 C++ 中,优化器可能会删除未读取的写入,而在 Java 中字符串是不可变的,因此它们不能被覆盖。)
  • 正如Vitor建议的那样,将存储密钥的内存页面标记为不可交换,以便永远不会将其写入磁盘。