Obtaining Chrome Extension ID for development
Asked Answered
T

5

75

Although similar to this SO question, I am not asking:

Under what conditions does an extension's ID change?

nor

How can I upload my zip archive to the Chrome Dashboard?

I am however asking, how I can obtain an extension's key without using the Chrome Dashboard. Therefore, I do not consider it a duplicate of this SO question.

The documentation for using Google Identity inside a Chrome extension states the need to copy an extensions's key to its manifest file.

To keep your application ID constant, you need to copy the key in the installed manifest.json to your source manifest.

However, when navigating to the recommended directory (...Google/Chrome/Default/Extensions) I do not see the ID of my unpacked extension. I realise this is because the extension was not installed as .crx file. However, the documentation is clearly written for the purposes of development:

Copy key in the installed manifest.json to your source manifest, so that your application ID will stay constant during development.

How can I avoid packaging my extension and reinstalling each time I make a change? If my development extension has no installed manifest file from which I can obtain the extension's key, where can I get it from?

Tannic answered 26/5, 2014 at 15:42 Comment(3)
NOTE: both answers are obsolete since Chrome 70+ because they do not allow to load packaged extensions from local disk. Only install from chrome store. Although there is still a button to create extensions in the Extenstions tab - it will throw errors related to CRX3 file format.Gypsophila
The process of generating a key and the non-existent documentation on it is just terrible :/Eachern
Why do you not want to use the Chrome Dashboard? You can just upload your extension there without publishing it. Then you can download the crx, install from the crx and get the key from the generated manifest.json file in the Data folder.Realgar
B
107

The easy way

The easiest way to get an extension ID is to generate the .pem file and extract the extension ID using the steps described in my other answer (read the part below the image).

The command-line way

The rest of this answer is for those who want to generate the extension ID with command-line tools only. I'm going to use OpenSSL because it is cross-platform.

First, we generate a private key. Keep this private key secret and do not lose it. Otherwise you will not be able to create a CRX file with the same extension ID. As of writing, the private keys generated by Chrome are 2048-bit RSA keys in PKCS #8 format (1024-bit until 2013). Throughout the answer, I will refer to this private key file as key.pem, because the Chrome Web Store expects that the private key is called key.pem.

Second, I show how to generate the value for the "key" field of the manifest file. This is just the public key, encoded in base64 format.

The third command in my answer shows how to calculate the extension ID given a public key (derived from a private key).

Linux / Mac

OpenSSL is installed on most Linux distros. If not, just install openssl via your favorite package manager.

# Create private key called key.pem
2>/dev/null openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt -out key.pem

# Generate string to be used as "key" in manifest.json (outputs to stdout)
2>/dev/null openssl rsa -in key.pem -pubout -outform DER | openssl base64 -A

# Calculate extension ID (outputs to stdout)
2>/dev/null openssl rsa -in key.pem -pubout -outform DER |  shasum -a 256 | head -c32 | tr 0-9a-f a-p

I've put 2>/dev/null at the start of each line to prevent "writing RSA key" from being output to the console.

Windows

If you don't have OpenSSL, you can get a precompiled binary from this mirror.

@echo off
:: Assuming that you have installed OpenSSL in this directory
SET PATH=%PATH%;C:\OpenSSL-Win32\bin

:: Create private key called key.pem
2>NUL openssl genrsa -out priv.tmp 2048
2>NUL openssl pkcs8 -topk8 -in priv.tmp -nocrypt -out key.pem
del priv.tmp

:: Generate string to be used as "key" in manifest.json
2>NUL openssl rsa -in key.pem -pubout -outform DER -out pub.tmp
2>NUL openssl base64 -A -in pub.tmp
del pub.tmp

