There are several hurdles to overcome to achieve what you are looking for.
First, the pyopenssl
binding itself is limited when it comes to its crypto
module, where you desired functionality resides. In fact, the pyopenssl crypto
documentation states:
The pyca/cryptography
module mentioned is exposed via two internal attributes of the pyopenssl crypto
module, with the names _lib
and _ffi
, which need to be used to get to the required functionality.
Then the CMS_verify()
function that would be your logical choice for this is not included in the pyca/cryptography
bindings either. However, for your purpose it is probably good enough to use PKCS7_verify()
-- you can read all about that in a StackExchange question OpenSSL PKCS#7 vs. S/MIME. The function crypto.load_pkcs7_data()
comes in handy.
All that said, the following code snippet might do it for you -- although from your description it is not clear to me whether the certificate of the signer is included in the .p7s
file (in that case you do not have to give -signer
as an argument to openssl cms -verify
like you did). It worked for me, so give it a try:
from OpenSSL import crypto
from OpenSSL._util import (
ffi as _ffi,
lib as _lib,
)
# Or, alternatively:
# from cryptography.hazmat.bindings.openssl.binding import Binding
# _lib = Binding.lib
# _ffi = Binding.ffi
with open('message_der.p7s', 'rb') as f:
p7data = f.read()
p7 = crypto.load_pkcs7_data(crypto.FILETYPE_ASN1, p7data)
bio_out =crypto._new_mem_buf()
res = _lib.PKCS7_verify(p7._pkcs7, _ffi.NULL, _ffi.NULL, _ffi.NULL, bio_out, _lib.PKCS7_NOVERIFY)
if res == 1:
databytes = crypto._bio_to_string(bio_out)
print(databytes)
else:
errno = _lib.ERR_get_error()
errstrlib = _ffi.string(_lib.ERR_lib_error_string(errno))
errstrfunc = _ffi.string(_lib.ERR_func_error_string(errno))
errstrreason = _ffi.string(_lib.ERR_reason_error_string(errno))
In case you decide to use this approach, here is a caveat about using this OpenSSL bindings module directly:
