函数解析:C语言如何使用Openssl库函数

前言

在做学校的工程实践的时候,学习到了关于如何在C语言中使用openssl库函数的方法,这里记录一下,方便以后查阅

PEM

PEM函数定义在crypto/pem.h中。函数比较简单,主要的函数有:

  1. PEM_write_XXXX/PEM_write_bio_XXXX

    将XXXX代表的信息类型写入到文件/bio中。

  2. PEM_read_XXXX/PEM_read_bio_XXXX

    从文件/bio中读取PEM的XXXX代表类型的信息。

XXXX可用代表的有:SSL_SESSION、X509、X509_REQ、X509_AUX、X509_CRL、RSAPrivateKey、RSAPublicKey、DSAPrivateKey、PrivateKey、PKCS7、DHparams、NETSCAPE_CERT_SEQUENCE、PKCS8PrivateKey、DSAPrivateKey、DSA_PUBKEY、DSAparams、ECPKParameters、ECPrivateKey、EC_PUBKEY等。

  1. PEM_ASN1_read/PEM_ASN1_read_bio

    比较底层的PEM读取函数,2)中的函数都调用了这两个函数。

  2. PEM_ASN1_write/PEM_ASN1_write_bio

    比较底层的PEM读取函数,1)中的函数都调用了这两个函数。

  1. PEM_read_bio

    读取PEM文件的各个部分,包括文件类型、头信息以及消息体(base64解码后的结果)。

  2. PEM_get_EVP_CIPHER_INFO

    根据头信息获取对称算法,并加载初始化向量iv。

  3. PEM_do_header

    根据对称算法,解密数据。

  1. PEM_bytes_read_bio

    获取PEM数据,得到的结果为一个DER编码的明文数据,该函数先后调用了5)、6)和7)函数。

RSA

  1. RSA_check_key

    检查RSA密钥。

  2. RSA_new

    生成一个RSA密钥结构,并采用默认的rsa_pkcs1_eay_meth RSA_METHOD方法。

  3. RSA_free

    释放RSA结构。

  4. 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. SA_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公钥。

抽象IO

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

BIO各个函数定义在crypto/bio.h中。所有的函数都由BIO_METHOD中的回调函数来实现。函数主要分为几类:

1) 具体BIO相关函数

​ 比如:BIO_new_file(生成新文件)和BIO_get_fd(设置网络链接)等。

2) 通用抽象函数

​ 比如BIO_read和BIO_write等。

另外,有很多函数是由宏定义通过控制函数BIO_ctrl实现,比如BIO_set_nbio、BIO_get_fd和BIO_eof等等。

下面就是将RSA密钥转换为字符串格式的抽象IO的使用案例

1
2
3
4
5
6
7
8
9
   // 将公钥导出为字符串形式
RSA *rsa_keypair;
char *public_key_str;
BIO *bio_public = BIO_new(BIO_s_mem());
PEM_write_bio_RSA_PUBKEY(bio_public, rsa_keypair);
size_t public_key_len = BIO_pending(bio_public);
public_key_str = malloc(public_key_len + 1);
BIO_read(bio_public, public_key_str, public_key_len);
public_key_str[public_key_len] = '\0';