22.1  PEM概述



openssl使用PEM(Privacy Enhanced Mail)格式来存放各种信息,他是openssl默认采用信息方式。openssl中PEM文件一般包含如下信息:



a.内容类型



表明本文件存放的是什么信息内容,他的形式为"---------------BEGIN XXXX-------------------",与结尾的"-----------------END XXXX---------------------------------"对应



b.头文件



表明数据是如果被处理存放,Openssl中庸的最多的是加密信息,比如加密算法以及初始化向量iv.



c. 信息体



为BASE64编码的数据




举例如下:



-----BEGIN RSA PRIVATE KEY----- 
 
 
 

   Proc-Type: 4,ENCRYPTED 
 
 
 

   DEK-Info: DES-EDE3-CBC,9CFD51EC6654FCC3




本例是作者生成的一个RSA密钥,以PEM格式加密存放,采用了openssl默认的对称加密算法。



表明了



本文件是一个RSA私钥;



DES-EDE3-CBC对称加密算法



9CFD51EC6654FCC3 对称算法初始化向量iv.




22.2  openssl的PEM实现



openssl的PEM模块实现位于crypto/pem目录下,并且还依赖于openssl的ASN1模块。


#define PEM_STRING_X509_OLD "X509_CERTIFICATE" 
 
 
 

   #define PEM_STRING_X509 "CERTIFICATE" 
 
 
 

   #define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE" 
 
 
 

   #define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST" 
 
 
 

   #define PEM_STRING_X509_REQ "CERTIFICATE REQUEST" 
 
 
 

   #define PEM_STRING_X509_CRL "X509 CRL" 
 
 
 

   #define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY" 
 
 
 

   #define PEM_STRING_PUBLIC "PUBLIC KEY" 
 
 
 

   #define PEM_STRING_RSA "RSA PRIVATE KEY" 
 
 
 

   #define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY" 
 
 
 

   #define PEM_STRING_DSA "DSA PRIVATE KEY" 
 
 
 

   #define PEM_STRING_DSA_PUBLIC "DSA PUBLIC KEY" 
 
 
 

   #define PEM_STRING_PKCS7 "PKCS7" 
 
 
 

   #define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA" 
 
 
 

   #define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY" 
 
 
 

   #define PEM_STRING_PKCS8INF "PRIVATE KEY" 
 
 
 

   #define PEM_STRING_DHPARAMS "DH PARAMETERS" 
 
 
 

   #define PEM_STRING_DHXPARAMS "X9.42 HD PARAMETERS" 
 
 
 

   #define PEM_STRING_SSL_SESSION "SSL SESSION PARAMETERS" 
 
 
 

   #define PEM_STRING_DSAPARAMS "DSA PARAMETERS" 
 
 
 

   #define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY" 
 
 
 

   #define PEM_STRING_ECPARAMETERS "EC PARAMETERS" 
 
 
 

   #define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY" 
 
 
 

   #define PEM_STRING_PARAMETERS "PARAMETERS" 
 
 
 

   #define PEM_STRING_CMS "CMS"



openssl生成PEM格式文件的大致过程如下



a.将各种数据DER编码



b,将a中的数据进行加密处理



c.根据类型以及是否加密,构造PEM头



d.将b中的数据进行BASE64编码,放入PEM文件



备注:openssl各个类型的PEM函数处理主要是write和read函数。write函数用于生成PEM格式的文件,而read函数主要用于读取PEM格式的文件。




22.3  PEM 函数



PEM函数定义在crypto/pem.h中



a.PEM_write_XXXX/PEM_write_bio_XXXXX



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



b.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\ECPrivteKey\EC_PUBKEY等



c. PEM_ASN1_read/PEM_ASN1_read_bio



低层的PEM读取函数



d.PEM_ASN_write/PEM_ASN1_write_bio



底层PEM写函数



e.PEM_read_bio



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



f.PEM_get_EVP_CIPHER_INFO



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



g.PEM_do_header



根据对称算法,解密数据



h.PEM_bytes_read_bio



获取PEM数据,得到的结果为一个DER编码的明文数据,改函数先后调用e,f,g.h




23.3  Engine 数据结构


struct engine_st 
 
 
 

   { 
 
 
 

   const char *id; 
 
 
 

   const char *name; 
 
 
 

   const RSA_METHOD *rsa_meth; 
 
 
 

   const DSA_METHOD *dsa_meth; 
 
 
 

   const DH_METHOD *dh_meth; 
 
 
 

   const EC_KEY_METHOD *ec_meth; 
 
 
 

   const RAND_METHOD *rand_meth; 
 
 
 

   ENGINE_CIPHERS_PTR ciphers; 
 
 
 

   ENGINE_DIGESTS_PTR digests; 
 
 
 

   ENGINE_PKEY_METHS_PTR pkey_meths; 
 
 
 

   ENGINE_PKEY_ASN1_METHS_PTR pkey_asn1_meths; 
 
 
 

   ENGINE_GEN_INT_FUNC_PTR destroy; 
 
 
 

   ENGINE_GEN_INT_FUNC_PTR init; 
 
 
 

   ENGINE_GEN_INT_FUNC_PTR finish; 
 
 
 

   ENGINE_CTRL_FUNC_PTR ctrl; 
 
 
 

   ENGINE_LOAD_KEY_PTR load_privkey; 
 
 
 

   ENGINE_LOAD_KEY_PTR load_pubkey; 
 
 
 

   ENGINE_SSL_CLIENT_CERT_PTR load_ssl_client_cert; 
 
 
 

   const ENGINE_CMD_DEFN *cnd_defns; 
 
 
 

   int flags; 
 
 
 

   CRYPTO_REF_COUNT struct_ref; 
 
 
 

   int funct_ref; 
 
 
 

   CRYPTO_EX_DATA ex_data; 
 
 
 

   struct engine_st *prev; 
 
 
 

   struct engine_st *next; 
 
 
 

   }



本结构包含大量运算集合函数



id:Engine标识



name:Engine名字



rsa_meth: RSA方法集合



dsa_meth:DSA方法集合



dh_meth: DH方法集合



ecdh_meth: ECDH方法结合



ecdsa_meth:ECDSA方法集合



rand_meth:随机数方法集合



store_meth:存储方法集合



ciphers:对称算法选取。



digests:摘要算法选取函数。该回调函数用来从用户实现的多个摘要算法中根据某种条件



destroy:销毁引擎函数



init:初始化引擎函数



finish:完成回调函数



ctrl:控制函数



load_privkey:加载私钥函数



load_pubkey:加载公钥函数



ex_data:扩展数据结构,可用来存放用户数据



prev/next:用于构建Engine链表,openssl中的硬件Engine可能不止一个。