当前位置:首页 > OpenSSL之pkcs7系列
openssl学习笔记之pkcs7-1
1. 概述
openssl之pkcs7介绍
openssl实现了pkcs7(加密消息语法标准)。在中。
p7包括6种数据内容:数据(data),签名数据(sign),数字信封数据(enveloped),签名数字信封数据(signed_and_enveloped),摘要数据(digest),加密数据(encrypted)。 后面将一一介绍如何对6种数据类型进行封装。 PKCS7结构体定义如下: typedef struct pkcs7_st {
/* The following is non NULL if it contains ASN1 encoding of * this structure */ unsigned char *asn1; long length;
#define PKCS7_S_HEADER 0 #define PKCS7_S_BODY 1 #define PKCS7_S_TAIL 2
int state; /* used during processing */ int detached;
ASN1_OBJECT *type;
/* content as defined by the type */
/* all encryption/message digests are applied to the 'contents', * leaving out the 'type' field. */ union { char *ptr;
/* NID_pkcs7_data */ ASN1_OCTET_STRING *data;
/* NID_pkcs7_signed */ PKCS7_SIGNED *sign;
/* NID_pkcs7_enveloped */ PKCS7_ENVELOPE *enveloped;
/* NID_pkcs7_signedAndEnveloped */
PKCS7_SIGN_ENVELOPE *signed_and_enveloped;
/* NID_pkcs7_digest */ PKCS7_DIGEST *digest;
/* NID_pkcs7_encrypted */ PKCS7_ENCRYPT *encrypted;
/* Anything else */ ASN1_TYPE *other; } d; } PKCS7; 数据(data): 明文打包
type为NID_pkcs7_data,ASN1_OCTET_STRING类型,即为简单的ASN1_STRING数据类型。 签名数据(sign):
把数据以及签名值打包,其中包括签名者的证书,CRL等,目的为确定发送者的身份。 type为NID_pkcs7_signed。PKCS7_SIGNED类型的数据,PKCS7_SIGNED定义如下: typedef struct pkcs7_signed_st {
ASN1_INTEGER *version; /* version 1 */ //版本
STACK_OF(X509_ALGOR) *md_algs; /* md used */ //摘要算法 STACK_OF(X509) *cert; /* [ 0 ] */ //签名证书 STACK_OF(X509_CRL) *crl; /* [ 1 ] */ //证书吊销列表 STACK_OF(PKCS7_SIGNER_INFO) *signer_info; 签名信息 struct pkcs7_st *contents; } PKCS7_SIGNED;
数字信封数据(enveloped):
使用接收者的公钥(从证书获取)加密数据。目的为保护数据,拥有私钥的接收者才能解开数据。 type为NID_pkcs7_enveloped。PKCS7_ENVELOPE类型的数据,PKCS7_ENVELOPE定义如下 typedef struct pkcs7_enveloped_st {
ASN1_INTEGER *version; /* version 0 */
STACK_OF(PKCS7_RECIP_INFO) *recipientinfo;//接收者的证书 PKCS7_ENC_CONTENT *enc_data;//用接收者证书公钥加密的数据 } PKCS7_ENVELOPE;
签名数字信封数据(signed_and_enveloped) 数字信封加签名
type为NID_pkcs7_signedAndEnveloped。PKCS7_SIGN_ENVELOPE类型的数据,PKCS7_SIGN_ENVELOPE定义如下 typedef struct pkcs7_signedandenveloped_st {
ASN1_INTEGER *version; /* version 1 */
STACK_OF(X509_ALGOR) *md_algs; /* md used */ STACK_OF(X509) *cert; /* [ 0 ] */ STACK_OF(X509_CRL) *crl; /* [ 1 ] */
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
PKCS7_ENC_CONTENT *enc_data;
STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; } PKCS7_SIGN_ENVELOPE; 加密数据(encrypted) 使用对称算法加密数据。
type为NID_pkcs7_encrypted。PKCS7_ENCRYPT类型的数据,PKCS7_ENCRYPT定义如下 typedef struct pkcs7_encrypted_st {
ASN1_INTEGER *version; /* version 0 */ PKCS7_ENC_CONTENT *enc_data; } PKCS7_ENCRYPT;
摘要数据(digest):
对数据摘要后打包。openssl没有实现,后面将介绍如何修改openssl源码实现对NID_pkcs7_digest的支持。 type为NID_pkcs7_digest。PKCS7_DIGEST类型的数据,PKCS7_DIGEST定义如下 typedef struct pkcs7_digest_st {
ASN1_INTEGER *version; /* version 0 */ X509_ALGOR *md; /* md used */ struct pkcs7_st *contents; ASN1_OCTET_STRING *digest; } PKCS7_DIGEST;
openssl之pkcs7-data内容类型的编码解码
:Data内容类型旨在表示任意的字节串,比如ASCII文本文件;其翻译留给应用。这样的串无需任何内部的结构. Data ::= OCTET STRING
pkcs7的类型为NID_pkcs7_data, d为ASN1_OCTET_STRING *data; 一:对data内容进行编码 1.新建一个PKCS7结构体。 p7 = PKCS7_new();
2.设置p7结构体的类型为NID_pkcs7_data PKCS7_set_type(p7,NID_pkcs7_data); 3.设置原文到ASN1_OCTET_STRING *data;
M_ASN1_OCTET_STRING_set(p7->d.data,src,srcLen); 4.转换pkcs7结构体为der编码 derLen = i2d_PKCS7(p7,&tmpder);
i2d_PKCS7的返回值为der编码的长度。第二个参数为der编码输出。
注意:openssl输出后会更改tmpder的指针,故使用时应该用临时指针。比如欲输出der编码内容到变量der中。 代码应如下:
unsigned char *der = NULL; unsigned char *dertmp = NULL; unsigned long derLen;
derLen = i2d_PKCS7(p7,NULL);
der = malloc(derLen); dertmp = der;
derLen = i2d_PKCS7(p7,&dertmp); ... free(der);
二:对data内容p7数据包进行解码 解码的过程和编码相反。
1。转换der编码为pkcs7结构体 d2i_PKCS7
2。检查p7 type是否是NID_pkcs7_data
if(OBJ_obj2nid(p7->type) != NID_pkcs7_data)//数据类型是否为pkcs7_data 3。取出源数据
srcLen = p7->d.data-〉length;
memcpy(src,p7->d.data->data,srcLen);
openssl之pkcs7- signed-data内容类型的编码解码
PKCS7_SIGNED.sign在openssl中的定义如下: typedef struct pkcs7_signed_st {
ASN1_INTEGER *version; /* version 1 */
STACK_OF(X509_ALGOR) *md_algs; /* md used */ STACK_OF(X509) *cert; /* [ 0 ] */ STACK_OF(X509_CRL) *crl; /* [ 1 ] */
STACK_OF(PKCS7_SIGNER_INFO) *signer_info; struct pkcs7_st *contents; } PKCS7_SIGNED;
signed内容类型由任意类型的内容和数字签名组成。任何类型的内容能够同时被任意数量的签名者签名。 签名数据的产生过程有如下几步:
1. 对于每一个签名者,他用消息摘要算法计算出摘要值 。 2. 对于每一个签名者,消息摘要和相关的信息用自己的私钥加密。
3. 对于每一个签名者,把加密的消息摘要和其他的签名者特定信息放入signer_info值中。每个 签名者的证书、crl等也在这一步被收集进来。
4. 把所有签名者的信息摘要算法、他们的signer_info值和内容一起放进sign值中。 调用openssl的代码如下: PKCS7* p7 = PKCS7_new();
PKCS7_set_type(p7, NID_pkcs7_signed);//设置类型为NID_pkcs7_signed PKCS7_content_new(p7, NID_pkcs7_data); PKCS7_set_detached(p7, 0); //添加签名者信息,
//x509:签名证书,pkey:签名者私钥。EVP_sha1()签名者摘要算法。
PKCS7_SIGNER_INFO* info = PKCS7_add_signature(p7, x509, pkey, EVP_sha1()); //添加签名者证书
PKCS7_add_certificate(p7, x509); //添加签名者的CA证书链
共分享92篇相关文档