Python - extract certificate from p7s file
up vote
1
down vote
favorite
Decoding an incoming email in Python, I have an attachment "smime.p7s".
If I write this to a file, then it can be extracted and viewed using
openssl pkcs7 -inform der -print_certs <smime.p7s
I'd like to do that in Python. There's an example here of the inverse process, i.e. how to sign a mail.
Looking at the OpenSSL API documentation there is an entry point PKCS7_get0_signers
which seems to do this.
Here's the code snippet I'm trying, based on a naive reworking of the signing code.
with open(fname, 'wb') as p7sfile:
p7sfile.write(sig)
pkcs7 = crypto._lib.PKCS7_get0_signers(sig, None, 0)
It doesn't work - giving
pkcs7 = crypto._lib.PKCS7_get0_signers(sig, None, 0)
TypeError: initializer for ctype 'PKCS7 *' must be a cdata pointer, not bytes
The function seems to require three parameters, although maybe flags is optional?
This line of code (from the older M2Crypto library) also suggests that entry point needs three parameters.
I don't understand why it would need a "certs.stack" as an input param when we are trying to extract the certs, and I don't understand what to put in "flags".
I'm pretty sure I need some specially typed buffer declarations to set up the call, and also retrieve the results (like the bio_in = crypto._new_mem_buf(data)
preamble in 1). Can someone please suggest how to do it?
Also - the M2Crypto
library is not compatible with Python 3.x, hence looking for an alternative.
python openssl cryptography pkcs#7 smime
add a comment |
up vote
1
down vote
favorite
Decoding an incoming email in Python, I have an attachment "smime.p7s".
If I write this to a file, then it can be extracted and viewed using
openssl pkcs7 -inform der -print_certs <smime.p7s
I'd like to do that in Python. There's an example here of the inverse process, i.e. how to sign a mail.
Looking at the OpenSSL API documentation there is an entry point PKCS7_get0_signers
which seems to do this.
Here's the code snippet I'm trying, based on a naive reworking of the signing code.
with open(fname, 'wb') as p7sfile:
p7sfile.write(sig)
pkcs7 = crypto._lib.PKCS7_get0_signers(sig, None, 0)
It doesn't work - giving
pkcs7 = crypto._lib.PKCS7_get0_signers(sig, None, 0)
TypeError: initializer for ctype 'PKCS7 *' must be a cdata pointer, not bytes
The function seems to require three parameters, although maybe flags is optional?
This line of code (from the older M2Crypto library) also suggests that entry point needs three parameters.
I don't understand why it would need a "certs.stack" as an input param when we are trying to extract the certs, and I don't understand what to put in "flags".
I'm pretty sure I need some specially typed buffer declarations to set up the call, and also retrieve the results (like the bio_in = crypto._new_mem_buf(data)
preamble in 1). Can someone please suggest how to do it?
Also - the M2Crypto
library is not compatible with Python 3.x, hence looking for an alternative.
python openssl cryptography pkcs#7 smime
Possible duplicate of Extract userCertificate from PKCS7 envelop in python
– stovfl
Nov 22 at 18:23
Yes, that is related. but uses the olderM2Crypto
library which isn't Python 3.x compatible. I found a code snippet using the PyOpenSSL library below which I'll propose as a self-answer.
– steve
Nov 23 at 12:25
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
Decoding an incoming email in Python, I have an attachment "smime.p7s".
If I write this to a file, then it can be extracted and viewed using
openssl pkcs7 -inform der -print_certs <smime.p7s
I'd like to do that in Python. There's an example here of the inverse process, i.e. how to sign a mail.
Looking at the OpenSSL API documentation there is an entry point PKCS7_get0_signers
which seems to do this.
Here's the code snippet I'm trying, based on a naive reworking of the signing code.
with open(fname, 'wb') as p7sfile:
p7sfile.write(sig)
pkcs7 = crypto._lib.PKCS7_get0_signers(sig, None, 0)
It doesn't work - giving
pkcs7 = crypto._lib.PKCS7_get0_signers(sig, None, 0)
TypeError: initializer for ctype 'PKCS7 *' must be a cdata pointer, not bytes
The function seems to require three parameters, although maybe flags is optional?
This line of code (from the older M2Crypto library) also suggests that entry point needs three parameters.
I don't understand why it would need a "certs.stack" as an input param when we are trying to extract the certs, and I don't understand what to put in "flags".
I'm pretty sure I need some specially typed buffer declarations to set up the call, and also retrieve the results (like the bio_in = crypto._new_mem_buf(data)
preamble in 1). Can someone please suggest how to do it?
Also - the M2Crypto
library is not compatible with Python 3.x, hence looking for an alternative.
python openssl cryptography pkcs#7 smime
Decoding an incoming email in Python, I have an attachment "smime.p7s".
If I write this to a file, then it can be extracted and viewed using
openssl pkcs7 -inform der -print_certs <smime.p7s
I'd like to do that in Python. There's an example here of the inverse process, i.e. how to sign a mail.
Looking at the OpenSSL API documentation there is an entry point PKCS7_get0_signers
which seems to do this.
Here's the code snippet I'm trying, based on a naive reworking of the signing code.
with open(fname, 'wb') as p7sfile:
p7sfile.write(sig)
pkcs7 = crypto._lib.PKCS7_get0_signers(sig, None, 0)
It doesn't work - giving
pkcs7 = crypto._lib.PKCS7_get0_signers(sig, None, 0)
TypeError: initializer for ctype 'PKCS7 *' must be a cdata pointer, not bytes
The function seems to require three parameters, although maybe flags is optional?
This line of code (from the older M2Crypto library) also suggests that entry point needs three parameters.
I don't understand why it would need a "certs.stack" as an input param when we are trying to extract the certs, and I don't understand what to put in "flags".
I'm pretty sure I need some specially typed buffer declarations to set up the call, and also retrieve the results (like the bio_in = crypto._new_mem_buf(data)
preamble in 1). Can someone please suggest how to do it?
Also - the M2Crypto
library is not compatible with Python 3.x, hence looking for an alternative.
python openssl cryptography pkcs#7 smime
python openssl cryptography pkcs#7 smime
edited Nov 23 at 14:23
asked Nov 22 at 17:42
steve
356
356
Possible duplicate of Extract userCertificate from PKCS7 envelop in python
– stovfl
Nov 22 at 18:23
Yes, that is related. but uses the olderM2Crypto
library which isn't Python 3.x compatible. I found a code snippet using the PyOpenSSL library below which I'll propose as a self-answer.
– steve
Nov 23 at 12:25
add a comment |
Possible duplicate of Extract userCertificate from PKCS7 envelop in python
– stovfl
Nov 22 at 18:23
Yes, that is related. but uses the olderM2Crypto
library which isn't Python 3.x compatible. I found a code snippet using the PyOpenSSL library below which I'll propose as a self-answer.
– steve
Nov 23 at 12:25
Possible duplicate of Extract userCertificate from PKCS7 envelop in python
– stovfl
Nov 22 at 18:23
Possible duplicate of Extract userCertificate from PKCS7 envelop in python
– stovfl
Nov 22 at 18:23
Yes, that is related. but uses the older
M2Crypto
library which isn't Python 3.x compatible. I found a code snippet using the PyOpenSSL library below which I'll propose as a self-answer.– steve
Nov 23 at 12:25
Yes, that is related. but uses the older
M2Crypto
library which isn't Python 3.x compatible. I found a code snippet using the PyOpenSSL library below which I'll propose as a self-answer.– steve
Nov 23 at 12:25
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
I found a useful code snippet here. This extracts certs from a PKCS7 binary object into a list of OpenSSL.crypto.X509
objects.
The OpenSSL.crypto.X509 object is OK for dumping out the certificate contents (it has a dump_certificate
method), but the attributes are hard to work with as they are still ASN.1 encoded and are C types.
Once you've got a list of certs, each can be converted into a cryptography
Certificate
object which is Python native and more amenable. For example:
class Cert(object):
"""
Convenient container object for human-readable and output-file friendly certificate contents
"""
pem = ''
email_signer = None
startT = None
endT = None
issuer = {}
algorithm = None
def extract_smime_signature(payload):
"""
Extract public certificates from the PKCS7 binary payload
:param payload: bytes
:return: list of Cert objects
"""
pkcs7 = crypto.load_pkcs7_data(crypto.FILETYPE_ASN1, payload)
certs = get_certificates(pkcs7)
certList =
# Collect the following info from the certificates
all_cert_times_valid = True
for c in certs:
# Convert to the modern & easier to use https://cryptography.io library objects
c2 = crypto.X509.to_cryptography(c)
c3 = Cert()
# check each certificate's time validity, ANDing cumulatively across each one
c3.startT = c2.not_valid_before
c3.endT = c2.not_valid_after
now = datetime.now()
all_cert_times_valid = all_cert_times_valid and (c3.startT <= now) and (now <= c3.endT)
# get Issuer, unpacking the ASN.1 structure into a dict
for i in c2.issuer.rdns:
for j in i:
c3.issuer[j.oid._name] = j.value
# get email address from the cert "subject" - consider more than one address in the bundle as an error
for i in c2.subject.rdns:
for j in i:
attrName = j.oid._name
if attrName == 'emailAddress':
c3.email_signer = j.value
# Get hash alg - just for interest
c3.algorithm = c2.signature_hash_algorithm.name
c3.pem = c2.public_bytes(serialization.Encoding.PEM).decode('utf8')
certList.append(c3)
return certList
The checks on the certs made in this code are overly simplistic. With access to a trusted cert bundle (such as the file "ca-bundle.crt" available in many Linuxes) it's possible to do much better than this. It's work in progress, but see github.com/tuck1s/sparkySecure/blob/master/readSMIMEsig.py
– steve
2 days ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436023%2fpython-extract-certificate-from-p7s-file%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
I found a useful code snippet here. This extracts certs from a PKCS7 binary object into a list of OpenSSL.crypto.X509
objects.
The OpenSSL.crypto.X509 object is OK for dumping out the certificate contents (it has a dump_certificate
method), but the attributes are hard to work with as they are still ASN.1 encoded and are C types.
Once you've got a list of certs, each can be converted into a cryptography
Certificate
object which is Python native and more amenable. For example:
class Cert(object):
"""
Convenient container object for human-readable and output-file friendly certificate contents
"""
pem = ''
email_signer = None
startT = None
endT = None
issuer = {}
algorithm = None
def extract_smime_signature(payload):
"""
Extract public certificates from the PKCS7 binary payload
:param payload: bytes
:return: list of Cert objects
"""
pkcs7 = crypto.load_pkcs7_data(crypto.FILETYPE_ASN1, payload)
certs = get_certificates(pkcs7)
certList =
# Collect the following info from the certificates
all_cert_times_valid = True
for c in certs:
# Convert to the modern & easier to use https://cryptography.io library objects
c2 = crypto.X509.to_cryptography(c)
c3 = Cert()
# check each certificate's time validity, ANDing cumulatively across each one
c3.startT = c2.not_valid_before
c3.endT = c2.not_valid_after
now = datetime.now()
all_cert_times_valid = all_cert_times_valid and (c3.startT <= now) and (now <= c3.endT)
# get Issuer, unpacking the ASN.1 structure into a dict
for i in c2.issuer.rdns:
for j in i:
c3.issuer[j.oid._name] = j.value
# get email address from the cert "subject" - consider more than one address in the bundle as an error
for i in c2.subject.rdns:
for j in i:
attrName = j.oid._name
if attrName == 'emailAddress':
c3.email_signer = j.value
# Get hash alg - just for interest
c3.algorithm = c2.signature_hash_algorithm.name
c3.pem = c2.public_bytes(serialization.Encoding.PEM).decode('utf8')
certList.append(c3)
return certList
The checks on the certs made in this code are overly simplistic. With access to a trusted cert bundle (such as the file "ca-bundle.crt" available in many Linuxes) it's possible to do much better than this. It's work in progress, but see github.com/tuck1s/sparkySecure/blob/master/readSMIMEsig.py
– steve
2 days ago
add a comment |
up vote
0
down vote
I found a useful code snippet here. This extracts certs from a PKCS7 binary object into a list of OpenSSL.crypto.X509
objects.
The OpenSSL.crypto.X509 object is OK for dumping out the certificate contents (it has a dump_certificate
method), but the attributes are hard to work with as they are still ASN.1 encoded and are C types.
Once you've got a list of certs, each can be converted into a cryptography
Certificate
object which is Python native and more amenable. For example:
class Cert(object):
"""
Convenient container object for human-readable and output-file friendly certificate contents
"""
pem = ''
email_signer = None
startT = None
endT = None
issuer = {}
algorithm = None
def extract_smime_signature(payload):
"""
Extract public certificates from the PKCS7 binary payload
:param payload: bytes
:return: list of Cert objects
"""
pkcs7 = crypto.load_pkcs7_data(crypto.FILETYPE_ASN1, payload)
certs = get_certificates(pkcs7)
certList =
# Collect the following info from the certificates
all_cert_times_valid = True
for c in certs:
# Convert to the modern & easier to use https://cryptography.io library objects
c2 = crypto.X509.to_cryptography(c)
c3 = Cert()
# check each certificate's time validity, ANDing cumulatively across each one
c3.startT = c2.not_valid_before
c3.endT = c2.not_valid_after
now = datetime.now()
all_cert_times_valid = all_cert_times_valid and (c3.startT <= now) and (now <= c3.endT)
# get Issuer, unpacking the ASN.1 structure into a dict
for i in c2.issuer.rdns:
for j in i:
c3.issuer[j.oid._name] = j.value
# get email address from the cert "subject" - consider more than one address in the bundle as an error
for i in c2.subject.rdns:
for j in i:
attrName = j.oid._name
if attrName == 'emailAddress':
c3.email_signer = j.value
# Get hash alg - just for interest
c3.algorithm = c2.signature_hash_algorithm.name
c3.pem = c2.public_bytes(serialization.Encoding.PEM).decode('utf8')
certList.append(c3)
return certList
The checks on the certs made in this code are overly simplistic. With access to a trusted cert bundle (such as the file "ca-bundle.crt" available in many Linuxes) it's possible to do much better than this. It's work in progress, but see github.com/tuck1s/sparkySecure/blob/master/readSMIMEsig.py
– steve
2 days ago
add a comment |
up vote
0
down vote
up vote
0
down vote
I found a useful code snippet here. This extracts certs from a PKCS7 binary object into a list of OpenSSL.crypto.X509
objects.
The OpenSSL.crypto.X509 object is OK for dumping out the certificate contents (it has a dump_certificate
method), but the attributes are hard to work with as they are still ASN.1 encoded and are C types.
Once you've got a list of certs, each can be converted into a cryptography
Certificate
object which is Python native and more amenable. For example:
class Cert(object):
"""
Convenient container object for human-readable and output-file friendly certificate contents
"""
pem = ''
email_signer = None
startT = None
endT = None
issuer = {}
algorithm = None
def extract_smime_signature(payload):
"""
Extract public certificates from the PKCS7 binary payload
:param payload: bytes
:return: list of Cert objects
"""
pkcs7 = crypto.load_pkcs7_data(crypto.FILETYPE_ASN1, payload)
certs = get_certificates(pkcs7)
certList =
# Collect the following info from the certificates
all_cert_times_valid = True
for c in certs:
# Convert to the modern & easier to use https://cryptography.io library objects
c2 = crypto.X509.to_cryptography(c)
c3 = Cert()
# check each certificate's time validity, ANDing cumulatively across each one
c3.startT = c2.not_valid_before
c3.endT = c2.not_valid_after
now = datetime.now()
all_cert_times_valid = all_cert_times_valid and (c3.startT <= now) and (now <= c3.endT)
# get Issuer, unpacking the ASN.1 structure into a dict
for i in c2.issuer.rdns:
for j in i:
c3.issuer[j.oid._name] = j.value
# get email address from the cert "subject" - consider more than one address in the bundle as an error
for i in c2.subject.rdns:
for j in i:
attrName = j.oid._name
if attrName == 'emailAddress':
c3.email_signer = j.value
# Get hash alg - just for interest
c3.algorithm = c2.signature_hash_algorithm.name
c3.pem = c2.public_bytes(serialization.Encoding.PEM).decode('utf8')
certList.append(c3)
return certList
I found a useful code snippet here. This extracts certs from a PKCS7 binary object into a list of OpenSSL.crypto.X509
objects.
The OpenSSL.crypto.X509 object is OK for dumping out the certificate contents (it has a dump_certificate
method), but the attributes are hard to work with as they are still ASN.1 encoded and are C types.
Once you've got a list of certs, each can be converted into a cryptography
Certificate
object which is Python native and more amenable. For example:
class Cert(object):
"""
Convenient container object for human-readable and output-file friendly certificate contents
"""
pem = ''
email_signer = None
startT = None
endT = None
issuer = {}
algorithm = None
def extract_smime_signature(payload):
"""
Extract public certificates from the PKCS7 binary payload
:param payload: bytes
:return: list of Cert objects
"""
pkcs7 = crypto.load_pkcs7_data(crypto.FILETYPE_ASN1, payload)
certs = get_certificates(pkcs7)
certList =
# Collect the following info from the certificates
all_cert_times_valid = True
for c in certs:
# Convert to the modern & easier to use https://cryptography.io library objects
c2 = crypto.X509.to_cryptography(c)
c3 = Cert()
# check each certificate's time validity, ANDing cumulatively across each one
c3.startT = c2.not_valid_before
c3.endT = c2.not_valid_after
now = datetime.now()
all_cert_times_valid = all_cert_times_valid and (c3.startT <= now) and (now <= c3.endT)
# get Issuer, unpacking the ASN.1 structure into a dict
for i in c2.issuer.rdns:
for j in i:
c3.issuer[j.oid._name] = j.value
# get email address from the cert "subject" - consider more than one address in the bundle as an error
for i in c2.subject.rdns:
for j in i:
attrName = j.oid._name
if attrName == 'emailAddress':
c3.email_signer = j.value
# Get hash alg - just for interest
c3.algorithm = c2.signature_hash_algorithm.name
c3.pem = c2.public_bytes(serialization.Encoding.PEM).decode('utf8')
certList.append(c3)
return certList
edited Nov 23 at 15:43
answered Nov 23 at 12:32
steve
356
356
The checks on the certs made in this code are overly simplistic. With access to a trusted cert bundle (such as the file "ca-bundle.crt" available in many Linuxes) it's possible to do much better than this. It's work in progress, but see github.com/tuck1s/sparkySecure/blob/master/readSMIMEsig.py
– steve
2 days ago
add a comment |
The checks on the certs made in this code are overly simplistic. With access to a trusted cert bundle (such as the file "ca-bundle.crt" available in many Linuxes) it's possible to do much better than this. It's work in progress, but see github.com/tuck1s/sparkySecure/blob/master/readSMIMEsig.py
– steve
2 days ago
The checks on the certs made in this code are overly simplistic. With access to a trusted cert bundle (such as the file "ca-bundle.crt" available in many Linuxes) it's possible to do much better than this. It's work in progress, but see github.com/tuck1s/sparkySecure/blob/master/readSMIMEsig.py
– steve
2 days ago
The checks on the certs made in this code are overly simplistic. With access to a trusted cert bundle (such as the file "ca-bundle.crt" available in many Linuxes) it's possible to do much better than this. It's work in progress, but see github.com/tuck1s/sparkySecure/blob/master/readSMIMEsig.py
– steve
2 days ago
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436023%2fpython-extract-certificate-from-p7s-file%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Possible duplicate of Extract userCertificate from PKCS7 envelop in python
– stovfl
Nov 22 at 18:23
Yes, that is related. but uses the older
M2Crypto
library which isn't Python 3.x compatible. I found a code snippet using the PyOpenSSL library below which I'll propose as a self-answer.– steve
Nov 23 at 12:25