openssl相關(guān)數(shù)據(jù)結(jié)構(gòu)的設(shè)計

hash表

數(shù)據(jù)結(jié)構(gòu):使用鏈表數(shù)組實現(xiàn)

typedef struct lhash_node_st{
    void* data;
    struct lhash_node_st *next;
#ifndef OPENSSL_NO_HASH_COMP
    unsigned long hash;
#endif
}LHASH_NODE;

typedef struct lhash_st{
    LHASH_NODE **b;//整個hash表維護一個鏈表數(shù)組
    LHASH_COMP_FN_TYPE comp;//數(shù)據(jù)查找的比較函數(shù)句柄
    LHASH_HASH_FN_TYPE hash;//用于存放計算hash值函數(shù)的地址?
    unsigned int num_nodes;//當前節(jié)點數(shù)量
    unsigned int num_all_nodes;//節(jié)點容量
    unsigned int p;
    unsigned int pmax;
    unsigned long up_load;/*load times 256*/
    unsigned long down_load;/*load times 256*/
    unsigned long num_items;
    unsigned long num_expands;
    unsigned long num_expand_reallocs;
    unsigned long num_contracts;
    unsigned long num_constract_reallocs;
    unsigned long  num_hash_calls;
    unsigned long num_comp_calls;
    unsigned long num_insert;
    unsigned long num_replace;
    unsigned long num_delete;
    unsigned long num_no_delete;
    unsigned long num_retrieve;
    unsigned long num_retrieve_miss;
    unsigned long num_hash_comps;
    int error;
}LHASH;

相關(guān)接口

- LHASH *lh_new(LHASH_HASH_FN_TYPE h,LHASH_COMP_FN_TYPE c);
- void *lh_delte(LHASH *lh, const void *data);
- void *lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func);
- void *lh_insert(LHASH *lh, void *data);
- void *lh_retrieve(LHASH *lh, const void *data);

內(nèi)存分配

內(nèi)存相關(guān)數(shù)據(jù)結(jié)構(gòu)

typedef struct app_mem_info_st{
    unsigned long thread;
    const char *file;
    int line;
    cosnt char *info;
    struct app_mem_info_st *next;
    int references;
    
}APP_INFO;

typedef struct mem_st{
    void *addr;//分配內(nèi)存的地址
    int num;//分配內(nèi)存的大小
    const char *file;//分配內(nèi)存映射的文件
    int line;//分配內(nèi)存的行號??
    unsigned long thread;//分配內(nèi)存的線程ID
    unsigned long order;//第幾次分配內(nèi)存
    time_t time;//內(nèi)存分配時間
    APP_INFO *app_info;//鏈表。存放用戶應(yīng)用信息,如文件、行號、以及其他
    unsigned int references;//被引用次數(shù)
}MEM;

內(nèi)存操作相關(guān)接口

  • CRYPTO_mem_ctrl:控制內(nèi)存分配時是否記錄內(nèi)存信息,用于查找內(nèi)存泄漏
  • CRYPTO_is_mem_check_on:檢查內(nèi)存信息記錄是否打開
  • CRYPTO_dbg_malloc:用于分配內(nèi)存
  • CRYPTO_dbg_free:用于釋放內(nèi)存
  • CRYPTO_mem_leaks:將內(nèi)存泄漏輸出到BIO(后面會介紹)
  • CRYPTO_mem_leaks_fp:將內(nèi)存泄露輸出到文件中
  • CRYPTO_mem_leaks_cb:設(shè)定自定義內(nèi)存泄漏處理的回調(diào)函數(shù)

抽象IO(BIO)

對于io類型的抽象封裝,包括:內(nèi)存、文件、日志、標準輸入輸出、socket(TCP/UDP)、加解密、摘要、ssl通道等。通過回調(diào)函數(shù)隱藏了底層的實現(xiàn)細節(jié),所有類型的bio的調(diào)用大體上是類似的。BIO中的數(shù)據(jù)從一個BIO傳送到另外一個BIO或者是應(yīng)用程序。

數(shù)據(jù)結(jié)構(gòu)

BIO_METHOD:定義各種回調(diào)函數(shù),這是一種抽象接口的封裝,具體bio對象會實現(xiàn)這些接口的一個子集。
typedef struct bio_method_st{
    int type;
    const char *name;
    int (*bwrite)(BIO *, const char *, int);
    int (*bread)(BIO*, char *, int);
    int (*bputs))BIO *, const char *);
    int (bgets)(BIO *, char *, int);
    int (*ctrl)(BIO *, int, long, void *);
    int (*create)(BIO *);
    int (*destroy)(BIO *);
    long (*callback_ctrl)(BIO *, int, bio_info_cb *);
}BIO_METHOD;

