Extract extension id from (ASN1) mozilla.rsa file
Asked Answered
F

2

1

How do you retrieve the extension ID from the xpi file? (It is needed f.ex. for global extension installation)

In previous versions, you could get it from the install.rdf, which no longer exists in WebExtensions. http://www.di-mgt.com.au/how-mozilla-signs-addons.html describes that it is contained in the META-INF/mozilla.rsa file.

In python, there is the pyasn1 library. I could not get it to work on the first attempt:

from pyasn1.codec.der import decoder
f = open('/path/to/addon-dir/META-INF/mozilla.rsa')
decoder.decode(f)

gave

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/pyasn1/codec/ber/decoder.py", line 623, in __call__
    raise error.PyAsn1Error('Bad octet stream type')
pyasn1.error.PyAsn1Error: Bad octet stream type
Ferminafermion answered 2/3, 2017 at 21:13 Comment(0)
B
3

The decode method want a buffer (string), not a file object. Use:

from pyasn1.codec.der import decoder
buf = open('/path/to/addon-dir/META-INF/mozilla.rsa').read()
decoder.decode(buf)

Worked for me.

Edit:

The pyasn1_modules package includes classes that represent some common PKCS structs. You can start with something like this:

from pyasn1.codec.der import decoder as der_decoder
from pyasn1_modules import rfc5652, rfc2315, rfc5280

mozPath = "/path/to/mozilla.rsa"
buf = open(mozPath,"rb").read()
contentInfo = der_decoder.decode(buf, asn1Spec=rfc5652.ContentInfo())[0]

if contentInfo[0] != rfc2315.signedData:
    # fail...

signedData = der_decoder.decode(contentInfo[1], asn1Spec=rfc5652.SignedData())[0]

print(signedData.prettyPrint())

This produces output similar to openssl asn1parse -inform DER -in mozilla.rsa (I myself prefer pyasn1's indentation over openssl's "d=depth".)

If you want to further parse it using pyasn1 you can try something like:

for cert in signedData["certificates"]:
    subject = cert["certificate"]["tbsCertificate"]["subject"]
    for rdn in subject["rdnSequence"]:
        if rdn[0][0] == rfc5280.AttributeType("2.5.4.3"):
            cn = rdn[0][1].asOctets()[2:]          ### Not nice
            if cn != "production-signing-ca.addons.mozilla.org":
                print cn

The major problem is here is that I'm doing something kind awful to get the string in the marked line, but except for this I don't think you can get much better.

If you find out how to get the string properly please share.

Bina answered 13/4, 2017 at 21:4 Comment(2)
Sorry for the late accept. I hadn't found time to test it before. Is there an easier way than doing decoder.decode(buf)[0][1][3][0][5][5][0][1].asOctets()?Ferminafermion
@serv-inc: Define "easier". There are classes to help you parse the PKCS structs, but you still have to look for the certificates you're interested in. I've edited the answer with some more information.Bina
F
0

This hack worked:

openssl asn1parse -inform DER -in mozilla.rsa  | grep -A 1 commonName | grep '{' | cut -d ':' -f 4

It relies on

  • the output of asn1parse, and
  • that the only commonName with a { belongs to the id

Anything more elegant is appreciated.

Ferminafermion answered 2/3, 2017 at 21:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.