hau*_*ron 25 c++ stdstring c++11
考虑一个场景,std::string用于存储秘密.一旦它被消耗并且不再需要它,最好清理它,即覆盖包含它的内存,从而隐藏秘密.
std::string提供一个函数const char* data()返回指向(自C++ 11)连续内存的指针.
现在,由于内存是连续的,并且由于范围结束,变量将在清理后立即销毁,因此安全:
char* modifiable = const_cast<char*>(secretString.data());
OpenSSL_cleanse(modifiable, secretString.size());
Run Code Online (Sandbox Code Playgroud)
根据这里引用的标准:
$ 5.2.11/7 -注意:根据目的,通过指针,左值或指针以从得到的数据成员的写操作的类型
const_cast即擅自抛弃一个const-qualifier68可能会产生不确定的行为(7.1.5.1).
否则会提出建议,但是上面的条件(连续的,待去除的)是否安全?
Gal*_*lik 17
这可能是安全的.但不保证.
然而,因为C++11,一个std::string必须这样你就可以使用它的第一个元素的地址安全存取其内部的阵列实现为邻接数据&secretString[0].
if(!secretString.empty()) // avoid UB
{
char* modifiable = &secretString[0];
OpenSSL_cleanse(modifiable, secretString.size());
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*ely 14
标准明确表示你不得写入const char*返回的data(),所以不要这样做.
有一种非常安全的方法可以获得可修改的指针:
if (secretString.size())
OpenSSL_cleanse(&secretString.front(), secretString.size());
Run Code Online (Sandbox Code Playgroud)
或者,如果字符串可能已经缩小,并且您希望确保其整个容量被擦除:
if (secretString.capacity()) {
secretString.resize(secretString.capacity());
OpenSSL_cleanse(&secretString.front(), secretString.size());
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*mas 13
std :: string是存储机密的不良选择.由于字符串是可复制的,有时副本不被注意,你的秘密可能"得到腿".此外,字符串扩展技术可能会导致您的秘密片段(或全部)的多个副本.
经验决定了一个可移动的,不可复制的,擦拭干净的摧毁,非智能(没有棘手的副本)类.
Dav*_*aim 12
您可以使用std::fill垃圾填充字符串:
std::fill(str.begin(),str.end(), 0);
Run Code Online (Sandbox Code Playgroud)
请注意,简单地清除或缩小字符串(使用clear或等方法shrink_to_fit)并不能保证字符串数据将从进程内存中删除.恶意进程可能会转储进程内存,如果字符串未被正确覆盖,则可以提取秘密.
奖励:有趣的是,出于安全原因而丢弃字符串数据的能力迫使某些编程语言(如Java)返回密码char[]而不是String.在Java中,String是不可变的,因此"废弃"它将创建一个新的字符串副本.因此,您需要一个可修改的对象,例如char[]不使用copy-on-write.
编辑:如果您的编译器确实优化了此调用,您可以使用特定的编译器标志来确保不会优化废弃函数:
#ifdef WIN32
#pragma optimize("",off)
void trashString(std::string& str){
std::fill(str.begin(),str.end(),0);
}
#pragma optimize("",on)
#endif
#ifdef __GCC__
void __attribute__((optimize("O0"))) trashString(std::string& str) {
std::fill(str.begin(),str.end(),0);
}
#endif
#ifdef __clang__
void __attribute__ ((optnone)) trashString(std::string& str) {
std::fill(str.begin(),str.end(),0);
}
#endif
Run Code Online (Sandbox Code Playgroud)