代码之家  ›  专栏  ›  技术社区  ›  EinderJam

如何在文件中读写AES密钥?

  •  2
  • EinderJam  · 技术社区  · 7 年前

    我试图将AES密钥写入文件,然后稍后读取。我使用的是Crypto++库,AES密钥初始化如下。在下面 byte 是的typedef unsigned char

    byte key[CryptoPP::AES::MAX_KEYLENGTH]
    

    密钥长度为32字节。我尝试用以下内容将其写入文件:

    FILE* file = fopen("C:\\key", "wb");
    fwrite(key, 1, sizeof(key), file);
    fclose(file);
    

    并使用以下方法进行恢复:

    FILE* read_file = fopen("C:\\key", "rb");
    fseek(read_file, 0, SEEK_END);
    long int size = ftell(read_file);
    fclose(read_file);
    
    read_file = fopen("C:\\key", "rb");
    unsigned char * in = (unsigned char *)malloc(size);
    byte readed_key = fread(in, sizeof(unsigned char), size, read_file);
    fclose(read_file);
    if (key == readed_key)
    {
        cout << "this is the right key !";
    }
    free(in);
    

    但是,我收到一条错误消息:

    我不明白为什么,因为 readed_key key 字节 byte* .


    AES 在Crypto++wiki上,密钥生成如下。我发现我只是在创建密钥(而不是生成它):

    SecByteBlock key(0x00, AES::MAX_KEYLENGTH);
    rnd.GenerateBlock( key, key.size() );
    

    有了它我就用不上了

    std::vector<byte> key(32);
    rnd.GenerateBlock(key, key.size());
    

    因为 rnd.Generateblock std::vector< byte > into byte*

    2 回复  |  直到 7 年前
        1
  •  4
  •   jww avp    7 年前

    如何在文件中读写AES密钥?

    SecByteBlock 一点


    以下是使用信源和接收器将数据读入字节数组的加密++方法。您可以在以下网站上阅读更多关于它们的信息: Pipelines 在Crypto++wiki中。

    byte key[CryptoPP::AES::MAX_KEYLENGTH];
    FileSource fs("C:\\key.bin", true, new ArraySink(key, sizeof(key)));
    

    byte key[CryptoPP::AES::MAX_KEYLENGTH];
    ArraySource as(key, sizeof(key), true, new FileSink("C:\\key.bin"));
    

    以下是使用流将数据读入字节数组的C++方法。它来自 Reading and writing binary file

    byte key[CryptoPP::AES::MAX_KEYLENGTH];
    std::ifstream fs("C:\\key.bin", std::ios::binary);
    fs.read(key, sizeof(key));
    

    以下是使用流将数据写入文件的C++方法。

    byte key[CryptoPP::AES::MAX_KEYLENGTH];
    std::ofstream fs("C:\\key.bin", std::ios::binary);
    fs.write(key, sizeof(key));
    

    std::vector<byte> key(32);
    rnd.GenerateBlock(key, key.size());
    

    因为rnd。Generateblock无法转换 std::vector< byte > 进入 byte* .这让我快疯了。。。。

    这里,您需要一个指向第一个元素的非常量指针。取向量中第一个元素的地址。这同样适用于 std::string .

    std::vector<byte> key(32);
    rnd.GenerateBlock(&key[0], key.size());
    

    。一旦使用完,它会将内存中的密钥归零。

    一般来说,如果信息是敏感的,那么您希望使用 SecBlock<T> 假使 SecByteBlock公司 T 是一个 byte 还有一个typedef SecByteBlock公司 .但是你可以 SecBlock<T> 什么都没有。

    SecByteBlock公司

    SecByteBlock key(AES::MAX_KEYLENGTH);
    FileSource fs("C:\\key.bin", true, new ArraySink(key.begin(), key.size()));
    

    SecByteBlock公司 在构造时将元素初始化为已知值。您正在使用以下功能。所有元素初始化为 0x00 .

    SecByteBlock key(0x00, AES::MAX_KEYLENGTH);
    rnd.GenerateBlock(key, key.size());
    

    放弃初始化。只需请求一个未初始化的内存块:

    SecByteBlock key(AES::MAX_KEYLENGTH);
    rnd.GenerateBlock(key, key.size());
    
        2
  •  2
  •   Andrew    7 年前

    key 是一个 大堆 byte ,即其类型为 byte[32] (假设 CryptoPP::AES::MAX_KEYLENGTH 是等于32的整数常数)。 byte[N] byte* 在某些情况下,包括在比较过程中使用 == 比如在你的 if (key == readed_key) 线

    readed_key 定义为

    此外,您正在使用 fread (3) 错误;返回值是读取的项数,而不是读取的数据。您读取的数据存储在 in 大堆您需要比较 钥匙 在里面

    编辑: @vasek 指出比较应该写出来

    if (memcmp(key, in, size) == 0) { /* keys are equal */ }
    

    由于您使用的是C++(Crypto++库是C++库),因此可以使用更高级别的抽象来避免使用 malloc free 并使代码更易于使用:

    live example :

    #include <cstdint>
    #include <fstream>
    #include <iostream>
    #include <vector>
    
    using byte = char;
    
    int main() {
        std::vector<byte> key(32);
        // Code would go here to generate the `key`
        // ...
    
        {
            std::ofstream out("C:\\key", std::ios::out | std::ios::binary);
            out.write(key.data(), key.size());
        } // file is closed automatically here!
    
        std::vector<byte> read_key(32);
        {
            std::ifstream in("C:\\key", std::ios::in | std::ios::binary);
            in.read(read_key.data(), read_key.size());
        }
    
        if (key == read_key) {
            std::cout << "Keys are equal!\n";
        }
    
        return 0;    
    }
    

    std::vector<byte> 处理内存分配(您只需告诉它构造函数中的大小;使用 .data() 获取指向内容的指针;完整密钥的比较免费提供 std::vector operator== ),以及C++iostreams read write fread / fwrite 。您仍然可以进行搜索以确定密钥大小;我把它作为一个 exercise to the reader