bio_st:實際使用的bio的類
struct bio_st{
    BIO_METHOD *method;
    long (*callback)(struct bio_st *, const char *, int, long, long);
    char *cb_arg;/*回調(diào)函數(shù)的第一個參數(shù)*/
    int init;//句柄初始化標記
    int shutdown;//關(guān)閉
    int retry_reason;//socket和ssl BIO中的異步阻塞時重試
    int num;//針對具體BIO而異
    void *ptr;//具體BIO的相關(guān)信息
    struct bio_st *next_bio;
    struct bio_st *prev_bio;
    int references;
    unsigned long num_read;//讀取的字節(jié)數(shù)
    unsigned long num_write;//寫入的字節(jié)數(shù)
    CRYPTO_EX_DATA ex_data;//用于存放額外數(shù)據(jù)
};

相關(guān)接口
  • BIO_new:生成一個bio,參數(shù)為類型,比如BIO_s_mem(),初始化bio_st的各種參數(shù)
  • BIO_new_file:獲取新bio,file可以是各種文件類型,針對不同的文件類型,傳入的參數(shù)不一樣,傳入的參數(shù)一般是原始文件描述符,如BIO_new_socket獲取套接字,傳入的是監(jiān)聽套接字
  • BIO_get_fd:設(shè)置網(wǎng)絡(luò)鏈接,獲取socket
//服務(wù)器端
sock=BIO_get_accept_socket("2323",0); //獲取一個監(jiān)聽的套接字描述符
sbio=BIO_new_socket(sock, BIO_NOCLOSE); //生成一個套接字的bio(被重新設(shè)置過的)
ret=BIO_accept(sock,&addr); //從監(jiān)聽的套接字上獲取到達的連接請求,并生成新的帶有本地標識的客戶端描述符
BIO_set_fd(sbio,ret,BIO_NOCLOSE);//將客戶端描述符綁定在BIO上,接下來的讀取,寫入,釋放都在此處理
//客戶端:
cbio=BIO_new_connect("localhost:http");//用于生成建立連接到本地web服務(wù)的BIO
out=BIO_new_fp(stdout,BIO_NOCLOSE);//生成一個輸出到屏幕的BIO
//驗證連接
if(BIO_do_connect(cbio) <= 0) 
{ 
  fprintf(stderr, "Error connecting to server\n"); 
} 
//發(fā)送請求
BIO_puts(cbio, "GET / HTTP/1.0\n\n"); 
for(;;) 
{ 
  len = BIO_read(cbio, tmpbuf, 1024); //從cbio讀出到緩存
  if(len <= 0) break; 
  BIO_write(out, tmpbuf, len); //從緩存輸出到屏幕
} 
BIO_free(cbio); 
BIO_free(out); 
return 0;
  • BIO_read,BIO_write等對bio的操作

openssl隨機數(shù)

openssl使用摘要算法來生成隨機數(shù)。其維護一個內(nèi)部隨機狀態(tài)數(shù)據(jù),通過這些內(nèi)部數(shù)據(jù)計算摘要生成隨機數(shù)。

數(shù)據(jù)結(jié)構(gòu)

/crypto/rand.h

struct rand_meth_st{
  void (*seed)(const void *buf, int num);//進一步隨機化
  int (*bytes)(unsigned char *buf, int num);//生成隨機數(shù)
  void (*cleanup)(void);//清除函數(shù)
  void (*add)(const void *buf, int num, double entropy);//與seed類似,使之更加無序
  int (*pseudorand)(unsigned char *buf, int num);//也是生成隨機數(shù),但是做更精細的控制
  int (*status)(void);
}

在同級目錄下的主要源碼

  • md_rand.c:實現(xiàn)基于摘要的隨機數(shù)生成
  • rand_lib.c:簡單調(diào)用了rand_meth中的回調(diào)函數(shù)
  • rand_win.c/rand_unix.c/rand_os2.c:提供平臺相關(guān)的RAND_poll函數(shù)實現(xiàn)和其他系統(tǒng)特有函數(shù)的實現(xiàn)
  • randfile.c:用于從隨機文件中加載隨機種子等

