2016-09-15 57 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。