如何从文件读取和写入 AES 密钥?
How to read and write an AES key to and from a file?
我正在尝试将 AES 密钥写入文件然后稍后读取。我正在使用 Crypto++ 库,AES 密钥初始化如下。下面,byte
是 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);
但是,我收到一条错误消息:
incompatible operand types : byte* and byte.
我不明白为什么,因为 readed_key
和 key
是用 byte
而不是 byte*
初始化的。
我查看了Crypto++ wiki上的AES,密钥生成如下。我发现我只是在创建密钥(而不是生成密钥):
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*
这让我发疯....
key
是 byte
的 数组 ,即它的类型是 byte[32]
(假设 CryptoPP::AES::MAX_KEYLENGTH
是一个整数常数等于 32)。 byte[N]
在某些情况下会衰减到 byte*
,包括在使用 ==
进行比较期间,例如在您的 if (key == readed_key)
行中。
readed_key
定义为byte
,两者不一样。
此外,您使用 fread (3)
不正确; return 值是读取的项目数,而不是读取的数据。您读取的数据存储在 in
数组中。您需要将 key
的每个元素与 in
的每个元素进行比较,以检查键是否相同。
编辑:感谢@vasek指出比较应该写成
if (memcmp(key, in, size) == 0) { /* keys are equal */ }
由于您使用的是 C++(Crypto++ 库是一个 C++ 库),您可以使用更高级别的抽象来避免使用 malloc
/free
进行手动内存管理并使代码更简单合作:
#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.
How to read and write an AES key to and from a file?
我将避免使用您的代码,因为它主要是 C 代码。 Andrew 指出了它的一些问题,因此没有必要重复它。相反,我将向您展示 Crypto++ 和 C++ 的处理方式。我也会稍微讨论一下 SecByteBlock
。
这是使用源和接收器将数据读入字节数组的 Crypto++ 方法。您可以在 Crypto++ wiki 的 Pipelines 阅读更多关于它们的信息。
byte key[CryptoPP::AES::MAX_KEYLENGTH];
FileSource fs("C:\key.bin", true, new ArraySink(key, sizeof(key)));
这是使用源和接收器将数据写入文件的 Crypto++ 方法。
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());
Because rnd.Generateblock can't convert std::vector< byte >
into
byte*
. This is driving me crazy....
在这里,您需要一个指向第一个元素的非常量指针。获取向量中第一个元素的地址。这同样适用于 std::string
.
std::vector<byte> key(32);
rnd.GenerateBlock(&key[0], key.size());
由于密钥敏感,您应该使用SecByteBlock
。使用完毕后,它会将内存中的密钥归零。
一般来说,如果信息是敏感的,那么你要使用SecBlock<T>
。在 SecByteBlock
的情况下,T
是一个 byte
,SecByteBlock
有一个 typedef。但是你可以用任何东西做一个SecBlock<T>
。
这是使用源和接收器将数据读入 SecByteBlock
的 Crypto++ 方法。
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());
我正在尝试将 AES 密钥写入文件然后稍后读取。我正在使用 Crypto++ 库,AES 密钥初始化如下。下面,byte
是 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);
但是,我收到一条错误消息:
incompatible operand types : byte* and byte.
我不明白为什么,因为 readed_key
和 key
是用 byte
而不是 byte*
初始化的。
我查看了Crypto++ wiki上的AES,密钥生成如下。我发现我只是在创建密钥(而不是生成密钥):
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*
这让我发疯....
key
是 byte
的 数组 ,即它的类型是 byte[32]
(假设 CryptoPP::AES::MAX_KEYLENGTH
是一个整数常数等于 32)。 byte[N]
在某些情况下会衰减到 byte*
,包括在使用 ==
进行比较期间,例如在您的 if (key == readed_key)
行中。
readed_key
定义为byte
,两者不一样。
此外,您使用 fread (3)
不正确; return 值是读取的项目数,而不是读取的数据。您读取的数据存储在 in
数组中。您需要将 key
的每个元素与 in
的每个元素进行比较,以检查键是否相同。
编辑:感谢@vasek指出比较应该写成
if (memcmp(key, in, size) == 0) { /* keys are equal */ }
由于您使用的是 C++(Crypto++ 库是一个 C++ 库),您可以使用更高级别的抽象来避免使用 malloc
/free
进行手动内存管理并使代码更简单合作:
#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.
How to read and write an AES key to and from a file?
我将避免使用您的代码,因为它主要是 C 代码。 Andrew 指出了它的一些问题,因此没有必要重复它。相反,我将向您展示 Crypto++ 和 C++ 的处理方式。我也会稍微讨论一下 SecByteBlock
。
这是使用源和接收器将数据读入字节数组的 Crypto++ 方法。您可以在 Crypto++ wiki 的 Pipelines 阅读更多关于它们的信息。
byte key[CryptoPP::AES::MAX_KEYLENGTH];
FileSource fs("C:\key.bin", true, new ArraySink(key, sizeof(key)));
这是使用源和接收器将数据写入文件的 Crypto++ 方法。
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());
Because rnd.Generateblock can't convert
std::vector< byte >
intobyte*
. This is driving me crazy....
在这里,您需要一个指向第一个元素的非常量指针。获取向量中第一个元素的地址。这同样适用于 std::string
.
std::vector<byte> key(32);
rnd.GenerateBlock(&key[0], key.size());
由于密钥敏感,您应该使用SecByteBlock
。使用完毕后,它会将内存中的密钥归零。
一般来说,如果信息是敏感的,那么你要使用SecBlock<T>
。在 SecByteBlock
的情况下,T
是一个 byte
,SecByteBlock
有一个 typedef。但是你可以用任何东西做一个SecBlock<T>
。
这是使用源和接收器将数据读入 SecByteBlock
的 Crypto++ 方法。
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());