【问题标题】:Safely zeroing buffers after working with crypto/*使用 crypto/* 后安全归零缓冲区
【发布时间】:2019-11-14 06:45:09
【问题描述】:

有没有办法将包含 e 的缓冲区归零? G。之后的私钥 使用它们并确保编译器不会将归零代码删除为 没用过?有件事告诉我一个简单的:

copy(privateKey, make([]byte, keySize))

不能保证留在那里。

【问题讨论】:

  • 为什么编译器会删除不是空操作的代码?这个具体的例子会破坏很多东西。
  • @NathanVērzemnieks 不确定你的意思。 C 编译器一直这样做,这是一个已知问题。例如,请参阅this article
  • 啊,这很有趣!不是我以前遇到过的。我很好奇 - 而不是试图推断假设的编译器可能会或可能不会做什么,并欺骗他们认为使用了归零缓冲区,为什么不实际使用它呢?比如说,将它传递给一个将其字节值添加到全局计数器的函数,然后如果计数器值非零,则发生恐慌。当然,这会增加一些计算量,但对于大多数目的来说,它似乎应该是相对微不足道的。

标签: security go cryptography


【解决方案1】:

听起来您想防止敏感数据留在内存中。但是您是否考虑过数据可能已被复制或交换到磁盘?

出于这些原因,我使用https://github.com/awnumar/memguard 包。 它提供了在不再需要时销毁数据的功能,同时保持数据安全。

你可以在这里阅读它的背景; https://spacetime.dev/memory-security-go

【讨论】:

    【解决方案2】:

    在将缓冲区归零并将其传递给另一个函数之后,如何检查(部分)缓冲区的内容?例如:

    copy(privateKey, make([]byte, keySize))
    
    if privateKey[0] != 0 {
        // If you pass the buffer to another function,
        // this check and above copy() can't be optimized away:
        fmt.Println("Zeroing failed", privateKey[0])
    }
    

    为了绝对安全,您可以将传递的缓冲区内容与随机字节进行异或运算,但如果 / 由于未优化清零,则永远不会到达 if 正文。

    您可能认为一个非常智能的编译器可能会推断出上述copy()privateKey[0] 并因此确定条件始终为假并仍将其优化掉(尽管这不太可能)。对此的解决方案不是使用make([]byte, keySize),而是使用例如来自全局变量或函数参数(其值只能在运行时确定)的切片,因此编译器不能足够聪明地推断条件在编译时总是为假。

    【讨论】:

    • 我自己也想过这一点,但足够智能的编译器也可以推断出这一点。我正在寻找“由规范保证”的东西,但如果没有这样的功能,我也可以接受。
    • @Ainar-G 如果你有一个包级变量var ZeroBuf []byte,编译器就无法优化复制它,因为任何其他包都可能在运行时随时更改它的值.
    • GC 可能会复制密钥,将原始密钥留在后面等待释放。 current Go 确实不使用复制 GC(所以只要你不超过切片的当前上限,底层数组就不会移动)但我在这里真的很谨慎.
    猜你喜欢
    • 2014-03-26
    • 1970-01-01
    • 2015-01-24
    • 1970-01-01
    • 2016-12-26
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    相关资源
    最近更新 更多