Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the signed content from a PKCS7 envelop with M2Crypto?

I need to get the digest of a PKCS#7 envelop to manually check it.

Usually when you want to validate the signature of a pkcs#7 envelop you do that:

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.

But in my case, the digest type is md5sha1 that is not recognized by openssl:

$ openssl list-message-digest-commands
md4
md5
rmd160
sha
sha1

What I need to do I to get the pkcs#7 signedContent and to manually check it.

What I need is a Python equivalent to org.bouncycastle.cms.CMSSignedDataParser.

How can I get the digest to be able to validate it manually without having to use sm_obj.verify?

like image 551
Natim Avatar asked Mar 29 '13 09:03

Natim


People also ask

What is PKCS7 signature?

PKCS #7 is the specific standard used for generation and verification of digital signatures and certificates managed by a PKI (Public Key Infrastructure). This standard served as the basis for the S/MIME (Secure/Multipurpose Internet Mail Extensions) standard.


1 Answers

Ok so I was able to do it in 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()"

Just need to convert it in Python now.

like image 54
Natim Avatar answered Oct 08 '22 10:10

Natim