如何使用Python输出仅证书PKCS#7

2024-10-01 09:26:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用Python实现一个SCEP服务器。SCEP规范要求我用“仅限证书的PKCS 7”响应PKIOperation。Apple在Ruby中有一个参考实现,它执行以下操作。在

require 'openssl'

@@root_cert = OpenSSL::X509::Certificate.new(File.read("ca_cert.pem"))
@@ra_cert = OpenSSL::X509::Certificate.new(File.read("ra_cert.pem"))

scep_certs = OpenSSL::PKCS7.new()
scep_certs.type="signed"
scep_certs.certificates=[@@root_cert, @@ra_cert]

File.open('from_ruby.der', 'w') { |file| file.write(scep_certs.to_der)}

该代码正确地输出一个pcks7der文件,该文件同时包含CA和RA证书。我正在尝试将这些代码移植到Python。我使用M2Crypto库来访问OpenSSL。我正在为M2Crypto.SMIME.PKCS7没有certificates方法而挣扎。到目前为止,我提出了以下几点。在

^{pr2}$

这个Python代码确实输出了一个DER编码的文件,看起来它确实包含了两个证书。但是OpenSSL无法读取此文件。在

openssl pkcs7 -in from_ruby.der -inform DER -print_certs

打印出Ruby脚本中的证书就可以了,而

openssl pkcs7 -in from_python.der -inform DER -print_certs

引发此错误

unable to load PKCS7 object
89377:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong             tag:/SourceCache/OpenSSL098/OpenSSL098-47.1/src/crypto/asn1/tasn_dec.c:1315:
89377:error:0D06C03A:asn1 encoding routines:ASN1_D2I_EX_PRIMITIVE:nested asn1 error:/SourceCache/OpenSSL098/OpenSSL098-47.1/src/crypto/asn1/tasn_dec.c:827:
89377:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:/SourceCache/OpenSSL098/OpenSSL098-47.1/src/crypto/asn1/tasn_dec.c:747:Field=type, Type=PKCS7

如何让Python以与Ruby相同的格式输出CA和RA证书?在

I have posted the test certs I'm using as a gist.

更新: 我找到了生成相同文件的openssl命令。在

openssl crl2pkcs7 -nocrl -certfile ca_cert.pem -certfile ra_cert.pem -out crl.der -outform DER

现在,我如何在Python中做到这一点。与this question相同


Tags: 文件certerrorpem证书racertsopenssl
3条回答

我有一种感觉(完全没有经过测试)是这样的:

an_smime = M2Crypto.SMIME.SMIME()
an_smime.set_x509_stack(stack)
an_smime.write(M2Crypto.BIO.File('from_python.der'), pkcs7=True)

有相同的需求,最后派生M2Crypto来添加一个新函数,该函数将创建一个退化的PKCS7对象。https://github.com/HanSooloo/M2Crypto-martinpaljak

所涉及的步骤如下:

  1. 将M2Crypto从Martin Paljak的回购中取出,换成新的。在
  2. 修改_pkcs7.iSWIG接口文件以添加下面的函数。在

_pkcs7.i修改

// Adding X.509 related header files to be able to use their data types.
#include <openssl/x509.h>
#include <openssl/x509v3.h>

// Adding PKCS7_SIGNED data type to help create the degenerate data structure.
%apply Pointer NONNULL { PKCS7_SIGNED * };

// Additional interface definitions for degenerate PKCS#7 object creation.
// Inspired by the crl2p7.c file from OpenSSL.  Will need to clean up a bit for function returns.
%threadallow pkcs7_create_degenerate;
%inline %{
int pkcs7_create_degenerate(STACK_OF(X509) *cert_stack, BIO *bio) {
    int ret=1;
    PKCS7 *p7=NULL;
    PKCS7_SIGNED *p7s=NULL;
    X509_CRL *crl=NULL;
    STACK_OF(X509_CRL) *crl_stack=NULL;

    if ((p7=PKCS7_new()) == NULL) goto end;
    if ((p7s=PKCS7_SIGNED_new()) == NULL) goto end;  

    p7->type=OBJ_nid2obj(NID_pkcs7_signed);
    p7->d.sign=p7s;
    p7s->contents->type=OBJ_nid2obj(NID_pkcs7_data);

    if (!ASN1_INTEGER_set(p7s->version,1)) goto end;
    if ((crl_stack=sk_X509_CRL_new_null()) == NULL) goto end;
    p7s->crl=crl_stack;
    p7s->cert=cert_stack;

    ret=i2d_PKCS7_bio(bio, p7);

end:
    p7s->cert=NULL;

    if (p7 != NULL) {
//      printf("about to free p7: ");
        PKCS7_free(p7);
//      printf("freed.\n");
    }

    return ret;

}
%}

功能详细信息

该函数接受X509堆栈指针和BIO指针作为输入,并返回一个表示成功的整数。在

X509堆栈指针需要指向一个堆栈,其中包含要放入退化PKCS#7对象中的证书。在

BIO指针需要指向一个空的BIO结构,该BIO结构稍后将用PKCS#7对象填充。在

使用上述函数的Python代码示例:

^{pr2}$

您可以使用Python ctypes直接调用OpenSSL共享库函数来实现这一点。Here's an example。在

相关问题 更多 >