主要函數(shù)

  • int RAND_load_file(const char *file, long bytes):本函數(shù)將file指定的隨機數(shù)文件中的數(shù)據(jù)讀取bytes字節(jié),調(diào)用RAND_add進行計算,生成內(nèi)部隨機數(shù)
  • RAND_write_file:生成一個隨機數(shù)文件
  • const char *RAND_file_name(char *file, size_t num):獲取隨機數(shù)文件名,如果隨機數(shù)文件長度小于num則返回空,否則返回文件名
  • RAND_poll:計算內(nèi)部隨機數(shù),各個平臺都有各自的實現(xiàn)
  • RAND_screen/RAND_event:windows特有函數(shù),用來計算內(nèi)部隨機數(shù),其調(diào)用了RAND_seed
  • RAND_seed/RAND_add:計算隨機數(shù)
  • RAND_bytes/RAND_pseudo_bytes:用來計算隨機數(shù)
  • RAND_cleanup:清除內(nèi)部隨機數(shù)
  • RAND_set_rand_method:設(shè)置rand_meth,自定義設(shè)置
  • RAND_status:用來查看內(nèi)部隨機數(shù)熵值是否已到達預定值,如果沒有就不生成隨機數(shù)

BASE64編解碼

BASE64是一種常見的將16進制數(shù)據(jù)轉(zhuǎn)化為可見字符的編碼。于ASCII碼相比,它占用的空間較小。

編碼原理

將數(shù)據(jù)編碼成BASE64編碼時,以三字節(jié)為一組,轉(zhuǎn)換為24bit的二進制數(shù),將24bit的二進制分為四組,每組6bit。對于每一組,得到一個數(shù)字0-63。然而根據(jù)這個數(shù)字查表即可以得到相應(yīng)的字符

  • 不夠24bit時,在右邊用零填充,轉(zhuǎn)化為“=”,解碼時直接去掉即可

接口

編碼接口
  • EVP_EncodeInit:編碼前初始上下文
  • EVP_EncodeUpdate:編碼,可多次調(diào)用
  • EVP_EncodeFinal:編碼并輸出結(jié)果
  • EVP_EncodeBlock:編碼
解碼接口
  • EVP_DecodeInit 解碼前初始化上下文。
  • EVP_DecodeUpdate BASE64解碼,本函數(shù)可多次調(diào)用。
  • EVP_DecodeFinal BASE64解碼,并輸出結(jié)果。
  • EVP_DecodeBlock BASE64解碼,可單獨調(diào)用。

摘要與HMAC

摘要將任意數(shù)據(jù)通過計算獲取唯一對應(yīng)值。它是一種多對一的關(guān)系。主要用于網(wǎng)絡(luò)安全領(lǐng)域的身份驗證于簽名。常見的摘要算法有:sha、sha1、sha256以及md5等

摘要的實現(xiàn)

crypto/目錄下存放著各種摘要的源代碼

函數(shù)說明

  • xxx_Init:初始化上下文,用于多數(shù)據(jù)摘要
  • xxx_Update:摘要算法的名稱,進行摘要計算,可運行多次
  • xxx_final:摘要算法的名稱
  • xxx:對一個數(shù)據(jù)進行摘要,該函數(shù)由上述三個函數(shù)實現(xiàn)

HMAC

HMAC用于保護消息的完整性,它采用摘要算法對消息、填充、以及秘密進行混合運算。用戶將其和消息一并發(fā)出去,接收方收到數(shù)據(jù)進行相同的運算然后對比發(fā)來的hmac,驗證數(shù)據(jù)是否被篡改

數(shù)據(jù)壓縮

RSA

RSA算法是一個廣泛使用的公鑰算法。其密鑰包含公鑰和私鑰。它能用于數(shù)字簽名、身份認證以及密鑰交換。rsa密鑰長度一般為1024或者更高。

RSA的組成

  • n:模數(shù)
  • e:公鑰指數(shù)
  • d:私鑰指數(shù)
  • p:最初的大素數(shù)
  • q:最初的大素數(shù)
  • dmp1:e*dmp1 = 1 (mod (p-1))
  • dmq1:e*dmq1 = 1 (mod (q-1))
  • iqmp:q*iqmp = 1 (mod p )
    其中公鑰為n和e,私鑰為n和d;在實際應(yīng)用中,公鑰加密一般用來協(xié)商密鑰;私鑰加密用于簽名,供對方驗證發(fā)送方身份的合法性,防止中間人攻擊

openssl的rsa實現(xiàn)

