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)。
- 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ù)。。。