我在加载pkcs#7文件时遇到问题,请求帮助找出我做错了什么。
我使用OpenSSL 0.9.8g运行M2Crypto-0.21.1(如Ubuntu 9.4中所示),并使用SWIG 1.3.36和python 2.6.2构建。
“python setup.py test --test-suite = tests.test_smime”运行15次测试,退出状态为“OK”;所以安装似乎没问题。
我使用数字签名程序以PEM格式创建了一个pkcs#7文件,并使用OpenSSL从命令行对其进行了测试:
openssl smime -verify -inform PEM -in mandato-PEM.p7m -noverify
打印信封中包含的内容(我签名的文本文件)和“验证成功”。所以OpenSSL(与M2Crypto使用的版本相同)似乎喜欢我的文件。
但是,当我在M2Crypto中尝试相同的操作时,它会在开头就开始窒息:
p7,data = SMIME.smime_load_pkcs7('mandato-PEM.p7m')
我得到以下异常:
Traceback (most recent call last): File "./sign.py", line 110, in <module> p7, data = SMIME.smime_load_pkcs7('mandato-PEM.p7m') File "/usr/local/lib/python2.6/dist-packages/M2Crypto-0.21.1-py2.6-linux-i686.egg/M2Crypto/SMIME.py", line 91, in smime_load_pkcs7 p7_ptr, bio_ptr = m2.smime_read_pkcs7(bio) M2Crypto.SMIME.SMIME_Error: no content type
虽然我在Ubuntu(https://lists.ubuntu.com/archives/ubuntu-server-bugs/2010-July/038683.html)中找到了问题的信息,但在我看来这不适用于此因为我手动构建了最新的M2Crypto,测试套件运行正常。
任何帮助解决我的问题都将受到高度赞赏!
非常感谢-bud
答案 0 :(得分:2)
经过大量的努力,这里解决了遇到同样问题的其他人。
我正在关注食谱http://code.activestate.com/recipes/285211/,并在网上发现了许多只是“验证(p7)”[SMIME的方法]不正确并且“验证(p7,数据)”是正确的事情的讨论去做。
这仅适用于分离签名的SMIME文档。我的pkcs#7文件和所有其他意大利数字签名文件都是pkcs#7信封,其中包含签名和文件内容(采用DER格式)。
必须按如下方式验证已封装的p7m文件:
s=SMIME.SMIME()
st = X509.X509_Store()
st.load_info(trustedCAsPEMfileName)
s.set_x509_store(st)
p7bio = BIO.MemoryBuffer(p7strPEM)
p7 = SMIME.load_pkcs7_bio(p7bio)
certStack = p7.get0_signers(X509.X509_Stack())
s.set_x509_stack(certStack)
try:
docContent = s.verify(p7)
except SMIME.PKCS7_Error, e:
print "An exception occurred!!!!"
print e
为了测试这是否有效,我编辑了p7m文件,使签名不再验证,并正确打印出“摘要失败”。
答案 1 :(得分:2)
您也可以直接验证.p7m文件(附加的DER格式),但需要通过m2直接调用OpenSSL(m2.pkcs7_read_bio_der(input_bio._ptr())
)从DER格式加载PKCS#7对象,因为此内部没有此功能M2Crypto SMIME模块。有关建议的补丁,请参阅Small patch to SMIME.py。
这是一个示例代码:
import logging
from M2Crypto import SMIME, X509, m2, BIO
certstore_path = "/etc/ssl/certs/ca-certificates.crt"
file_descriptor = open('test_file.p7m', 'rb')
input_bio = BIO.File(file_descriptor)
signer = SMIME.SMIME()
cert_store = X509.X509_Store()
cert_store.load_info(certstore_path)
signer.set_x509_store(cert_store)
try:
p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(input_bio._ptr()), 1)
except SMIME.SMIME_Error, e:
logging.error('load pkcs7 error: ' + str(e))
sk3 = p7.get0_signers(X509.X509_Stack())
signer.set_x509_stack(sk3)
data_bio = None
try:
v = signer.verify(p7, data_bio)
except SMIME.SMIME_Error, e:
logging.error('smime error: ' + str(e))
except SMIME.PKCS7_Error, e:
logging.error('pkcs7 error: ' + str(e))
代码来源:pysmime core
答案 2 :(得分:0)
我发现签名和签名的最佳参考是M2Crypto测试:
http://svn.osafoundation.org/m2crypto/trunk/tests/test_smime.py
def test_sign(self):
buf = BIO.MemoryBuffer(self.cleartext)
s = SMIME.SMIME()
s.load_key('tests/signer_key.pem', 'tests/signer.pem')
p7 = s.sign(buf, SMIME.PKCS7_DETACHED)
assert len(buf) == 0
assert p7.type() == SMIME.PKCS7_SIGNED, p7.type()
assert isinstance(p7, SMIME.PKCS7), p7
out = BIO.MemoryBuffer()
p7.write(out)
buf = out.read()
assert buf[:len('-----BEGIN PKCS7-----')] == '-----BEGIN PKCS7-----'
buf = buf.strip()
assert buf[-len('-----END PKCS7-----'):] == '-----END PKCS7-----', buf[-len('-----END PKCS7-----'):]
assert len(buf) > len('-----END PKCS7-----') + len('-----BEGIN PKCS7-----')
s.write(out, p7, BIO.MemoryBuffer(self.cleartext))
return out
def test_verify(self):
s = SMIME.SMIME()
x509 = X509.load_cert('tests/signer.pem')
sk = X509.X509_Stack()
sk.push(x509)
s.set_x509_stack(sk)
st = X509.X509_Store()
st.load_info('tests/ca.pem')
s.set_x509_store(st)
p7, data = SMIME.smime_load_pkcs7_bio(self.signed)
assert isinstance(p7, SMIME.PKCS7), p7
v = s.verify(p7, data)
assert v == self.cleartext
t = p7.get0_signers(sk)
assert len(t) == 1
assert t[0].as_pem() == x509.as_pem(), t[0].as_text()
请注意文档(http://svn.osafoundation.org/m2crypto/trunk/doc/howto.smime.html),因为它没有更新。
请参阅此补丁:
答案 3 :(得分:0)
如果您只想从.p7m文件中提取原始文件(而不进行验证),则需要使用pip install M2Crypto
安装M2Crypto(您可能必须先运行sudo apt-get install libssl-dev
),然后再运行Python代码:
from M2Crypto import BIO, SMIME, X509
# Load file in memory just to showcase BIO usage
with open('file.p7m', 'rb') as file:
p7m = file.read()
smime = SMIME.SMIME()
smime.set_x509_store(X509.X509_Store())
smime.set_x509_stack(X509.X509_Stack())
original_file_content = smime.verify(
SMIME.load_pkcs7_bio_der(BIO.MemoryBuffer(p7m)),
flags=SMIME.PKCS7_NOVERIFY
)
根据使用情况,您可以使用SMIME.load_pkcs7
,SMIME.load_pkcs7_bio
,SMIME.load_pkcs7_der
而不是SMIME.load_pkcs7_bio_der
:内存(_bio
)或文件系统上.p7m文件以及PEM或DER(_der
)格式。