如何创建DER格式的CMS签名消息并使用openssl库进行验证?

时间:2019-06-10 04:49:47

标签: syntax openssl cryptography message der

我创建了一个私有证书,并使用OpenSSL命令成功生成并验证了CMS签名数据。

$ openssl cms -sign -signer server.pem -inkey server.key -nodetach -md sha256 -in LLS_SignedMultiTable_SignedArea.bin -outform der -out sample.cms-der -noattr
$ openssl cms -verify -CAfile root.crt.pem -inform der -in sample.cms-der 

我想使用C语言和OpenSSL库制作自己的“签名”和“验证”实用程序。 此外,我想确保CMS签名的数据具有“ sha256WithRSAEncryption”而不是“ rsaEncryption”。

$ openssl asn1parse -inform der -in ./sample.cms-der  

  193:d=10 hl=2 l=   9 prim: OBJECT            :rsaEncryption
  204:d=10 hl=2 l=   0 prim: NULL
  206:d=6  hl=2 l=  47 cons: SEQUENCE
  208:d=7  hl=2 l=   9 prim: OBJECT            :messageDigest
  219:d=7  hl=2 l=  34 cons: SET
  221:d=8  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]: ....
  255:d=5  hl=2 l=  13 cons: SEQUENCE
  257:d=6  hl=2 l=   9 prim: OBJECT            :rsaEncryption
  268:d=6  hl=2 l=   0 prim: NULL
  270:d=5  hl=4 l= 256 prim: OCTET STRING      [HEX DUMP]: ....

这是我的源代码。它创建了DER格式的签名数据,但验证失败。它的签名数据生成rsaEncryption,而不是sha256WithRSAEncryption。

如何创建'sha256WithRSAEncryption'ed CMS签名数据并进行验证?

$ cat cms_sign.c
/* Simple S/MIME signing example */
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <openssl/err.h>

int main(int argc, char **argv)
{
    BIO *in = NULL, *out = NULL, *tbio = NULL;
    X509 *scert = NULL;
    EVP_PKEY *skey = NULL;
    CMS_ContentInfo *cms = NULL;
    int ret = 1;



int flags = CMS_DETACHED | CMS_NOINTERN | CMS_NOINTERN |CMS_BINARY ;

OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();

/* Read in signer certificate and private key */
tbio = BIO_new_file(argv[1], "r");

if (!tbio)
    goto err;

scert = PEM_read_bio_X509(tbio, NULL, 0, NULL);

BIO_reset(tbio);

skey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL);

if (!scert || !skey)
    goto err;

/* Open content being signed */

in = BIO_new_file(argv[2], "r");

if (!in)
    goto err;

/* Sign content */
cms = CMS_sign(scert, skey, NULL, in, flags);

if (!cms)
    goto err;

out = BIO_new_file("sample.cms-der", "w");
if (!out)
    goto err;

if ( !i2d_CMS_bio(out, cms))
    goto err;

ret = 0;

 err:

    if (ret) {
        fprintf(stderr, "Error Signing Data\n");
        ERR_print_errors_fp(stderr);
    }

    CMS_ContentInfo_free(cms);
    X509_free(scert);
    EVP_PKEY_free(skey);
    BIO_free(in);
    BIO_free(out);
    BIO_free(tbio);
    return ret;
}

$ cat cms_verify.c
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>              /* open() */

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/pkcs7.h>
#include <openssl/safestack.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>     /* X509_PURPOSE_ANY */
#include <openssl/x509_vfy.h>

#include <openssl/cms.h>
#include <openssl/pem.h>


int testcms (const char* cert_path, const char* sod_path)
{
    BIO *in = NULL, *out = NULL, *tbio = NULL, *cont = NULL;
    X509_STORE *st = NULL;
    X509 *cacert = NULL;
    CMS_ContentInfo *cms = NULL;

    int ret = 1;

    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();

    st = X509_STORE_new();

    tbio = BIO_new_file(cert_path, "r");

    if (!tbio) {
        fprintf(stderr, "Cert file not opened: path=%s;\n", cert_path);
        goto err;
    }

    cacert = PEM_read_bio_X509(tbio, NULL, 0, NULL);

    if (!cacert) {
        fprintf(stderr, "PEM_read_bio_X509 FAILED: cert.path=%s;\n", 
   cert_path);
        goto err;
    }

    if (!X509_STORE_add_cert(st, cacert)) {
        fprintf(stderr, "X509_STORE_add_cert FAILED: cert.path=%s;\n", 
        cert_path);
        goto err;
    }

    in = BIO_new_file(sod_path, "r");

    if (!in) {
        fprintf(stderr, "PKCS7 file not opened: path=%s;\n", sod_path);
        goto err;
    }


cms = d2i_CMS_bio(in, NULL);

if (!cms) {
    fprintf(stderr, "SMIME_read_CMS FAILED: pkcs7.path=%s;\n", sod_path);
    goto err;
}

 out = BIO_new_file("smver.txt", "w");
if (!out)
    goto err;

if (!CMS_verify(cms, NULL, st, cont, out, 0)) {
    fprintf(stderr, "Verification Failure\n");
    goto err;
}

fprintf(stderr, "Verification Successful\n");

ret = 0;

err:

if (ret) {
    fprintf(stderr, "Error Verifying Data\n");
    ERR_print_errors_fp(stderr);
}

    CMS_ContentInfo_free(cms);
    X509_free(cacert);
    BIO_free(in);
    BIO_free(out);
    BIO_free(tbio);
    return ret;
}

void usage ()
{
  printf("program cert_path signature_path\n");
}

int main (int argc, char *argv[])
{

  if (argc < 2 ) { usage(); return 0; }
  testcms(argv[1], argv[2]);
  return 0;
}

0 个答案:

没有答案