openssl相关数据结构的设计

2019-11-01  本文已影响0人  镜中无我

hash表

数据结构:使用链表数组实现

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表维护一个链表数组
    LHASH_COMP_FN_TYPE comp;//数据查找的比较函数句柄
    LHASH_HASH_FN_TYPE hash;//用于存放计算hash值函数的地址?
    unsigned int num_nodes;//当前节点数量
    unsigned int num_all_nodes;//节点容量
    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;

相关接口

- 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);

内存分配

内存相关数据结构

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;//分配内存的地址
    int num;//分配内存的大小
    const char *file;//分配内存映射的文件
    int line;//分配内存的行号??
    unsigned long thread;//分配内存的线程ID
    unsigned long order;//第几次分配内存
    time_t time;//内存分配时间
    APP_INFO *app_info;//链表。存放用户应用信息,如文件、行号、以及其他
    unsigned int references;//被引用次数
}MEM;

内存操作相关接口

抽象IO(BIO)

对于io类型的抽象封装,包括:内存、文件、日志、标准输入输出、socket(TCP/UDP)、加解密、摘要、ssl通道等。通过回调函数隐藏了底层的实现细节,所有类型的bio的调用大体上是类似的。BIO中的数据从一个BIO传送到另外一个BIO或者是应用程序。

数据结构

BIO_METHOD:定义各种回调函数,这是一种抽象接口的封装,具体bio对象会实现这些接口的一个子集。
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;/*回调函数的第一个参数*/
    int init;//句柄初始化标记
    int shutdown;//关闭
    int retry_reason;//socket和ssl BIO中的异步阻塞时重试
    int num;//针对具体BIO而异
    void *ptr;//具体BIO的相关信息
    struct bio_st *next_bio;
    struct bio_st *prev_bio;
    int references;
    unsigned long num_read;//读取的字节数
    unsigned long num_write;//写入的字节数
    CRYPTO_EX_DATA ex_data;//用于存放额外数据
};

相关接口
//服务器端
sock=BIO_get_accept_socket("2323",0); //获取一个监听的套接字描述符
sbio=BIO_new_socket(sock, BIO_NOCLOSE); //生成一个套接字的bio(被重新设置过的)
ret=BIO_accept(sock,&addr); //从监听的套接字上获取到达的连接请求,并生成新的带有本地标识的客户端描述符
BIO_set_fd(sbio,ret,BIO_NOCLOSE);//将客户端描述符绑定在BIO上,接下来的读取,写入,释放都在此处理
//客户端:
cbio=BIO_new_connect("localhost:http");//用于生成建立连接到本地web服务的BIO
out=BIO_new_fp(stdout,BIO_NOCLOSE);//生成一个输出到屏幕的BIO
//验证连接
if(BIO_do_connect(cbio) <= 0) 
{ 
  fprintf(stderr, "Error connecting to server\n"); 
} 
//发送请求
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;

openssl随机数

openssl使用摘要算法来生成随机数。其维护一个内部随机状态数据,通过这些内部数据计算摘要生成随机数。

数据结构

/crypto/rand.h

struct rand_meth_st{
  void (*seed)(const void *buf, int num);//进一步随机化
  int (*bytes)(unsigned char *buf, int num);//生成随机数
  void (*cleanup)(void);//清除函数
  void (*add)(const void *buf, int num, double entropy);//与seed类似,使之更加无序
  int (*pseudorand)(unsigned char *buf, int num);//也是生成随机数,但是做更精细的控制
  int (*status)(void);
}

在同级目录下的主要源码

主要函数

BASE64编解码

BASE64是一种常见的将16进制数据转化为可见字符的编码。于ASCII码相比,它占用的空间较小。

编码原理

将数据编码成BASE64编码时,以三字节为一组,转换为24bit的二进制数,将24bit的二进制分为四组,每组6bit。对于每一组,得到一个数字0-63。然而根据这个数字查表即可以得到相应的字符

接口

编码接口
解码接口

摘要与HMAC

摘要将任意数据通过计算获取唯一对应值。它是一种多对一的关系。主要用于网络安全领域的身份验证于签名。常见的摘要算法有:sha、sha1、sha256以及md5等

摘要的实现

crypto/目录下存放着各种摘要的源代码

函数说明

HMAC

HMAC用于保护消息的完整性,它采用摘要算法对消息、填充、以及秘密进行混合运算。用户将其和消息一并发出去,接收方收到数据进行相同的运算然后对比发来的hmac,验证数据是否被篡改

数据压缩

RSA

RSA算法是一个广泛使用的公钥算法。其密钥包含公钥和私钥。它能用于数字签名、身份认证以及密钥交换。rsa密钥长度一般为1024或者更高。

RSA的组成

openssl的rsa实现

数据结构
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密钥结构,并采用默认的rsa_pkcs1_eay_meth RSA_METHOD方法。
3)RSA_free
释放RSA结构。

  1. RSA RSA_generate_key(int bits, unsigned long e_value,
    void (
    callback)(int,int,void *), void *cb_arg)
    生成RSA密钥,bits是模数比特数,e_value是公钥指数e,callback回调函数由用户
    实现,用于干预密钥生成过程中的一些运算,可为空。
    5) RSA_get_default_method
    获取默认的RSA_METHOD,为rsa_pkcs1_eay_meth。 6) RSA_get_ex_data
    获取扩展数据。
    7) RSA_get_method
    获取RSA结构的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
    各种填充方式函数。
    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
    各种去除填充函数。
    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
    设置RSA结构中的method,当用户实现了一个RSA_METHOD时,调用此函数来设置,使
    RSA运算采用用户的方法。
    15)RSA_set_ex_data
    设置扩展数据。
    16)RSA_sign
    RSA签名。
    17)RSA_sign_ASN1_OCTET_STRING
    另外一种RSA签名,不涉及摘要算法,它将输入数据作为ASN1_OCTET_STRING进行DER
    编码,然后直接调用RSA_private_encrypt进行计算。
    18)RSA_size
    获取RSA密钥长度字节数。
    19)RSA_up_ref
    给RSA密钥增加一个引用。
    20)RSA_verify
    RSA验证。
    21)RSA_verify_ASN1_OCTET_STRING
    另一种RSA验证,不涉及摘要算法,与RSA_sign_ASN1_OCTET_STRING对应。
    22)RSAPrivateKey_asn1_meth
    获取 RSA 私钥的 ASN1_METHOD,包括 i2d、d2i、new 和 free 函数地址。
    23)RSAPrivateKey_dup
    复制RSA私钥。
    24)RSAPublicKey_dup
    复制RSA公钥。

未完待续。。。

数字签名算法(DSA)

DH算法(通信双方进行密钥协商的协议)

https工作全流程

上一篇 下一篇

猜你喜欢

热点阅读