mmadfox / go-crx3

Chrome browser extension tools. Provides a set of tools packing, unpacking, zip, unzip, download, etc.
Apache License 2.0
26 stars 8 forks source link

Support `key` command #5

Open przemoc opened 6 months ago

przemoc commented 6 months ago

id command is already supported, but another useful one would be key.

key should be equivalent of what following command does on private key: openssl rsa -in key.pem -pubout -outform DER | openssl base64 -A

If CRX/ZIP's manifest.json has a key field, then key command could be made to work also on such CRX/ZIP files and display their key then.

This key value is useful for developers to keep consistent ID: https://developer.chrome.com/docs/extensions/reference/manifest/key


BTW thank you for creating the tool! This year I have to update my web browser extension, NavigUp, and migrate to Manifest V3 (known issues, checklist) to ensure its users won't be impacted by Manifest V2 support timeline, specifically:

June 2024: Chrome MV2 deprecation pre-stable rollout
June 2024 + 1-X months: Chrome MV2 deprecation stable rollout

At some point Chrome deprecated CRX2 format and introduced CRX3 - CRX₃ Design Doc. Beside relying on Chrome Web Store, I always self-hosted my extension too, so being able to create CRX3 easily will be super handy.


In the distant past I used crxmake, possibly https://github.com/Constellation/crxmake, but I have no notes to tell for sure. I refuse to accept need to use hundred megabyte browser binary to create crx file. If not for your tool, i.e. crx3, I would possibly had to write one for myself (most likely in C/C++). There are some JavaScript based solutions, but I'm not fan of JavaScript runtime environments like Node.js, and prefer more standalone solutions.

mmadfox commented 4 weeks ago

Thank you very much for the great ideas. I added the pubkey command in the new release.

przemoc commented 4 weeks ago

Thank you for introducing pubkey command. Did you test it with CRX files out there?

I did a quick check on my extension (still not migrated to MV3, but in CRX3 format when obtained from webstore), confronting results with handy Chrome extension source viewer, openssl, and webstore. go-crx3 doesn't seem to provide proper results.

go-crx3

$ crx3 pubkey ~/Downloads/eigojmmlmgigbldiclbpibmjnlbdpiaa.crx
MIIBCgKCAQEAj/u/XDdjlDyw7gHEtaaasZ9GdG8WOKAyJzXd8HFrDtz2Jcuy7er7MtWvHgNDA0bwpznbI5YdZeV4UfCEsA4SrA5b3MnWTHwA1bgbiDM+L9rrqvcadcKuOlTeN48Q0ijmhHlNFbTzvT9W0zw/GKv8LgXAHggxtmHQ/Z9PP2QNF5O8rUHHSL4AJ6hNcEKSBVSmbbjeVm4gSXDuED5r0nwxvRtupDxGYp8IZpP5KlExqNu1nbkPc+igCTIB6XsqijagzxewUHCdovmkb2JNtskx/PMIEv+TvWIx2BzqGp71gSh/dV7SJ3rClvWd2xj8dtxG8FfAWDTIIi0qZXWn2QhizQIDAQAB
$ crx3 id ~/Downloads/eigojmmlmgigbldiclbpibmjnlbdpiaa.crx
eigojmmlmgigbldiclbpibmjnlbdpiaa

Extension page > Chrome extension source viewer > View source > Dev Console:

Public key (paste into manifest.json to preserve extension ID)
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDR8RyDbBAaZaEsh4VTye63j6QDOGP1YMSCJ+2KyJXH8IHneddHl2mUKD27FrNNUm7N6NnzRSFmVRolvgph4CByu3D7mHdDekNk8cj0ilsfF+GlUllGPMCPzalp+Zitufq81Cg4oModC3SvPUT1gQIQ9NGGkjlOrBu9J6gs/syPRQIDAQAB",
Calculated extension ID: eigojmmlmgigbldiclbpibmjnlbdpiaa

openssl

$ openssl rsa -in navigup.pem -inform PEM -pubout -outform DER | openssl base64 -A
writing RSA key
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDR8RyDbBAaZaEsh4VTye63j6QDOGP1YMSCJ+2KyJXH8IHneddHl2mUKD27FrNNUm7N6NnzRSFmVRolvgph4CByu3D7mHdDekNk8cj0ilsfF+GlUllGPMCPzalp+Zitufq81Cg4oModC3SvPUT1gQIQ9NGGkjlOrBu9J6gs/syPRQIDAQAB

Chrome Web Store > Developer Dashboard > Extension > Build > Package > View public key

image

Short analysis

I noticed that output coming from go-crx3 is longer, so I did another quick check, by decoding base64 public keys, showing their info, and calculating extension ID from them.

