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证书链
for (int i=0; i<sk_X509_num(ca); i++)
{
PKCS7_add_certificate(p7, sk_X509_value(ca, i));
}
BIO* p7bio = PKCS7_dataInit(p7, NULL);
BIO_write(p7bio, "How are you!", strlen("How are you!"));//加入原始数据,
PKCS7_dataFinal(p7, p7bio); //处理数据。
//转换为der编码输出
i2d_PKCS7(p7,&dertmp);
PKCS7_free(p7);
BIO_free(p7bio);
解析P7签名的代码:
//der编码转换为PKCS7结构体
PKCS7 * p7 =d2i_PKCS7(NULL,dertmp,derLen)
//解析出原始数据
BIO *p7bio= PKCS7_dataDecode(p7,NULL,NULL,NULL);
//从BIO中读取原始数据,将得到"How are you!"
srcLen = BIO_read(p7bio,src,1024);
//获得签名者信息stack
STACK_OF(PKCS7_SIGNER_INFO) *sk = PKCS7_get_signer_info(p7);
//获得签名者个数(本例只有1个)
int signCount = sk_PKCS7_SIGNER_INFO_num(sk );
for(int i=0;i
{
//获得签名者信息
PKCS7_SIGNER_INFO *signInfo = sk_PKCS7_SIGNER_INFO_value(sk,i);
//获得签名者证书
X509 *cert= PKCS7_cert_from_signer_info(p7,signInfo);
//验证签名
if(PKCS7_signatureVerify(p7bio,p7,signInfo,cert) != 1)
{
printf("signatureVerify Err\n");
}
}