2016-09-15 89 views
1

Hy我目前在c中编写一个应该从签名文件+公钥验证文件的程序。关于理解bio_push的openssl问题

我复制toghether从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; 
} 

我现在试着去了解这个代码并且设法simpliefy它。

  1. 我的生物的理解就像一个流至极可以像Java中的地图功能的一些东西,所以你给它它采用了功能至极由CTX和你有输出choosen输入转换的值。

  2. 我不明白的是,BIO_push的功能是什么? 我不明白直接使用biomd时的差异。

回答

0

实际上BIO并不像一个具有地图功能的流。 BIO是一个缓冲IO,用作OpenSSL库的输入或输出内存。

BIO_PUSH将第二个参数附加到第一个参数。这意味着在你的代码中“BIO in”附加到“BIO biomd”。

您可以在BIO_PUSH manpage找到更多关于它的信息:

对于这些示例假设MD1和MD2是消化BIOS,B64是 的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。