$ echo 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDR8RyDbBAaZaEsh4VTye63j6QDOGP1YMSCJ+2KyJXH8IHneddHl2mUKD27FrNNUm7N6NnzRSFmVRolvgph4CByu3D7mHdDekNk8cj0ilsfF+GlUllGPMCPzalp+Zitufq81Cg4oModC3SvPUT1gQIQ9NGGkjlOrBu9J6gs/syPRQIDAQAB' | openssl base64 -d >pubkey1.der
$ echo 'MIIBCgKCAQEAj/u/XDdjlDyw7gHEtaaasZ9GdG8WOKAyJzXd8HFrDtz2Jcuy7er7MtWvHgNDA0bwpznbI5YdZeV4UfCEsA4SrA5b3MnWTHwA1bgbiDM+L9rrqvcadcKuOlTeN48Q0ijmhHlNFbTzvT9W0zw/GKv8LgXAHggxtmHQ/Z9PP2QNF5O8rUHHSL4AJ6hNcEKSBVSmbbjeVm4gSXDuED5r0nwxvRtupDxGYp8IZpP5KlExqNu1nbkPc+igCTIB6XsqijagzxewUHCdovmkb2JNtskx/PMIEv+TvWIx2BzqGp71gSh/dV7SJ3rClvWd2xj8dtxG8FfAWDTIIi0qZXWn2QhizQIDAQAB' | openssl base64 -d >pubkey2.der
$ openssl rsa -in pubkey1.der -inform DER -pubin -text
Public-Key: (1024 bit)
Modulus:
    00:d1:f1:1c:83:6c:10:1a:65:a1:2c:87:85:53:c9:
    ee:b7:8f:a4:03:38:63:f5:60:c4:82:27:ed:8a:c8:
    95:c7:f0:81:e7:79:d7:47:97:69:94:28:3d:bb:16:
    b3:4d:52:6e:cd:e8:d9:f3:45:21:66:55:1a:25:be:
    0a:61:e0:20:72:bb:70:fb:98:77:43:7a:43:64:f1:
    c8:f4:8a:5b:1f:17:e1:a5:52:59:46:3c:c0:8f:cd:
    a9:69:f9:98:ad:b9:fa:bc:d4:28:38:a0:ca:1d:0b:
    74:af:3d:44:f5:81:02:10:f4:d1:86:92:39:4e:ac:
    1b:bd:27:a8:2c:fe:cc:8f:45
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDR8RyDbBAaZaEsh4VTye63j6QD
OGP1YMSCJ+2KyJXH8IHneddHl2mUKD27FrNNUm7N6NnzRSFmVRolvgph4CByu3D7
mHdDekNk8cj0ilsfF+GlUllGPMCPzalp+Zitufq81Cg4oModC3SvPUT1gQIQ9NGG
kjlOrBu9J6gs/syPRQIDAQAB
-----END PUBLIC KEY-----
$ openssl rsa -in pubkey2.der -inform DER -pubin -text
Public-Key: (2048 bit)
Modulus:
    00:8f:fb:bf:5c:37:63:94:3c:b0:ee:01:c4:b5:a6:
    9a:b1:9f:46:74:6f:16:38:a0:32:27:35:dd:f0:71:
    6b:0e:dc:f6:25:cb:b2:ed:ea:fb:32:d5:af:1e:03:
    43:03:46:f0:a7:39:db:23:96:1d:65:e5:78:51:f0:
    84:b0:0e:12:ac:0e:5b:dc:c9:d6:4c:7c:00:d5:b8:
    1b:88:33:3e:2f:da:eb:aa:f7:1a:75:c2:ae:3a:54:
    de:37:8f:10:d2:28:e6:84:79:4d:15:b4:f3:bd:3f:
    56:d3:3c:3f:18:ab:fc:2e:05:c0:1e:08:31:b6:61:
    d0:fd:9f:4f:3f:64:0d:17:93:bc:ad:41:c7:48:be:
    00:27:a8:4d:70:42:92:05:54:a6:6d:b8:de:56:6e:
    20:49:70:ee:10:3e:6b:d2:7c:31:bd:1b:6e:a4:3c:
    46:62:9f:08:66:93:f9:2a:51:31:a8:db:b5:9d:b9:
    0f:73:e8:a0:09:32:01:e9:7b:2a:8a:36:a0:cf:17:
    b0:50:70:9d:a2:f9:a4:6f:62:4d:b6:c9:31:fc:f3:
    08:12:ff:93:bd:62:31:d8:1c:ea:1a:9e:f5:81:28:
    7f:75:5e:d2:27:7a:c2:96:f5:9d:db:18:fc:76:dc:
    46:f0:57:c0:58:34:c8:22:2d:2a:65:75:a7:d9:08:
    62:cd
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj/u/XDdjlDyw7gHEtaaa
sZ9GdG8WOKAyJzXd8HFrDtz2Jcuy7er7MtWvHgNDA0bwpznbI5YdZeV4UfCEsA4S
rA5b3MnWTHwA1bgbiDM+L9rrqvcadcKuOlTeN48Q0ijmhHlNFbTzvT9W0zw/GKv8
LgXAHggxtmHQ/Z9PP2QNF5O8rUHHSL4AJ6hNcEKSBVSmbbjeVm4gSXDuED5r0nwx
vRtupDxGYp8IZpP5KlExqNu1nbkPc+igCTIB6XsqijagzxewUHCdovmkb2JNtskx
/PMIEv+TvWIx2BzqGp71gSh/dV7SJ3rClvWd2xj8dtxG8FfAWDTIIi0qZXWn2Qhi
zQIDAQAB
-----END PUBLIC KEY-----
$ cat pubkey1.der | sha256sum | head -c32 | tr 0-9a-f a-p
eigojmmlmgigbldiclbpibmjnlbdpiaa
$ cat pubkey2.der | sha256sum | head -c32 | tr 0-9a-f a-p
ndbbbokdeocpkaiembjedmlfajdkoegn

