Haskell 或 OCAML 可以处理敏感数据而不会通过垃圾收集泄漏吗?

use*_*215 16 ocaml garbage-collection haskell memory-management

我会做这样的事情(伪代码):

1. load sensitive encrypted data from file
2. decrypt the data
3. do something with the unencrypted data
4. override the data safely / securely (for example with random data)
Run Code Online (Sandbox Code Playgroud)

敏感数据在内存中保持原样(未加密)的时间应尽可能短。

不得以任何方式泄露明文数据。

A. 这样的程序可以用 Haskell 或 OCAML 编写吗?

B. 是否可以防止数据泄露,即被垃圾收集器在后台静默复制?

C. 能否在内存中正确覆盖纯数据?

据我所知,垃圾收集器 (GC) 可以在后台静默复制数据。我猜这是由分代 GC 算法完成的,但我不确定。

我知道如果攻击者设法在正确的时间/状态获取程序的内存,攻击者仍然有可能获得纯数据。我只是考虑这样做以提高安全性,因为我没有控制上下文(即操作系统、交换等)。

leh*_*ins 12

我已经在评论中提到了这一点,但我认为这是一个非常好的问题,值得回答。

已经存在ScrubbedBytes具有以下属性的数据类型:

  • 它是用 分配的newAlignedPinnedByteArray#,这意味着虽然新分配的MutableByteArray#在你的代码中的任何地方被引用,但它不会被 GC,但它也不会被移动或复制。
  • 分配后,会创建一个弱指针,mkWeak#并将终结器添加到新分配的内存中。这意味着每当您的代码中不再引用已清理的字节时,并且在 GC 释放内存之前,将调用清理器,将零写入内存。
  • 相等不会短路,从而防止时序攻击。

这个洗涤器有一个小问题。它不会被执行的可能性很小,特别是如果程序在 GC 应该清理内存之前退出。(查看有关弱指针的更多信息。)因此,我建议使用bracket模式来实现它。以下是如何使用primitive包完成它:

import Control.Exception
import Control.Monad.Primitive (RealWorld)
import qualified Data.Primitive.ByteArray as BA

withScrubbedMutableByteArray ::
     Int -- ^ Number of bytes
  -> (BA.MutableByteArray RealWorld -> IO a)
  -- ^ Action to execute
  -> IO a
withScrubbedMutableByteArray c f = do
  mba <- BA.newPinnedByteArray c
  f mba `finally` BA.setByteArray mba 0 c (0 :: Word8)
Run Code Online (Sandbox Code Playgroud)

使用finally更安全的原因是因为您将有更强的保证将内存清零。例如,用户在正确的设置中按 Ctrl-C 不会阻止洗涤器运行。


ivg*_*ivg 5

在 OCaml 中,可以使用不受 GC 控制、从不复制、也从不检查的 Bigarray 轻松完成。您可以使用Unix.map_file加载它并使用 ocaml-struct很好地处理加载的数据(如果它是结构化的)。OCaml 广泛用于编写与安全相关的低级代码,请参阅Mirage项目(它有大量与加密相关的库)、ocaml-tls是 OCaml 中 TLS 协议的纯实现,以及使用 OCaml 作为TLS 协议的Project Everest目标语言。

在解密/加密和以其他方式处理秘密数据时,您应该小心,不要将其放入盒装类型中,包括字符串和 int64 整数。如果您查看mirage-crypto,您会发现所有算法都仅使用整数来实现,这些整数表示为立即数并且永远不会被 GC 触及。