如何编写密码安全类?

ere*_*eOn 14 c++ memory string

这个问题遵循@sharptooth在这个相关问题中提出的建议.

可以std::string调整,以便它变得密码安全吗?

如果没有,什么是写有密码处理类(因此类,它大关心它写入内存和破坏之前将其清除)的指导方针?

ybu*_*ill 20

是的,首先定义一个自定义分配器:

template <class T> class SecureAllocator : public std::allocator<T>
{
public:
    template<class U> struct rebind { typedef SecureAllocator<U> other; };

    SecureAllocator() throw() {}
    SecureAllocator(const SecureAllocator&) throw() {}
    template <class U> SecureAllocator(const SecureAllocator<U>&) throw() {}

    void deallocate(pointer p, size_type n)
    {
        std::fill_n((volatile char*)p, n*sizeof(T), 0);
        std::allocator<T>::deallocate(p, n);
    }
};
Run Code Online (Sandbox Code Playgroud)

此分配器在释放之前将内存清零.现在你输入type:

typedef std::basic_string<char, std::char_traits<char>, SecureAllocator<char>> SecureString;
Run Code Online (Sandbox Code Playgroud)

但是有一个小问题,std :: string可能会使用小字符串优化并在其内部存储一些数据,而无需动态分配.因此,您必须在销毁时明确清除它或使用我们的自定义分配器在堆上分配:

int main(int, char**)
{
    using boost::shared_ptr;
    using boost::allocate_shared;
    shared_ptr<SecureString> str = allocate_shared<SecureString>(SecureAllocator<SecureString>(), "aaa");

}
Run Code Online (Sandbox Code Playgroud)

这可以保证在释放之前将所有数据归零,例如,包括字符串的大小.

  • 不要使用`std :: fill_n`,使用类似`SecureZeroMemory()`(http://msdn.microsoft.com/en-us/library/aa366877(VS.85).aspx) - 与`std: :fill_n`编译器可能会优化擦除. (5认同)
  • @sharptooth SecureZeroMemory 不是标准的,并且 volatile 会阻止优化。是的,如果没有系统调用,一些数据可能会在 CPU 刷新缓存之前保留在内存中。 (3认同)
  • 分配器应该通过调用[`mlock`](http://man7.org/linux/man-pages/man2/mlock.2.html)来禁用交换它分配内存的页面.否则,数据可能会写入磁盘. (3认同)
  • @ybungalobill:不确定,但看起来像是一种利用`volatile`的好方法. (2认同)