From: AJ ONeal Date: Sun, 14 Nov 2021 01:36:20 +0000 (+0000) Subject: feature: add gpg-pubkey X-Git-Url: https://git.josue.xyz/?p=webi-installers%2F.git;a=commitdiff_plain;h=5b97c474ab8d125c578cf9ac2750158672dfc8cb feature: add gpg-pubkey --- diff --git a/gpg-pubkey/README.md b/gpg-pubkey/README.md new file mode 100644 index 0000000..31eee10 --- /dev/null +++ b/gpg-pubkey/README.md @@ -0,0 +1,239 @@ +--- +title: GnuPG Pub Key +homepage: https://webinstall.dev/gpg-pubkey +tagline: | + Get your GnuPG Public Key. +--- + +## Cheat Sheet + +> Your GnuPG Public Key can be used for signing git commits and email, among +> other things. The file public key ends in `.asc`. + +This installs two commands. + +- `gpg-pubkey` will: + 1. Create a new gpg keypair if you don’t already have one \ + (uses `~/.gitconfig` for name and email) + 2. Copy your new or existing GnuPG Public Key to your `Downloads` folder + 3. Print the location of the copied key, and its contents, to the screen +- `gpg-pubkey-id` will output the id of your public key. + +The easiest way to get your GnuPG Public Key: + +```bash +curl https://webinstall.dev/gpg-pubkey | bash +``` + +This is what the output of `gpg-pubkey` looks like (except much longer): + +```txt +GnuPG Public Key ID: CA025BC42F00BBBE + +~/Downloads/john@example.com.gpg.asc: + +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGGLrUIBEAC+k1rHvi4xbCiN/cnh3Zi4rbKeJdPIWDP0wDhZcYzIN4/ZWVAm +... (several lines omitted for brevity) +nZH7UhxDx6Gu4w1+uef0E/cjz2BuEn/LN9UBGWwI5dLp5p03FeXYzzAwt6sh +=rRiF +-----END PGP PUBLIC KEY BLOCK----- +``` + +Note: Your public key is the _entire_ section starting with and including +`-----BEGIN` all the way to and including `BLOCK-----` + +### Files + +These are the files / directories that are created and/or modified with this +install: + +```txt +~/.config/envman/PATH.env +~/.local/bin/gpg-pubkey +~/.local/bin/gpg-pubkey-id +~/.gnupg/ +~/Downloads/YOU.KEY_ID.gpg.asc +``` + +## How to add your GPG Public Key to GitHub + +1. Go to your GitHub Profile () +2. Go to the SSH and GPG Keys () +3. Add GPG Key () +4. Paste the output of `gpg-pubkey` into the form + +## How to automatically sign your git commits + +Run `gpg-pubkey-id` to get your GnuPG Public Key ID and then update your +`~/.gitconfig` to sign with it by default: + +```bash +#!/bin/bash + +MY_KEY_ID="$( + gpg-pubkey-id +)" + +git config --global user.signingkey "${MY_KEY_ID}" +git config --global commit.gpgsign true +git config --global log.showSignature true +``` + +Or, for Windows users: + +```bash +#!/usr/bin/env pwsh + +$my_key_id = gpg-pubkey-id + +git config --global user.signingkey "$my_key_id" +git config --global commit.gpgsign true +git config --global log.showSignature true +``` + +## How to use `gpg` manually + +- How to get your Public Key ID +- How to export your Public Key +- How to create a Private Key + +### How to get your GnuPG Public Key ID + +All _Secret Keys_ have _Public IDs_ (and corresponding _Public Keys_). + +Here's a command to list your secret key(s) and get the Public ID (of the first +one, if you have many): + +```bash +#!/bin/bash + +MY_KEY_ID="$( + gpg --list-secret-keys --keyid-format LONG | + grep sec | + cut -d'/' -f2 | + cut -d' ' -f1 +)" +echo "$MY_KEY_ID" +``` + +Or, for Windows users: + +```pwsh +#!/usr/bin/env pwsh + +$my_key_id = ( + gpg --list-secret-keys --keyid-format LONG | + Select-String -Pattern '\.*sec.*\/' | + Select-Object Line | + ForEach-Object { + $_.Line.split('/')[1].split(' ')[0] + } +) +echo "$my_key_id" +``` + +Let's break that down, for good measure: + +All secret keys have a Public Key and a Public ID, which can be viewed in _LONG_ +format: + +```bash +gpg --list-secret-keys --keyid-format LONG +``` + +```txt +/Users/me/.gnupg/pubring.kbx +---------------------------- +sec rsa3072/CA025BC42F00BBBE 2021-11-10 [SCEA] + 6F848282295B19123748D36BCA025BC42F00BBBE +uid [ultimate] John Doe (mac.local) +ssb rsa3072/674124162BF19A32 2021-11-10 [SEA] +``` + +The line with the Public Key ID is the one that starts with `sec`: + +```txt +sec rsa3072/CA025BC42F00BBBE 2021-11-10 [SCEA] +``` + +Specifically, it's the part just after the `/` - **CA025BC42F00BBBE**, in this +case. + +Note: It's important that you list the Secret Keys, because listing Public Keys +will show all keys that you trust in your gpg keychain (co-workers, for +example), not just keys that you own. + +### How to export your GnuPG Public Key: + +Here's how to copy your Public Key into your Downloads folder: + +```bash +gpg --armor --export "${MY_KEY_ID}" > ~/Downloads/"${MY_EMAIL}".gpg.asc +``` + +Or, if you just want to print it to your console, run this: + +```bash +gpg --armor --export "${MY_KEY_ID}" +``` + +### How to create an GnuPG Private Key: + +Generally speaking you'll want to use the same name and email for `git` and +`gpg`. + +Here's how you can automate creating a key using the same info as what's in your +`~/.gitconfig`: + +```bash +#!/bin/bash + +MY_NAME="$( git config --global user.name )" +MY_HOST="$( hostname )" +MY_EMAIL="$( git config --global user.email )" + +gpg --batch --generate-key << EOF + %echo Generating RSA 3072 key + Key-Type: RSA + Key-Length: 3072 + Subkey-Type: RSA + Subkey-Length: 3072 + Name-Real: ${MY_NAME} + Name-Comment: ${MY_HOST} + Name-Email: ${MY_EMAIL} + Expire-Date: 0 + %commit +EOF +``` + +Or, for the Windows folk... + +```bash +#!/usr/bin/env pwsh + +$my_name = git config --global user.name +$my_host = hostname +$my_email = git config --global user.email + +echo " + %echo Generating RSA 3072 key + Key-Type: RSA + Key-Length: 3072 + Subkey-Type: RSA + Subkey-Length: 3072 + Name-Real: $my_name + Name-Comment: $my_host + Name-Email: $my_email + Expire-Date: 0 + %commit +" | gpg --batch --generate-key +``` + +Note: if you want to create a key without a passphrase, add +`--pinentry=loopback --passphrase=''` to the arguments. + +(though typically it's better to create a random passphrase and just let macOS +store it in your user Keychain and forget it - just so it doesn't get backed up +unencrypted, etc) diff --git a/gpg-pubkey/gpg-pubkey-id.ps1 b/gpg-pubkey/gpg-pubkey-id.ps1 new file mode 100644 index 0000000..b15d700 --- /dev/null +++ b/gpg-pubkey/gpg-pubkey-id.ps1 @@ -0,0 +1,8 @@ +#!/usr/bin/env pwsh + +gpg --list-secret-keys --keyid-format LONG | + Select-String -Pattern '\.*sec.*\/' | + Select-Object Line | + ForEach-Object { + $_.Line.split('/')[1].split(' ')[0] + } diff --git a/gpg-pubkey/gpg-pubkey-id.sh b/gpg-pubkey/gpg-pubkey-id.sh new file mode 100644 index 0000000..dd4062b --- /dev/null +++ b/gpg-pubkey/gpg-pubkey-id.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e +set -u + +gpg --list-secret-keys --keyid-format LONG | + grep sec | + cut -d'/' -f2 | + cut -d' ' -f1 diff --git a/gpg-pubkey/gpg-pubkey.ps1 b/gpg-pubkey/gpg-pubkey.ps1 new file mode 100644 index 0000000..88a8843 --- /dev/null +++ b/gpg-pubkey/gpg-pubkey.ps1 @@ -0,0 +1,41 @@ +#!/usr/bin/env pwsh + +$my_key_id = gpg --list-secret-keys --keyid-format LONG | + Select-String -Pattern '\.*sec.*\/' | + Select-Object Line | + ForEach-Object { + $_.Line.split('/')[1].split(' ')[0] + } + +if (!$my_key_id) +{ + $my_name = git config --global user.name + $my_email = git config --global user.email + $my_host = hostname + + echo " + %echo Generating RSA 3072 key + Key-Type: RSA + Key-Length: 3072 + Subkey-Type: RSA + Subkey-Length: 3072 + Name-Real: $my_name + Name-Comment: $my_host + Name-Email: $my_email + Expire-Date: 0 + %commit + " | gpg --batch --generate-key +} + +$my_asc_relpath = "Downloads/$my_email.$my_key_id.gpg.asc" +& gpg --armor --export $my_key_id > "$Env:USERPROFILE/$my_asc_relpath" + +# TODO use the comment (if any) for the name of the file +$my_email = git config --global user.email +echo "" +echo "GnuPG Public Key ID: $MY_KEY_ID" +echo "" +echo "~/$my_asc_relpath": +echo "" +& type "$Env:USERPROFILE/$my_asc_relpath" +echo "" diff --git a/gpg-pubkey/gpg-pubkey.sh b/gpg-pubkey/gpg-pubkey.sh new file mode 100755 index 0000000..3145f64 --- /dev/null +++ b/gpg-pubkey/gpg-pubkey.sh @@ -0,0 +1,131 @@ +#!/bin/bash +set -e +set -u + +function __get_git_email() { + grep 'email\s*=.*@' ~/.gitconfig | + tr -d '\t ' | head -n 1 | + cut -d'=' -f2 +} + +function __get_pubkey_id() { + gpg --list-secret-keys --keyid-format LONG | + grep sec | + cut -d'/' -f2 | + cut -d' ' -f1 +} + +function _create_gpg_key() { + if [[ ! -e ~/.gitconfig ]]; then + return 1 + fi + + MY_NAME="$( + grep 'name\s*=' ~/.gitconfig | + head -n 1 | + cut -d'=' -f2 | + sed -e 's/^[\t ]*//' + )" + if [[ -z ${MY_NAME} ]]; then + return 1 + fi + + MY_EMAIL="$( + __get_git_email + )" + if [[ -z ${MY_EMAIL} ]]; then + return 1 + fi + + MY_HOST="$(hostname)" + + # Without passphrase: + #gpg --batch --generate-key --pinentry=loopback --passphrase='' + + # With passphrase via macOS Keychain + gpg_opts=" + %echo Generating RSA 3072 key... + %echo Warning: It may take several minutes to gather enough entropy, + %echo especially on a linux VPS if haveged isn't installed. + %echo (try moving the mouse, downloading large files, etc) + Key-Type: RSA + Key-Length: 3072 + Subkey-Type: RSA + Subkey-Length: 3072 + Name-Real: ${MY_NAME} + Name-Comment: ${MY_HOST} + Name-Email: ${MY_EMAIL} + Expire-Date: 0 + %commit + " + if ! echo "$gpg_opts" | gpg --batch --generate-key 2> /dev/null; then + echo >&2 "" + echo >&2 "" + echo >&2 "" + echo >&2 "== STOP! CHOOSE A PASSPHRASE ==" + echo >&2 "" + echo >&2 "Choose a passphrase for this GPG Key." + echo >&2 "(the passphrase will not be shown as you type)" + echo >&2 "" + echo >&2 -n "Passphrase: " + read -r -s + echo >&2 "" + echo " + %echo Generating RSA 3072 key... + %echo Warning: It may take several minutes to gather enough entropy, + %echo especially on a linux VPS if haveged isn't installed. + %echo (try moving the mouse, downloading large files, etc) + Key-Type: RSA + Key-Length: 3072 + Subkey-Type: RSA + Subkey-Length: 3072 + Name-Real: ${MY_NAME} + Name-Comment: ${MY_HOST} + Name-Email: ${MY_EMAIL} + Passphrase: ${REPLY} + Expire-Date: 0 + %commit + " --batch --generate-key > gpg + fi + echo >&2 "Done" +} + +# (maybe) Create first key +if ! gpg --list-secret-keys | grep -q sec; then + if ! _create_gpg_key; then + echo >&2 "" + echo >&2 "Please set your name and email, and then try again:" + echo >&2 "" + echo >&2 " git config --global user.name 'John Doe'" + echo >&2 " git config --global user.email johndoe@example.com" + echo >&2 " gpg-pubkey" + echo >&2 "" + echo >&2 "(or manually create a private key first)" + echo >&2 "" + exit 1 + fi +fi + +MY_KEY_ID="$( + __get_pubkey_id +)" + +MY_EMAIL="$( + __get_git_email +)" + +#gpg --send-keys "${MY_KEY_ID}" + +MY_ASC_RELPATH="Downloads/${MY_EMAIL}.${MY_KEY_ID}.gpg.asc" +mkdir -p ~/Downloads/ +rm -f ~/"${MY_ASC_RELPATH}" +gpg --armor --export "${MY_KEY_ID}" > ~/"${MY_ASC_RELPATH}" + +echo >&2 "" +echo >&2 "GnuPG Public Key ID: ${MY_KEY_ID}" +echo >&2 "" +#shellcheck disable=SC2088 +echo >&2 "~/${MY_ASC_RELPATH}": +echo >&2 "" +cat ~/"${MY_ASC_RELPATH}" +echo >&2 "" diff --git a/gpg-pubkey/install.ps1 b/gpg-pubkey/install.ps1 new file mode 100644 index 0000000..79aeb14 --- /dev/null +++ b/gpg-pubkey/install.ps1 @@ -0,0 +1,43 @@ +#!/usr/bin/env pwsh + +# +# gpg-pubkey-id +# +$MY_CMD = "gpg-pubkey" +$MY_SUBCMD = "gpg-pubkey-id" + +& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_HOST/packages/$MY_CMD/$MY_SUBCMD.ps1" -o "$Env:USERPROFILE\.local\bin\$MY_SUBCMD.ps1.part" +Remove-Item -Path "$Env:USERPROFILE\.local\bin\$MY_SUBCMD.ps1" -Recurse -ErrorAction Ignore +& move "$Env:USERPROFILE\.local\bin\$MY_SUBCMD.ps1.part" "$Env:USERPROFILE\.local\bin\$MY_SUBCMD.ps1" +Set-Content -Path "$Env:USERPROFILE\.local\bin\$MY_SUBCMD.bat" -Value "@echo off`r`npushd %USERPROFILE%`r`npowershell -ExecutionPolicy Bypass .local\bin\$MY_SUBCMD.ps1 %1`r`npopd" + +# +# gpg-pubkey +# +$MY_CMD = "gpg-pubkey" + +& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_HOST/packages/$MY_CMD/$MY_CMD.ps1" -o "$Env:USERPROFILE\.local\bin\$MY_CMD.ps1.part" +Remove-Item -Path "$Env:USERPROFILE\.local\bin\$MY_CMD.ps1" -Recurse -ErrorAction Ignore +& move "$Env:USERPROFILE\.local\bin\$MY_CMD.ps1.part" "$Env:USERPROFILE\.local\bin\$MY_CMD.ps1" +Set-Content -Path "$Env:USERPROFILE\.local\bin\$MY_CMD.bat" -Value "@echo off`r`npushd %USERPROFILE%`r`npowershell -ExecutionPolicy Bypass .local\bin\$MY_CMD.ps1 %1`r`npopd" + +# +# Check the gpg exists +# + +$gpg_exists = Get-Command gpg 2> $null +if (!$gpg_exists) { + curl.exe "$Env:WEBI_HOST/gpg" | powershell + $gpg_exists = Get-Command gpg 2> $null + if (!$gpg_exists) { + echo "" + echo "(exited because gpg is not existalled)" + echo "" + Exit 1 + } +} + +# +# run gpg-pubkey +# +& "$Env:USERPROFILE\.local\bin\$MY_CMD.bat" diff --git a/gpg-pubkey/install.sh b/gpg-pubkey/install.sh new file mode 100644 index 0000000..fa80ed6 --- /dev/null +++ b/gpg-pubkey/install.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e +set -u + +function __install_gpg_pubkey() { + MY_CMD="gpg-pubkey" + + rm -f "$HOME/.local/bin/$MY_CMD" + webi_download "$WEBI_HOST/packages/$MY_CMD/$MY_CMD.sh" "$HOME/.local/bin/$MY_CMD" + chmod a+x "$HOME/.local/bin/$MY_CMD" +} + +function __install_gpg_pubkey_id() { + MY_CMD="gpg-pubkey" + MY_SUBCMD="gpg-pubkey-id" + + rm -f "$HOME/.local/bin/$MY_SUBCMD" + webi_download "$WEBI_HOST/packages/$MY_CMD/$MY_SUBCMD.sh" "$HOME/.local/bin/$MY_SUBCMD" + chmod a+x "$HOME/.local/bin/$MY_SUBCMD" +} + +function __check_gpg_exists() { + if ! command -v gpg; then + webi gpg + export PATH="$HOME/.local/opt/gnupg/bin:$PATH" + export PATH="$HOME/.local/opt/gnupg/bin/pinentry-mac.app/Contents/MacOS:$PATH" + fi +} + +__install_gpg_pubkey_id +__install_gpg_pubkey +__check_gpg_exists + +# run the command +"$HOME/.local/bin/$MY_CMD"