I haven't analyzed your code, but above results at least show that go-crx3 assumes somewhere RSA >= 2K, which can not always be true for extensions added to webstore long time ago (e.g. my extension was created ~15y ago IIRC), i.e. before longer keys were strictly recommended / enforced.

CRX Viewer also uses RSA 1K, so you can test on it too if you want.


But it looks it's not only matter of key size. I tried another extension, which uses RSA 2K, and for it pubkey also didn't return proper value.


EDIT: You can look at ASN.1 dumps (e.g. using ASN.1 JavaScript decoder as openssl asn1parse is limited) of pubkeys, even from above analysis, to better see some discrepancies (putting key size matter aside):

SubjectPublicKeyInfo SEQUENCE @0+159 (constructed): (2 elem)
  algorithm AlgorithmIdentifier SEQUENCE @3+13 (constructed): (2 elem)
    algorithm OBJECT_IDENTIFIER @5+9: 1.2.840.113549.1.1.1|rsaEncryption|PKCS #1
    parameters ANY NULL @16+0
  subjectPublicKey BIT_STRING @18+141 (encapsulates): (1120 bit)|...
    SEQUENCE @22+137 (constructed): (2 elem)
      INTEGER @25+129: (1024 bit)|...
      INTEGER @157+3: 65537
RSAPrivateKey SEQUENCE @0+266 (constructed): (2 elem)
  version Version INTEGER @4+257: (2048 bit)|...
  modulus INTEGER @265+3: 65537
mmadfox commented 3 weeks ago

Thank you for the detailed feedback! I will take it into account. I admit I skimmed through the specification and apparently misunderstood the task.

mmadfox commented 3 weeks ago

@przemoc If possible, please check the latest release v1.5.1, where I fixed the retrieval of the ID from the public key and corrected the pubkey command. I compared (tested) the public keys and ID generation with Chrome tools and OpenSSL. Once again, thank you for the detailed description of the problem. If the issue is not resolved, please let me know.

przemoc commented 3 weeks ago

@mmadfox Thanks for working on this. I cannot afford right now to do a more thorough check, but I just did two quick checks, firstly on my extension, secondly on another extension. We're not there yet. :)


1.

$ ( crx3 pubkey ~/Downloads/eigojmmlmgigbldiclbpibmjnlbdpiaa.crx; echo ) | openssl base64 -d >pubkey3.der
$ openssl asn1parse -in pubkey3.der -inform DER -i
    0:d=0  hl=4 l= 290 cons: SEQUENCE
    4:d=1  hl=2 l=  13 cons:  SEQUENCE
    6:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
   17:d=2  hl=2 l=   0 prim:   NULL
   19:d=1  hl=4 l= 271 prim:  BIT STRING

So it looks like it follows SubjectPublicKeyInfo format, but subjectPublicKey is still somehow becoming 2K.

Which means that the first problem I brought up in my previous comment remains true:

I haven't analyzed your code, but above results at least show that go-crx3 assumes somewhere RSA >= 2K, which can not always be true for extensions added to webstore long time ago (e.g. my extension was created ~15y ago IIRC), i.e. before longer keys were strictly recommended / enforced.


It seems there is yet another issue. Pubkey seemingly returns same (garbage?) stuff now.

3.

$ ( crx3 pubkey ~/Downloads/beakmhbijpdhipnjhnclmhgjlddhidpe.crx; echo ) | openssl base64 -d >linkding3.der
$ cat linkding3.der | sha256sum | head -c32 | tr 0-9a-f a-p
lfoeajgcchlidpicbabpmckkejpckcfb
$ cat pubkey3.der | sha256sum | head -c32 | tr 0-9a-f a-p
lfoeajgcchlidpicbabpmckkejpckcfb
mmadfox commented 1 week ago

Thank you for the detailed report on the issue. I will fix the error soon. Yes, I missed something in the implementation…