:: Calculate extension ID
2>NUL openssl rsa -in key.pem -pubout -outform DER -out pub.tmp
2>NUL openssl dgst -sha256 -out checksum.tmp pub.tmp
SET /p EXTID=<checksum.tmp
SET EXTID=%EXTID:* =%
SET EXTID=%EXTID:~0,32%
SET EXTID=%EXTID:f=p%
SET EXTID=%EXTID:e=o%
SET EXTID=%EXTID:d=n%
SET EXTID=%EXTID:c=m%
SET EXTID=%EXTID:b=l%
SET EXTID=%EXTID:a=k%
SET EXTID=%EXTID:9=j%
SET EXTID=%EXTID:8=i%
SET EXTID=%EXTID:7=h%
SET EXTID=%EXTID:6=g%
SET EXTID=%EXTID:5=f%
SET EXTID=%EXTID:4=e%
SET EXTID=%EXTID:3=d%
SET EXTID=%EXTID:2=c%
SET EXTID=%EXTID:1=b%
SET EXTID=%EXTID:0=a%
echo %EXTID%
del checksum.tmp pub.tmp

@echo on

I've put 2>NUL at the start of each line with the openssl command to hide a harmless warning about a missing config file.

Examples

Here is an example of running the previous commands on Linux. The relevant output of the commands are boldfaced. The first command creates a file, so there is no visible output in the shell. Note that the output of the second and third command do not end with a line break, so there is a "$" at the end of the line (which should not be copied).

