BIO 不刷新 OpenSSL 中的数据
BIO don't flush data in OpenSSL
我正在使用 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
中找不到任何内容。
为什么?
BIO
链接机制用于将过滤器 BIO
前置到 source/sink BIO
。它不是为连接源 BIO
和接收器 BIO
而设计的。
那么你可以做什么:
创建带有最终 BIO
接收器的 BIO
过滤器链。当向链头写入数据时,输入将遍历每个过滤器,直到到达接收器。
创建具有最终 BIO
来源的 BIO
过滤器链。当从链头读取数据时,读取请求将沿着链向上传递到源。然后,从源读取的数据将通过每个过滤器反向遍历链。
但是你不能做什么:
- 创建一个
BIO
链,它以源开始并以接收器结束,中间有过滤器。没有将数据从源自动“泵送”到接收器的机制。
一个附加说明:BIO_f_md
是一个过滤器 BIO
,它计算通过它的数据的摘要,但它不修改数据。所以 BIO
的输出是原始数据,而不是数据的摘要。在使用 BIO_get_md
(reference) 处理所有数据后,可以检索摘要。因此,在您的示例中,即使支持将源链接到接收器,最终的 dgst.txt
也只会包含来自 test.txt
.
的原始数据
要修复您的示例,有两种方法:
方法一
使用摘要 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);
方法二
创建一个带有摘要 BIO
的链,后跟一个用于丢弃数据的特殊接收器 BIO
(BIO_s_null
)。然后我们从源 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);
我正在使用 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
中找不到任何内容。
为什么?
BIO
链接机制用于将过滤器 BIO
前置到 source/sink BIO
。它不是为连接源 BIO
和接收器 BIO
而设计的。
那么你可以做什么:
创建带有最终
BIO
接收器的BIO
过滤器链。当向链头写入数据时,输入将遍历每个过滤器,直到到达接收器。创建具有最终
BIO
来源的BIO
过滤器链。当从链头读取数据时,读取请求将沿着链向上传递到源。然后,从源读取的数据将通过每个过滤器反向遍历链。
但是你不能做什么:
- 创建一个
BIO
链,它以源开始并以接收器结束,中间有过滤器。没有将数据从源自动“泵送”到接收器的机制。
一个附加说明:BIO_f_md
是一个过滤器 BIO
,它计算通过它的数据的摘要,但它不修改数据。所以 BIO
的输出是原始数据,而不是数据的摘要。在使用 BIO_get_md
(reference) 处理所有数据后,可以检索摘要。因此,在您的示例中,即使支持将源链接到接收器,最终的 dgst.txt
也只会包含来自 test.txt
.
要修复您的示例,有两种方法:
方法一
使用摘要 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);
方法二
创建一个带有摘要 BIO
的链,后跟一个用于丢弃数据的特殊接收器 BIO
(BIO_s_null
)。然后我们从源 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);