加密和序列化stl字符串和其他容器

zar*_*zar 4 c++ encryption serialization stl

我在stl容器中有数据(向量).向量中的每个节点都是一个也包含stl字符串的结构.

struct record
{
string name;
string location;
int salary;
}

vector< record > employees;
Run Code Online (Sandbox Code Playgroud)

我想序列化员工,但我也希望在序列化之前对其进行加密.

我的加密函数如下所示:

Encode(const char * inBfr, const int in_size, char ** outBfr, int& out_size )
Run Code Online (Sandbox Code Playgroud)

通过搜索它看起来像stl标准不需要我的结构的内存是连续的所以我不能只是抓住employees变量的内存.有没有其他智能方法可以使用我的基于stl的结构/容器的编码功能?Encode函数在普通的char*缓冲区中运行对我来说很好,所以我确切地知道进出什么但stl结构不是,我想找到一个很好的方法,所以我可以使用stl与这个函数.

如果有帮助,我也开始使用任何其他stl容器.

Die*_*ühl 12

虽然std::vector<T>保证连续布局元素,但这并没有多大帮助:你所拥有的记录可能包括填充,更重要的是,它会将对象std::string的内容存储在std::string对象外部(如果小字符串优化是使用时,该值可能嵌入在其中,std::string但它也将包含几个字节,这些字节不是std::strings值的一部分).因此,您最好的选择是格式化您的记录并加密格式化的字符串.

格式化是直接的,但我个人会将编码功能封装成一个简单的,std::streambuf以便加密可以通过过滤流缓冲区完成.鉴于您给出的签名,这可能看起来像这样:

class encryptbuf
    : public std::streambuf {
    std::streambuf* d_sbuf;
    char            d_buffer[1024];
public:
    encryptbuf(std::streambuf* sbuf)
        : d_sbuf(sbuf) {
        this->setp(this->d_buffer, this->d_buffer + sizeof(this->d_buffer) - 1);
    }
    int overflow(int c) {
        if (c != std::char_traits<char>::eof()) {
            *this->pptr() = std::char_traits<char>::to_char_type(c);
            this->pbump(1);
        }
        return this->pubsync()? std::char_traits<char>::eof(): std::char_traits<char>::not_eof(c);
    }
    int sync() {
        char* out(0);
        int   size(0);
        Encode(this->pbase(), this->pptr() - this->pbase(), &out, size);
        this->d_sbuf->sputn(out, size);
        delete[] out; // dunno: it seems the output buffer is allocated but how?
        this->setp(this->pbase(), this->epptr());
        return this->d_sbuf->pubsync();
    }
};

int main() {
    encryptbuf    sbuf(std::cout.rdbuf());
    std::ostream eout(&sbuf);
    eout << "print something encoded to standard output\n" << std::flush;
}
Run Code Online (Sandbox Code Playgroud)

现在,为打印到a的记录创建输出运算符std::ostream可用于创建编码

  • 有那么一刻,我震惊地遇到了一个用户,他知道这些流如何运作得很好,只需发布​​这样的答案.然后我看到了这个名字:D (4认同)

Jer*_*fin 6

将结构序列化为字符串,然后加密字符串可能最简单.例如:

std::ostringstream buffer;

buffer << a_record.name << "\n" << a_record.location << "\n" << a_record.salary;

encode(buffer.str().c_str(), buffer.str().length(), /* ... */);
Run Code Online (Sandbox Code Playgroud)

如果是我,我可能会写encode(或者至少是它的包装器)来获取矢量,字符串或流中的输入(并且可能产生输出).

如果你想要雄心勃勃,还有其他可能性.首先,@ MomooDuck提出了一个很好的观点,即为课程重载通常是值得operator<<的,而不是一直处理单个项目.这通常是一个类似于上面的小功能:

std::ostream &operator<<(std::ostream &os, record const &r) { 
    return os << r.name << "\n" << r.location << "\n" << r.salary;
}
Run Code Online (Sandbox Code Playgroud)

使用这个,你只需要:

std::ostringstream os;
os << a_record;

encode(os.str().c_str(), os.str().length(), /* ... */);
Run Code Online (Sandbox Code Playgroud)

其次,如果你想要真正雄心勃勃,你可以将加密(例如)加入一个codecvt方面,这样你就可以在将它写入流时自动加密所有数据,并在你重新读取时对其进行解密.另一种可能性是将加密构建到过滤streambuf对象中.该codecvt方面是可能是理论上应该是首选的方法,但streambuf几乎可以肯定是更容易实现,在与有关无关的"东西"少.

  • @zadane:你几乎需要先将它们序列化,然后加密.您可以单独加密记录,也可以将所有记录序列化为一个大字符串,然后对其进行加密 - 但在加密之前,您几乎需要将其"展平". (2认同)