$ # Create private key called key.pem
$ 2>/dev/null openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt -out key.pem
$ # Generate string to be used as "key" in manifest.json (outputs to stdout)
$ 2>/dev/null openssl rsa -in key.pem -pubout -outform DER | openssl base64 -A
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8vj7SK0NZ6ak7K6m6KEAkfGaNfKUahqFFms6W8rq+voaW7nETrpsMqNyhmBQ+ea0KkyI/S5XIrDQPqDcNpvesYlg9lsmi7CQBZjJw7zNqKkvn0oYaP4SNtWZfZopBumqFbzFi5cst2PT+XU9CBitxXNtocRtcjOsa44W1gPA5xanmtlF258N6Nann+rSOAdhIWqSo/J6fj72cxTNfmqLkwAvhdS4Zyux4F87vxp4YTSwElfYXFsHZWi7h66uuuMzqyOyJz5grhCJ24rtTshMQUCxQWyhO2XT2J1tVfUN1YVw6xdKUz3aGyKZeXCuql5klHmlqE9PTlbKj/1VMiIgCQIDAQAB$ 
$ # Calculate extension ID (outputs to stdout)
$ 2>/dev/null openssl rsa -in key.pem -pubout -outform DER | sha256sum | head -c32 | tr 0-9a-f a-p
mfabfdnimhipcapcioneheloaehhoggk$ 
$ cat key.pem   # Show content of key.pem for completeness of this demo
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDy+PtIrQ1npqTs
rqbooQCR8Zo18pRqGoUWazpbyur6+hpbucROumwyo3KGYFD55rQqTIj9LlcisNA+
oNw2m96xiWD2WyaLsJAFmMnDvM2oqS+fShho/hI21Zl9mikG6aoVvMWLlyy3Y9P5
dT0IGK3Fc22hxG1yM6xrjhbWA8DnFqea2UXbnw3o1qef6tI4B2EhapKj8np+PvZz
FM1+aouTAC+F1LhnK7HgXzu/GnhhNLASV9hcWwdlaLuHrq664zOrI7InPmCuEInb
iu1OyExBQLFBbKE7ZdPYnW1V9Q3VhXDrF0pTPdobIpl5cK6qXmSUeaWoT09OVsqP
/VUyIiAJAgMBAAECggEAIztFPKmTOwdn/MXqf+rwqTjuUopFSQllaPXNdYf8AL6J
Wema9IuFquYWcjO/Ki1wzH1ik8vHaMlYuOwcYnLBnN69x5s6AKFukNEx2IclDyLR
O/jDh13oCDl600KqVk1Fk3dW8cHPAxyfnRmJ6wWhFPOC3yUbdabWhpYI66mJrDhN
ZpN04RmH7DIlhlBpvq/OMVodhRtqb4/EVJYghTxUsrsv/I+3t3zl/o/c0DiOjiVZ
pEBYzn0rrHP8BAEhJWagGNgvotHPaVKAjoYcUiOUtMM4P1Js034XKjP4MHE1pMbN
VlVnQMz3/6CXFL+wU1QqfohdChmcnc4QwM+vCFK47QKBgQD/FjHxhCJco0rNqNua
B0inGx2Jfb4b+FWwLyNobaYey11o0MjpkpAvYcfe3zW8DQtmepDxGL8CpORoWtFg
sVnmhAir0I6bxdZLMwKcp4T+kHW3n/ae3z8tPvMvclCnARGEp+ccyDH9X2iyaSd5
8DeJ6ND32+yr+vLgyyK/JW1z5wKBgQDz167cLe+xoRUqlKdJq8lzmij30lGVUT2D
5Fn+2YUKIMeVEM7PlEmu9UmpN5HMA+LSNeiMZ1uhW5YQovXlXZCWoRqieeI4LMoM
M335hsAWpS8pFRdlXMy885w5FUC5v4Ji0RUI37WON6fxNd8zFVqAMOcAANg716RI
MWfblCJOjwKBgQDV8BKBIbYEBfv10poja9p2NFqodqpcIQIU2uQScGvzxdIY14q5
wu9kndiYxpH1nuch0sf/PSbuG8do8kpKk1P37mKrXyZL5TgeJ7EYG7OCITxpfiLE
Ci6dTv98mp6kAlRj8sH1tL2gaEWR5Hl0XpDl/DpOtsefUcAj4prIv6Y1nwKBgGUk
obNSmonjdxQidQFp8DWzTCr/Yje9ava6UVoUf8qjriV2w1H3AFlCBTvbgO5O7laj
ZcJXXPqhMq3T6ospNEBGsvWR+PO0IFrPQQGvkx3Rhq5TwVCaHZKCudozppVlin/S
mhcENBq5mz/CSMK3qMJjhm3J6+dmmw4W8C10VIahAoGARf4zus0TQIxRlix1Oaaz
sM5yANLcLivoeJDVOlUFUWgeSUc6Yma8T/FYlAkEVyyK+/nCWNErTS2yOzXEff01
n8F0h1DJ4K5zxt0OhGUIUAGgR/kqpub0omqTJcJndLv2qgzofwK21Uih6yQzDeus
lJsf3m3tuax5kcmhnDojbtE=
-----END PRIVATE KEY-----
Bewhiskered answered 26/5, 2014 at 21:30 Comment(12)
For anyone else on OSX who got sha256sum: command not found when doing Step 3 the SSL instructions, this comment fixed it up for me: https://mcmap.net/q/270610/-rvm-quot-sha256sum-nor-shasum-found-quotVibrations
Also for those on OSX who got that sha256sum: command not found error, you can replace it with shasum -a 256 on mac. With the complete command line being: 2>/dev/null openssl rsa -in key.pem -pubout -outform DER | shasum -a 256 | head -c32 | tr 0-9a-f a-p Nanceynanchang
sha256sum can also be replaced by openssl itself: | openssl dgst -sha256 -r (-r = "output in coreutils format" -- not sure how far back that goes)Allain
i got a redundant % character on Generate string to be used as "key" stepRetinitis
Hi, I have followed your instructions and ended up with two different IDs. To be clear, I get one ID (odl...) on the command line and another one when I set the key value in manifest.json and load the unpacked extension (mko...).Stipitate
@KarelFrajták Which of the two instructions? Which version of OpenSSL? Did you double-check that you are loading the correct extension directory containing manifest.json)?Bewhiskered
I know this is old, but what if you already have an extension id, can you get the key.pem in a reverse process?Monmouth
@Monmouth No, you cannot get a key.pem for a given extension ID, unless you know that the original key.pem was very short. That would indicate a short RSA key, and it is then feasible to calculate the desired key.pem by brute force. Most likely the RSA key used for signing Chrome extensions have at least 2k bits, so reversing from extension ID to key.pem is not possible in practice.Bewhiskered
what do we do with the public/private keys after we obtain them?Annunciator
I wrote a snippet based off of this answer that bruteforces an extension keypair with a desired prefix (only [a-p] can be used): gist.github.com/flotwig/37121c884d2f19712935eb1bc9a55efeDogfight
If someone else runs into the same issue as @KarelFrajták, the problem is probably that the "key" value you set in your manifest must be the full public key, in base64, not the truncated all-lower-case version you see in the chrome extension UI (known as the "ID").Defensible
Thanks for the explanation! Here is one-liner for key: key=`(openssl genrsa 1024 | openssl pkcs8 -topk8 -nocrypt | openssl rsa -pubout -outform DER | base64 -w0) 2>/dev/null`and for id: id=`echo "$key" | base64 -d | sha256sum | head -c32 | tr 0-9a-f a-p`Troxler
H
14

