我使用BIO来使用OpenSSL计算某个文件的摘要。我的代码如下:
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
int main(){
BIO* bio_infile;
bio_infile = BIO_new_file("test.txt", "rb");
BIO* bio_md = BIO_new(BIO_f_md());
BIO_set_md(bio_md, EVP_sha1());
BIO* bio_outfile;
bio_outfile = BIO_new_file("dgst.txt","w");
BIO_push(bio_md, bio_outfile);
BIO_push(bio_infile, bio_md);
BIO_flush(bio_infile);
BIO_flush(bio_md);
BIO_free(bio_infile);
BIO_free(bio_md);
BIO_free(bio_outfile);
return 0;
}但是,当我的程序用完时,我在文件dgst.txt中找不到任何东西。
为什么?
发布于 2020-09-13 16:30:50
BIO链接机制用于将BIO预先筛选到源/接收器BIO。它不是为将源BIO与接收器BIO连接起来而设计的。
所以你能做的是:
BIO接收器创建一个BIO过滤器链。当将数据写入链头时,输入将遍历每个过滤器,直到到达接收器为止。BIO源创建一个BIO过滤器链。当从链的头读取数据时,读取请求将沿着链传递到源。然后,从源读取的数据将通过每个过滤器沿着相反的方向遍历链。但你不能做的是:
BIO链,该链以源开始,以带过滤器的接收器结束。没有自动将数据从源“泵”到接收器的机制。另一个注意事项:BIO_f_md是一个筛选器BIO,它计算通过它传递的数据的摘要,但它不修改数据。因此,BIO的输出是原始数据,而不是数据摘要。在使用BIO_get_md (参考文献)处理了所有数据之后,可以检索摘要。因此,在您的示例中,即使支持将源链接到接收器,最终的dgst.txt也只包含来自test.txt的原始数据。
要修复您的示例,有两种方法:
方法1
使用摘要BIO创建一个链,然后是输入文件的源BIO。然后,我们可以从摘要BIO中读取数据,它内部从源BIO中提取数据。我们读取数据并立即丢弃它,直到处理完完整的文件为止。然后,我们可以从摘要BIO中检索摘要。
// Create chain: Digest -> Source File
BIO* bio_infile;
bio_infile = BIO_new_file("test.txt", "rb");
BIO* bio_md = BIO_new(BIO_f_md());
BIO_set_md(bio_md, EVP_sha1());
BIO* head = BIO_push(bio_md, bio_infile);
// Read from head of chain
std::array<char,1024> buf{};
int read;
while ((read = BIO_read(head, buf.data(), buf.size())) > 0) {
// Ignore buffer, we only want the data to pass throug the digest BIO
}
// Read result from digest BIO
EVP_MD *md;
BIO_get_md(bio_md, &md);
std::array<char, EVP_MAX_MD_SIZE> md_buf{};
int mdlen = BIO_gets(bio_md, md_buf.data(), md_buf.size());
// Print digest to stdout
for (int i = 0; i < mdlen; i++) {
printf("%02x", static_cast<uint8_t>(md_buf[i]));
}
printf("\n");
// Cleanup
BIO_free_all(head); 方法2
使用摘要BIO创建一个链,然后是一个用于丢弃数据的特殊接收器BIO (BIO_s_null)。然后,我们从源BIO中读取输入文件的数据(没有任何链接),并将数据写入摘要BIO。写入的数据通过摘要BIO传递到接收器BIO,接收器BIO将丢弃数据。处理完所有数据后,我们可以从摘要BIO检索摘要。
// Create chain: Digest -> Null Sink
BIO* bio_infile;
bio_infile = BIO_new_file("test.txt", "rb");
BIO* bio_md = BIO_new(BIO_f_md());
BIO_set_md(bio_md, EVP_sha1());
BIO* bio_null = BIO_new(BIO_s_null());
BIO* head = BIO_push(bio_md, bio_null);
// Read from file and write to chain
std::array<char,1024> buf{};
int read;
while ((read = BIO_read(bio_infile, buf.data(), buf.size())) > 0) {
BIO_write(head, buf.data(), read);
}
// Read result from digest BIO
EVP_MD *md;
BIO_get_md(bio_md, &md);
std::array<char, EVP_MAX_MD_SIZE> md_buf{};
int mdlen = BIO_gets(bio_md, md_buf.data(), md_buf.size());
// Print digest to stdout
for (int i = 0; i < mdlen; i++) {
printf("%02x", static_cast<uint8_t>(md_buf[i]));
}
printf("\n");
// Cleanup
BIO_free(bio_infile);
BIO_free_all(head); https://stackoverflow.com/questions/63296500
复制相似问题