Извлечь открытый сертификат из сообщения SMIME (pkcs7-signature) с помощью OpenSSL - PullRequest
21 голосов
/ 15 апреля 2011

Как я могу извлечь публичный сертификат из сообщения smime (pkcs7-signature) с помощью OpenSSL?

Ответы [ 3 ]

28 голосов
/ 18 апреля 2011

С помощью инструмента командной строки, предполагая, что само сообщение S / MIME находится в файле message:

openssl smime -verify -in message -noverify -signer cert.pem -out textdata

Записывает сертификат подписавшего (как встроено в большой двоичный объект подписи) в cert.pem, а текстовые данные сообщения - в файле textdata.

В качестве альтернативы, вы можете сохранить подпись большого двоичного объекта как независимый файл (это просто своего рода вложение, поэтому любое почтовое приложение или библиотека должны это сделать. Затем, если предположить, что указанный большой двоичный объект находится в файле с именем smime.p7s, использование:

openssl pkcs7 -in smime.p7s -inform DER -print_certs

, который будет распечатывать все сертификаты, встроенные в подпись PKCS # 7. Обратите внимание, что их может быть несколько: сам сертификат подписывающего лица и любые дополнительные сертификаты, которые подписчик посчитал подходящими для включения (например, промежуточные сертификаты CA, которые могут помочь в проверке его сертификата).

11 голосов
/ 15 февраля 2012

Или просто:

cat message.eml | openssl smime -pk7out | openssl pkcs7 -print_certs > senders-cert.pem
2 голосов
/ 26 июля 2014

Если вы пишете на C / C ++, этот фрагмент кода поможет

    //...assuming you have valid pkcs7, st1, m_store etc......

    verifyResult = PKCS7_verify( pkcs7, st1, m_store, content, out, flags);
    if(verifyResult != 1) {
        goto exit_free;
    }

    //Obtain the signers of this message. Certificates from st1 as well as any found included
    //in the message will be returned.
    signers = PKCS7_get0_signers(pkcs7, st1, flags);
    if (!save_certs(env, signerFilePath, signers)) {
        //Error log
    }

//This method will write the signer certificates into a file provided
int save_certs(JNIEnv *env, jstring signerFilePath, STACK_OF(X509) *signers)
{
    int result = 0;
    int i;
    BIO *tmp;
    int num_certificates = 0;

    if (signerFilePath == NULL) {
        return 0;
    }

    const char *signerfile = (const char *)env->GetStringUTFChars(signerFilePath, 0);
    tmp = BIO_new_file(signerfile, "w");
    if (!tmp) {
        //error. return
    }
    num_certificates = sk_X509_num(signers);
    for(i = 0; i < num_certificates; i++) {
        PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
    }
    result = 1;

    exit_free:
    BIO_free(tmp);
    if (signerfile) {
        env->ReleaseStringUTFChars(signerFilePath, signerfile);
        signerfile = 0;
    }
    return result;
}
...