The easiest way I found to do this is by packaging the chrome extension in development mode.

To package an extension:

Bring up the Extensions management page by going to this URL: chrome://extensions

Ensure that the "Developer mode" checkbox in the top right-hand corner is checked. Click the Pack extension button. A dialog appears.

In the Extension root directory field, specify the path to the extension's folder—for example, ~/mytodosextension. (Ignore the other field; you don't specify a private key file the first time you package a particular extension.)

Click Package. The packager creates two files:

  • a .crx file, which is the actual extension that can be installed,

  • and a .pem file, which contains the private key.

See chrome documentation here

Haiti answered 28/6, 2017 at 10:13 Comment(9)
what do we do with the public/private keys after we obtain them?Annunciator
@AlexanderMills You can set a key field in manifest.json with the private key. It would ensure that the same chrome extension id is always generated.Haiti
Will this generate common extension id for all who will install from web store?Dennard
Nice and easy way. Install the generated crx file and go to the corresponding extension directory. Open the manifest.json file and copy the key entry. Paste it into the packaged app's manifest. Then uninstall the crx extension again as you don't need it anymore. Now your unpackaged app will use the generated ID from the crx file across all your installations. Remember to remove the key from the manifest before upload to the Chrome app store.Ascocarp
Obsolete since Chrome 70+ or even earlier.Gypsophila
@celwell what doesn't work anymore? This all worked fine for me... generating the crx, getting a private key, installing the crx and getting the public key from the installed crx.Jael
@Ascocarp What do you mean by "Paste it into the packages app's manifest"? What should be the key? Is it "key"?Chisolm
@Chisolm Yes, the key is called "key". Copy that line including the long key value and insert it the in the original app's manifestAscocarp
These instructions are not even half of the story. Still it's very confusing how to get this working.Christan
H
10

Unpacked Chrome extensions ID is generated based on the path of it's directory. For unpacked extension you can generate the id in following way (code in Python):

import hashlib

m = hashlib.sha256()
m.update(bytes(PATH.encode('utf-8')))
EXTID = ''.join([chr(int(i, base=16) + ord('a')) for i in m.hexdigest()][:32])

where PATH is normalized path to the extension, ie.:

PATH = os.path.dirname(os.path.realpath(__file__))
Hula answered 26/4, 2020 at 22:6 Comment(0)
O
1

Bit of an update from yakxxx's answer. For some reason, Chrome has changed the path that the extension ID is generated from.

I don't know whether this affect other OS's other than MacOS but if you have an issue, check to see what address Chrome uses when you open the extension settings panel. They seem to have appended a /private/ to the original path. This is where the hash value is generated from.

New path for extensions

We have extension testing as part of our CI, so this little update broke our system.

Occlude answered 12/4, 2023 at 11:28 Comment(0)
T
1

If you already published the extension you can grab the public key from the developer dashboard

go to Build > package and click on the View public key button

developer dashboard

  1. Copy the code in between -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY-----

  2. Remove the newlines in order to make it a single line of text.

  3. Add the code to the manifest.json under the "key" field. This way the extension will use the same ID.

// manifest.json 

{ 
  "manifest_version": 3,
  "key": "ThisKeyIsGoingToBeVeryLong/go8GGC2u3UD9WI3MkmBgyiDPP2OreImEQhPvwpliioUMJmERZK3zPAx72z8MDvGp7Fx7ZlzuZpL4yyp4zXBI+MUhFGoqEh32oYnm4qkS4JpjWva5Ktn4YpAWxd4pSCVs8I4MZms20+yx5OlnlmWQEwQiiIwPPwG1e1jRw0Ak5duPpE3uysVGZXkGhC5FyOFM+oVXwc1kMqrrKnQiMJ3lgh59LjkX4z1cDNX3MomyUMJ+I+DaWC2VdHggB74BNANSd+zkPQeNKg3o7FetlDJya1bk8ofdNBARxHFMBtMXu/ONfCT3Q2kCY9gZDRktmNRiHG/1cXhkIcN1RWrbsCkwIDAQAB",
}
Tit answered 16/12, 2023 at 14:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.