此问题遵循@sharptooth在this related question中提出的建议。如何编写密码安全的类?
std::string
可以调整,以便它变成密码安全的吗?
如果不是,编写密码处理类的准则是什么(因此一个类需要非常小心它写入内存的内容并在破坏前清除它)?
此问题遵循@sharptooth在this related question中提出的建议。如何编写密码安全的类?
std::string
可以调整,以便它变成密码安全的吗?
如果不是,编写密码处理类的准则是什么(因此一个类需要非常小心它写入内存的内容并在破坏前清除它)?
是,首先定义一个自定义分配器:
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);
}
};
这个分配器重新分配之前归零内存。现在您的typedef:
typedef std::basic_string<char, std::char_traits<char>, SecureAllocator<char>> SecureString;
然而,有一个小问题,的std :: string可以使用小串的优化和一些数据存储内部本身,没有动态分配。所以你必须明确地将其清除销毁或堆中与我们的自定义分配器分配:
int main(int, char**)
{
using boost::shared_ptr;
using boost::allocate_shared;
shared_ptr<SecureString> str = allocate_shared<SecureString>(SecureAllocator<SecureString>(), "aaa");
}
这可以保证所有的数据被释放之前归零,包括字符串的大小,例如。
不要使用'std :: fill_n',使用类似'SecureZeroMemory()'(http://msdn.microsoft.com/en-us/library/aa366877(VS.85).aspx) - 与'std :: fill_n'编译器可能会优化删除。 – sharptooth 2010-09-24 09:21:09
当调用代码导致字符串缩短时,强制'std :: string'擦除空格 - 例如删除前N个元素,因此尾部移动“向左”并在右侧留下字符“ “? – sharptooth 2010-09-24 09:22:01
@sharptooth SecureZeroMemory不是标准的,volatile会阻止优化。是的,如果没有系统调用,则在CPU刷新缓存之前,有些数据可能会保留在内存中。 – ybungalobill 2010-09-24 09:23:50
1)使用std:wstring,2)按0x2022而不是密码符号:o)严重的是,如果您担心其他进程从您的内存中嗅探到某些内容,请添加/删除一些掩码(xor?) – alxx 2010-09-24 09:04:12
@alxx :如何使用'std :: wstring'而不是'std :: string'更安全?!我错过了什么吗? – ereOn 2010-09-24 09:06:18
0x2022是子弹符号。得到它? :) – alxx 2010-09-24 09:10:46