數(shù)據(jù)結(jié)構(gòu)
struct rsa_meth_st{
    const char *name;
    int (*rsa_pub_enc)(int flen, const unsigned char* from, unsigned char *to, RSA *rsa, int padding);
    int (*rsa_pub_dec)(int flen, const unsigned char* from, unsigned char *to, RSA *rsa, int padding);
    int (*rsa_priv_enc)(int flen,const unsigned char *from, unsigned char *to, RSA *rsa, int padding); 
    int (*rsa_priv_dec)(int flen,const unsigned char *from,unsigned char  *to, RSA *rsa, int padding);
    int (*rsa_sign)(int type,const unsigned char *m, unsigned int m_length,unsigned char *sigret, unsigned int *siglen, const RSA *rsa); 
    int (*rsa_verify)(int dtype,const unsigned char *m, unsigned int m_length,unsigned char *sigbuf, unsigned int siglen, const RSA *rsa); 
    int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); 
};

struct rsa_st{
  const RSA_METHOD *meth;
  ENGINE *engine;
  BIGNUM *n;
  BIGNUM *e;
  BIGNUM *d;
  BIGNUM *p
  BIGNUM *q;
  BIGNUM *dmp1;
  BIGNUM *dmq1;
  BIGNUM *iqmp;
  CRYPTO_EX_DATA ex_data;
  int references
  ...
}
主要接口

1)RSA_check_key
檢查RSA密鑰。
2)RSA_new
生成一個RSA密鑰結(jié)構(gòu),并采用默認的rsa_pkcs1_eay_meth RSA_METHOD方法。
3)RSA_free
釋放RSA結(jié)構(gòu)。

  1. RSA RSA_generate_key(int bits, unsigned long e_value,
    void (
    callback)(int,int,void *), void *cb_arg)
    生成RSA密鑰,bits是模數(shù)比特數(shù),e_value是公鑰指數(shù)e,callback回調(diào)函數(shù)由用戶
    實現(xiàn),用于干預密鑰生成過程中的一些運算,可為空。
    5) RSA_get_default_method
    獲取默認的RSA_METHOD,為rsa_pkcs1_eay_meth。 6) RSA_get_ex_data
    獲取擴展數(shù)據(jù)。
    7) RSA_get_method
    獲取RSA結(jié)構(gòu)的RSA_METHOD。 8) RSA_padding_add_none
    RSA_padding_add_PKCS1_OAEP
    RSA_padding_add_PKCS1_type_1(私鑰加密的填充)
    RSA_padding_add_PKCS1_type_2(公鑰加密的填充)
    RSA_padding_add_SSLv23
    各種填充方式函數(shù)。
    9) RSA_padding_check_none
    RSA_padding_check_PKCS1_OAEP
    RSA_padding_check_PKCS1_type_1
    RSA_padding_check_PKCS1_type_2
    RSA_padding_check_SSLv23
    RSA_PKCS1_SSLeay
    各種去除填充函數(shù)。
    10)int RSA_print(BIO *bp, const RSA *x, int off)
    將RSA信息輸出到BIO中,off為輸出信息在BIO中的偏移量,比如是屏幕BIO,則表示打印
    信息的位置離左邊屏幕邊緣的距離。
    11)int DSA_print_fp(FILE *fp, const DSA *x, int off)
    將RSA信息輸出到FILE中,off為輸出偏移量。
    12)RSA_public_decrypt
    RSA公鑰解密。
    13)RSA_public_encrypt
    RSA公鑰加密。
    14)RSA_set_default_method/ RSA_set_method
    設(shè)置RSA結(jié)構(gòu)中的method,當用戶實現(xiàn)了一個RSA_METHOD時,調(diào)用此函數(shù)來設(shè)置,使
    RSA運算采用用戶的方法。
    15)RSA_set_ex_data
    設(shè)置擴展數(shù)據(jù)。
    16)RSA_sign
    RSA簽名。
    17)RSA_sign_ASN1_OCTET_STRING
    另外一種RSA簽名,不涉及摘要算法,它將輸入數(shù)據(jù)作為ASN1_OCTET_STRING進行DER
    編碼,然后直接調(diào)用RSA_private_encrypt進行計算。
    18)RSA_size
    獲取RSA密鑰長度字節(jié)數(shù)。
    19)RSA_up_ref
    給RSA密鑰增加一個引用。
    20)RSA_verify
    RSA驗證。
    21)RSA_verify_ASN1_OCTET_STRING
    另一種RSA驗證,不涉及摘要算法,與RSA_sign_ASN1_OCTET_STRING對應(yīng)。
    22)RSAPrivateKey_asn1_meth
    獲取 RSA 私鑰的 ASN1_METHOD,包括 i2d、d2i、new 和 free 函數(shù)地址。
    23)RSAPrivateKey_dup
    復制RSA私鑰。
    24)RSAPublicKey_dup
    復制RSA公鑰。

未完待續(xù)。。。

數(shù)字簽名算法(DSA)

DH算法(通信雙方進行密鑰協(xié)商的協(xié)議)

https工作全流程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容