Hy i目前在c中编写一个程序,该程序应该从签名文件+公钥验证文件。
我从openssl二进制代码中复制了以下代码:
#include <BeTypes.h>
#include <mtypes.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/crypto.h>
typedef struct {
char *signature;
int len;
} Signature;
#define BUFFER_SIZE 1024*8
/**
* @brief reads a public key from PEM File
*
* @return EVP_PKEY containing the public key.
* Return Value must be released with EVP_PKEY_free();
*/
static EVP_PKEY *getPubKeyFromPEM(const char *filename) {
EVP_PKEY *pubkey = NULL;
BIO *bio_publickey = BIO_new_file(filename, "r");
pubkey = PEM_read_bio_PUBKEY(bio_publickey, NULL, NULL, NULL);
BIO_free(bio_publickey);
return pubkey;
}
/**
* @brief Reads Signatuer File
* @param filename_signature File path to signature file
* @param signature_maxlen Max Len for the Signature Buffer
* @return Signature containing len and the signature data
* Return Value must be released with OPENSSL_free()
*/
static Signature *getSignature(const char *filename_signature, int signature_maxlen) {
BIO *bio_signature = NULL;
Signature *ret;
//allocate return Object:
ret = OPENSSL_malloc(sizeof(Signature));
if(ret == NULL) {
return NULL;
}
//init return Object:
ret->signature = OPENSSL_malloc(signature_maxlen);
bio_signature = BIO_new_file(filename_signature, "rb");
ret->len = BIO_read(bio_signature, ret->signature, signature_maxlen);
//Free Read
BIO_free(bio_signature);
return ret;
}
BOOL thrusted_checkFile(const char *filename_pubKey, const char *filename_signature, const char *filename_signedfile) {
BOOL valid = FALSE;
EVP_PKEY *pubkey = NULL;
Signature *signature = NULL;
EVP_MD_CTX *ctx_md = NULL;
BIO *biomd;
EVP_PKEY_CTX *pctx = NULL;
BIO *input;
BIO *in;
EVP_MD_CTX *tctx;
const EVP_MD *md;
unsigned char *buf = NULL;
EVP_MD_CTX *ctx;
//Load Public key:
pubkey = getPubKeyFromPEM(filename_pubKey);
if(pubkey == NULL) {
return FALSE;
}
signature = getSignature(filename_signature, EVP_PKEY_size(pubkey));
//creates the thing whoever this thing is...
biomd = BIO_new(BIO_f_md());
if(biomd == NULL) {
return FALSE;
}
//Create HashAlgorythm Context
if(!BIO_get_md_ctx(biomd, &ctx_md)){
return FALSE;
}
//Init pctx:
if(!EVP_DigestVerifyInit(ctx_md, &pctx, NULL, NULL, pubkey)) {
return FALSE;
}
in = BIO_new(BIO_s_file());
if(in == NULL) {
return FALSE;
}
input = BIO_push(biomd, in);
BIO_get_md_ctx(biomd, &tctx);
md = EVP_MD_CTX_md(tctx);
if(BIO_read_filename(in, filename_signedfile) <= 0) {
return FALSE;
}
buf = OPENSSL_malloc(BUFFER_SIZE);
if(buf == NULL) {
return FALSE;
}
while(TRUE) {
int i = BIO_read(input, (char *)buf, BUFFER_SIZE);
if(i < 0) {
return FALSE;
} else if(i == 0) {
break;
}
}
BIO_get_md_ctx(input, &ctx);
valid = EVP_DigestVerifyFinal(ctx, signature->signature, signature->len) > 0;
printf("No Error on check!\n");
return valid;
}
我现在尝试理解这段代码并尝试简化它。
我对一个bio的理解就像一个流,它可以在java中有一些像map函数的东西,所以你给它一个输入,它使用一个由ctx和你输出的输出选择的函数转换后的价值观。
我不明白的是,BIO_push的作用是什么? 当我直接使用biomd时,我不明白这种差异。
答案 0 :(得分:0)
实际上BIO不像是具有地图功能的流。 BIO是一个缓冲IO,用作OpenSSL库的输入或输出内存。
BIO_PUSH将第二个参数附加到第一个参数。这意味着在您的代码中“BIO in”附加到“BIO biomd”。
您可以在BIO_PUSH manpage中找到有关它的更多信息:
对于这些例子,假设md1和md2是摘要BIO,b64是a base64 BIO和f是文件BIO。
如果致电:
BIO_push(b64,f);然后新链将成为b64链。后 拨打电话BIO_push(md2,b64); BIO_push(md1,md2);新的连锁店 是md1-md2-b64-f。写入md1的数据将被md1和md2消化, base64编码并写入f。应该注意阅读 导致数据反向传递,即读取数据 从f,base64解码并被md1和md2消化。如果通话:
BIO_pop(MD2);该调用将返回b64,新链将返回 md1-b64-f数据可以像以前一样写入md1。