title: Reading the certificate of PKCS#7 Signed Data using pure python
body: <p>There is already a lot of questions out there but the problem is, none of them have sufficient answers how to do it, especially when using python3.</p>
  
  <p>Basically, I want to read JAR/APK certificates, like this one: <a href="http://lapo.it/asn1js/#308206AE06092A864886F70D010702A082069F3082069B020101310B300906052B0E03021A0500300B06092A864886F70D010701A08204AC308204A830820390A003020102020900936EACBE07F201DF300D06092A864886F70D0101050500308194310B3009060355040613025553311330110603550408130A43616C69666F726E6961311630140603550407130D4D6F756E7461696E20566965773110300E060355040A1307416E64726F69643110300E060355040B1307416E64726F69643110300E06035504031307416E64726F69643122302006092A864886F70D0109011613616E64726F696440616E64726F69642E636F6D301E170D3038303232393031333334365A170D3335303731373031333334365A308194310B3009060355040613025553311330110603550408130A43616C69666F726E6961311630140603550407130D4D6F756E7461696E20566965773110300E060355040A1307416E64726F69643110300E060355040B1307416E64726F69643110300E06035504031307416E64726F69643122302006092A864886F70D0109011613616E64726F696440616E64726F69642E636F6D30820120300D06092A864886F70D01010105000382010D00308201080282010100D6931904DEC60B24B1EDC762E0D9D8253E3ECD6CEB1DE2FF068CA8E8BCA8CD6BD3786EA70AA76CE60EBB0F993559FFD93E77A943E7E83D4B64B8E4FEA2D3E656F1E267A81BBFB230B578C20443BE4C7218B846F5211586F038A14E89C2BE387F8EBECF8FCAC3DA1EE330C9EA93D0A7C3DC4AF350220D50080732E0809717EE6A053359E6A694EC2CB3F284A0A466C87A94D83B31093A67372E2F6412C06E6D42F15818DFFE0381CC0CD444DA6CDDC3B82458194801B32564134FBFDE98C9287748DBF5676A540D8154C8BBCA07B9E247553311C46B9AF76FDEECCC8E69E7C8A2D08E782620943F99727D3C04FE72991D99DF9BAE38A0B2177FA31D5B6AFEE91F020103A381FC3081F9301D0603551D0E04160414485900563D272C46AE118605A47419AC09CA8C113081C90603551D230481C13081BE8014485900563D272C46AE118605A47419AC09CA8C11A1819AA48197308194310B3009060355040613025553311330110603550408130A43616C69666F726E6961311630140603550407130D4D6F756E7461696E20566965773110300E060355040A1307416E64726F69643110300E060355040B1307416E64726F69643110300E06035504031307416E64726F69643122302006092A864886F70D0109011613616E64726F696440616E64726F69642E636F6D820900936EACBE07F201DF300C0603551D13040530030101FF300D06092A864886F70D010105050003820101007AAF968CEB50C441055118D0DAABAF015B8A765A27A715A2C2B44F221415FFDACE03095ABFA42DF70708726C2069E5C36EDDAE0400BE29452C084BC27EB6A17EAC9DBE182C204EB15311F455D824B656DBE4DC2240912D7586FE88951D01A8FEB5AE5A4260535DF83431052422468C36E22C2A5EF994D61DD7306AE4C9F6951BA3C12F1D1914DDC61F1A62DA2DF827F603FEA5603B2C540DBD7C019C36BAB29A4271C117DF523CDBC5F3817A49E0EFA60CBD7F74177E7A4F193D43F4220772666E4C4D83E1BD5A86087CF34F2DEC21E245CA6C2BB016E683638050D2C430EEA7C26A1C49D3760A58AB7F1A82CC938B4831384324BD0401FA12163A50570E684D318201CA308201C60201013081A2308194310B3009060355040613025553311330110603550408130A43616C69666F726E6961311630140603550407130D4D6F756E7461696E20566965773110300E060355040A1307416E64726F69643110300E060355040B1307416E64726F69643110300E06035504031307416E64726F69643122302006092A864886F70D0109011613616E64726F696440616E64726F69642E636F6D020900936EACBE07F201DF300906052B0E03021A0500300D06092A864886F70D01010105000482010097F573FC2453BCCD534950C572AE222B0E54CB8483A67F675903657DE94BAB6B1B222F056496B37AF12C24A8840112E8968DFAF369B7EB03FE2FA7EBA65E66FE89B6600FEB7BE8273F0C57E069B7397BA7A5DA1DBBA529BA85443B7AEB723FF5DAF53F47A1EA31CF1716616DCE81E2271964974FA1C064B4738A0A04E87A34AFB3BBA74D2DEB974C3DCD6609D2F61338612DC143F17E8CCB12179DBD22D344FE5D8E3AF0BF8B2E8F11635F7F540042924C82D7C8D49553F16EB57A5875B0249204F1AB6417A754A2955823F595D2926DEAF91F9515BFF8A10BD03D3A2CBC222A423018175A6EFEDE59F3D7FA6D39ACA599831D04E583CBC423D4244718ED2F42" rel="nofollow noreferrer">Link to ASN1 Decoder, with Android Test Signing Key</a></p>
  
  <p>There are now several alternatives:</p>
  
  <ul>
  <li>pyasn1: seems to work, but only can parse the raw ASN.1 format</li>
  <li>M2Crypto: only works on py2</li>
  <li>Chilkat: Not free, although CkCert seems to be free</li>
  <li>cryptography: Can not load the certificate, as the X509 certificate is inside the PKCS#7 container</li>
  </ul>
  
  <p>I found a way to use pyasn1 to unpack the cert from the pkcs#7 message, then use cryptography to read it:</p>
  
  <pre><code>from pyasn1.codec.der.decoder import decode
  from pyasn1.codec.der.encoder import encode
  from cryptography import x509
  from cryptography.hazmat.backends import default_backend
  
  cdata = open("CERT.RSA", "rb").read()
  cert, rest = decode(cdata)
  # The cert should be located there
  realcert = encode(cert[1][3])
  realcert = realcert[2 + (realcert[1] &amp; 0x7F) if realcert[1] &amp; 0x80 &gt; 1 else 2:]  # remove the first DER identifier from the front
  x509.load_der_x509_certificate(realcert, default_backend())
  </code></pre>
  
  <p>which gives</p>
  
  <pre><code>&lt;Certificate(subject=&lt;Name([&lt;NameAttribute(oid=&lt;ObjectIdentifier(oid=2.5.4.6, name=countryName)&gt;, value='US')&gt;, &lt;NameAttribute(oid=&lt;ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)&gt;, value='California')&gt;, &lt;NameAttribute(oid=&lt;ObjectIdentifier(oid=2.5.4.7, name=localityName)&gt;, value='Mountain View')&gt;, &lt;NameAttribute(oid=&lt;ObjectIdentifier(oid=2.5.4.10, name=organizationName)&gt;, value='Android')&gt;, &lt;NameAttribute(oid=&lt;ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)&gt;, value='Android')&gt;, &lt;NameAttribute(oid=&lt;ObjectIdentifier(oid=2.5.4.3, name=commonName)&gt;, value='Android')&gt;, &lt;NameAttribute(oid=&lt;ObjectIdentifier(oid=1.2.840.113549.1.9.1, name=emailAddress)&gt;, value='android@android.com')&gt;])&gt;, ...)&gt;
  </code></pre>
  
  <p>Is there no other way to have it clean and tidy?</p>