In the development life cycle, there are a number of points where it is useful to have a published public key. Examples include build signing, Git commit signing, and communicating with other community members securely. Build signing in particular is a required part of the release process for the Celo blockchain client.
In support of these uses, OpenPGP public keys can be published to celo.org, where they can downloaded securely by anyone.
If you want to read more about OpenPGP keys, including their structure and metadata, check out Anatomy of a GPG Key by Dave Steele.
Note: This guide assumes you have an @clabs.co email address, but if you do not, simply change the email domain to your primary developer email (e.g. @example.com for [email protected])
GnuPG, or gpg
, is by far the most popular implementation of OpenPGP, and it is what we will be using here.
Install gpg
on MacOS with Homebrew using brew install gpg
or visit gnupg.org/download for other options.
In this guide, a couple of environment variables are used in the commands. Set the following for convenience:
export USER_NAME='your name on the clabs.co email domain. e.g. alice for [email protected]'
export REAL_NAME='your first and last name. e.g. Alice Turing'
OpenPGP supports a number of cryptographic algorithms including RSA and ECC.
Here we recommend secp256k1
, which is the algorithm underlying identity on the Celo blockchain, because it is fast, secure, and promotes interoperability within the Celo ecosystem. (e.g. Your OpenPGP key could be used to take actions on-chain, which is pretty neat.)
In OpenPGP, each key is associated with a user identity, which is commonly an email address and your name (e.g. "Alice Turing [email protected]"). A public key created by gpg
will automatically include the username, in addition to the cryptographic public key information, so when someone downloads your public key, they will know it is intended for your email address.
By publishing keys on celo.org, users can securely download any published key associated with an @celo.org
user identifier, and know that it is the correct one because publishing to celo.org requires approval of the Celo core developers.
We recommend generating your developer key pair with a YubiKey. Generating your key on a YubiKey provides higher security by making it virtually impossible for an attacker to steal your private key by hacking your computer.
Warning: Losing your YubiKey will result in the permanent loss of any keys stored on it. It is not possible to create a backup of a private key created with this method.
Note: When asked for the admin PIN, it is 12345678 by default. If asked for the user PIN, it is 123456 by default.
- Insert the YubiKey into the USB port.
- Run
gpg --card-edit --expert
- At the
gpg/card>
prompt, enter the following commands:admin
key-attr
2
to selectECC
on the signature key.9
to selectsecp256k1
on the signature key.- Repeat this selection for the encryption and authentication keys.
generate
- When asked if you want to backup your encryption key, specify
n
for no. - Specify an expiration date, for example
2y
for 2 years. - Enter you full name and
@clabs.co
email address when prompted. - You may add a comment, but it is not required.
- When asked if you want to backup your encryption key, specify
quit
See the official YubiKey documentation for more information.
Use the following command, replacing the environment variables, to generate a new key on your machine:
gpg --quick-generate-key "${REAL_NAME} <${USER_NAME}@clabs.co>" secp256k1
You now have a secret key and public key, on secp256k1
and with a 2 year expiration, associated with your @clabs.co
email address.
See man gpg
for more information on key generation options.
If you've generated a key on your local machine, it can be imported onto your YubiKey with the following steps.
Note: When asked for the admin PIN, it is 12345678 by default. If asked for the user PIN, it is 123456 by default.
- Insert the YubiKey into the USB port.
gpg --edit-key ${USER_NAME}@clabs.co
- At the
gpg
prompt enter the following commands: 2.keytocard
and select1
to set the signature key on the YubiKey. 7.keytocard
and select3
to set the authentication key on the YubiKey. 8.quit
and save your changes.
See the official YubiKey documentation
Use the following command as a quick way to verify that your new key can be used to produce a valid signature:
gpg -u ${USER_NAME}@clabs.co -o - --sign <(head -c 256 /dev/urandom) | gpg --verify -
Note: The command above works by signing 256 bytes of random data with your new key, then verifying the signature over that data.
You should see Good signature from ...
with your real name and email.
Keys are published to celo.org using OpenPGP WKD, which is essentially just a hosted folder of public keys. Published keys are managed by submitting a pull request to the master
branch of celo-monorepo
on GitHub.
The domain (e.g. celo.org
) of the user identifier much match the site it's hosted on, so you'll need to run the following command to add the celo.org
domain to your key:
gpg --quick-add-uid ${USER_NAME}@clabs.co "${REAL_NAME} <${USER_NAME}@celo.org>"
Note: You do not need an
@celo.org
email address to publish a key with the@celo.org
domain, but it must not conflict with an existing email or published key.
Additionally you may want to add identities for staging.celo.org
and dev.celo.org
so you can confirm your keys are published correctly on a non-production version of the website.
gpg --quick-add-uid ${USER_NAME}@clabs.co "${REAL_NAME} <${USER_NAME}@staging.celo.org>"
gpg --quick-add-uid ${USER_NAME}@clabs.co "${REAL_NAME} <${USER_NAME}@dev.celo.org>"
Adding your key to the @celo/web
package of celo-monorepo
will allow them to be available on celo.org with the next website deployment.
Running the following command from the root of celo-monorepo
will add your key to the packages/web/openpgpkey
directory:
gpg --list-options show-only-fpr-mbox -k ${USER_NAME}@clabs.co | $(gpgconf --list-dirs libexecdir)/gpg-wks-client -v --install-key -C packages/web/openpgpkey
You should confirm that new key files were added to the packages/web/openpgpkey/
directory and open a pull request with the changes. You should see new files in the packages/web/openpgpkey/${DOMAIN}/hu
folders for each of the domains you added to you key, including clabs.co
, celo.org
, staging.celo.org
and dev.celo.org
if you followed the directions above.
Once a new version of celo.org is published, you will be able to verify your keys are published correctly with the key lookup instructions below.
If you have access to the cLabs Google Cloud project, verifying your keys are correctly added to the repository can be accomplished by pushing your changes to dev.celo.org
.
After making sure you are not going to clobber another engineer's changes, run the following commands in the packages/web
directory of celo-monorepo
.
yarn deploy:dev
gpg --auto-key-locate wkd --locate-external-keys ${USER_NAME}@dev.celo.org
If correctly configured you will see the message "not changed" on the first line of the output and the downloaded key will match the key you just generated.
Users can lookup keys on the @celo.org
domain with the following command:
gpg --auto-key-locate wkd --locate-external-keys ${USER_NAME}@celo.org
This command will query celo.org over HTTPS and retrieve the latest key for ${USER_NAME}@celo.org
.
A signature can be produced over a document with a number of options using gpg
.
Use the following command to produce an ASCII encoded detached signature with your @clabs.co
key:
gpg -u ${USER_NAME}@clabs.co -o doc.txt.asc --armor --detach-sign doc.txt
This command will produce the signature file doc.txt.asc
for doc.txt
. The signature file can be distributed along side the document, and be verified by any user with access to the document and your public key.
A signature file produced with the method above can be verified by any user that possesses your public key with the following command.
gpg --verify doc.txt.asc doc.txt
See the gpg
manual entry on signatures for more information.