我需要获取PKCS#7信封的摘要才能手动检查它。
通常,当您想要验证pkcs#7信封的签名时,您可以这样做:
from M2Crypto import SMIME, X509, BIO
sm_obj = SMIME.SMIME()
x509 = X509.load_cert(join(PATH, 'QualifiedChain.crt'))
sk = X509.X509_Stack()
sk.push(x509)
sm_obj.set_x509_stack(sk)
st = X509.X509_Store()
st.load_info(join(PATH, 'QualifiedChain.crt'))
sm_obj.set_x509_store(st)
# re-wrap signature so that it fits base64 standards
cooked_sig = '\n'.join(raw_sig[pos:pos + 76] for pos in
xrange(0, len(raw_sig), 76))
# now, wrap the signature in a PKCS7 block
sig = "-----BEGIN PKCS7-----\n%s\n-----END PKCS7-----\n" % cooked_sig
# and load it into an SMIME p7 object through the BIO I/O buffer:
buf = BIO.MemoryBuffer(sig)
p7 = SMIME.load_pkcs7_bio(buf)
signers = p7.get0_signers(sk)
certificat = signers[0]
data_bio = BIO.MemoryBuffer(MSG)
sm_obj.verify(p7, data_bio) # This is the line that count.
但就我而言,摘要类型是md5sha1,openssl无法识别:
$ openssl list-message-digest-commands
md4
md5
rmd160
sha
sha1
我需要做什么才能获得pkcs#7 signedContent并手动检查它。
我需要的是一个等同于org.bouncycastle.cms.CMSSignedDataParser
的Python。
如何在不使用sm_obj.verify
的情况下手动验证摘要?
答案 0 :(得分:4)
好的,所以我能够用bash做到这一点:
#!/bin/bash
if [ $# -ne 1 ]; then
echo "USAGE: $0 sig.pkcs7.pem"
exit 1
fi
rm -fr /tmp/pkcs7tosignature
mkdir /tmp/pkcs7tosignature
cp "$1" /tmp/pkcs7tosignature/sig.pkcs7
cd /tmp/pkcs7tosignature/
# Convert PEM pkcs7 to DER
openssl pkcs7 -in sig.pkcs7 -inform PEM -out sig.der -outform DER
# Extract x509 certificate
openssl pkcs7 -in sig.pkcs7 -inform PEM -print_certs > cert.pem
# Look for signed signature offset
offset=$(openssl asn1parse -inform der -in sig.der | python -c "import sys; l = sys.stdin.readlines()[-1]; print int(l.split(':')[0]) + int(l.split('hl=')[1].split()[0])")
count=$(openssl asn1parse -inform der -in sig.der | python -c "import sys; l = sys.stdin.readlines()[-1]; print int(l.split('hl=')[1].split('l=')[1].split()[0])")
# Copy signed signature
dd if=sig.der of=signed-sha1.bin bs=1 skip=$[ $offset ] count=$count 2>/dev/null
# Extract public key from certificate
openssl x509 -inform pem -in cert.pem -noout -pubkey > pubkey.pem
# Decrypt signed signature
openssl rsautl -verify -pubin -inkey pubkey.pem < signed-sha1.bin > verified.bin
# Print pkcs7 algorithm
openssl asn1parse -inform der -in verified.bin | python -c "import sys; l = sys.stdin.read(); print l.split('OBJECT')[1].split('\n')[0].split(':')[1].strip()"
# Print pkcs7 signature
openssl asn1parse -inform der -in verified.bin | python -c "import sys; l = sys.stdin.read(); print l.split('[HEX DUMP]:')[1].split('\n')[0].strip()"
现在只需要用Python转换它。
答案 1 :(得分:2)
尝试以下内容,深受此blog post启发:
import OpenSSL
from Crypto.Util import asn1
c=OpenSSL.crypto
certbuffer = # get your PEM here, e.g. by cert = open("/path/to/file.pkcs7.pem", 'rb').read()
# This is the certificate to validate
# an OpenSSL.crypto.X509 object
cert=c.load_certificate(crypto.FILETYPE_PEM, certbuffer)
# Get the signing algorithm
algo=cert.get_signature_algorithm()
# Get the ASN1 format of the certificate
cert_asn1=c.dump_certificate(c.FILETYPE_ASN1, cert)
# Decode the certificate
der=asn1.DerSequence()
der.decode(cert_asn1)
# The certificate has three parts:
# - certificate
# - signature algorithm
# - signature
# http://usefulfor.com/nothing/2009/06/10/x509-certificate-basics/
der_cert=der[0]
der_algo=der[1]
der_sig=der[2]
# The signature is a BIT STRING (Type 3)
# Decode that as well
der_sig_in=asn1.DerObject()
der_sig_in.decode(der_sig)
# Get the payload
sig0=der_sig_in.payload
# Do the following to see a validation error for tests
# der_cert=der_cert[:20]+'1'+der_cert[21:]
# First byte is the number of unused bits. This should be 0
# http://msdn.microsoft.com/en-us/library/windows/desktop/bb540792(v=vs.85).aspx
if sig0[0]!='\x00':
raise Exception('Number of unused bits is strange')
# Now get the signature itself
sig=sig0[1:]
# and do the actual verification against your custom hash
# ...
答案 2 :(得分:0)
PKCS7有一个SignerInfos集合。每个SignerInfo可以具有不同的消息摘要算法。
见https://github.com/erny/pyx509。这需要pyasn1和pyasn1-modules。
./pkcs_parse <pkcs7 signature in DER format>
这为每个签名者信息提取摘要算法。