feature: add gpg-pubkey
authorAJ ONeal <aj@therootcompany.com>
Sun, 14 Nov 2021 01:36:20 +0000 (01:36 +0000)
committerAJ ONeal <aj@therootcompany.com>
Sun, 14 Nov 2021 08:18:32 +0000 (08:18 +0000)
gpg-pubkey/README.md [new file with mode: 0644]
gpg-pubkey/gpg-pubkey-id.ps1 [new file with mode: 0644]
gpg-pubkey/gpg-pubkey-id.sh [new file with mode: 0644]
gpg-pubkey/gpg-pubkey.ps1 [new file with mode: 0644]
gpg-pubkey/gpg-pubkey.sh [new file with mode: 0755]
gpg-pubkey/install.ps1 [new file with mode: 0644]
gpg-pubkey/install.sh [new file with mode: 0644]

diff --git a/gpg-pubkey/README.md b/gpg-pubkey/README.md
new file mode 100644 (file)
index 0000000..31eee10
--- /dev/null
@@ -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 (<https://github.com/settings/profile>)
+2. Go to the SSH and GPG Keys (<https://github.com/settings/keys>)
+3. Add GPG Key (<https://github.com/settings/gpg/new>)
+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) <john@example.com>
+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 (file)
index 0000000..b15d700
--- /dev/null
@@ -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 (file)
index 0000000..dd4062b
--- /dev/null
@@ -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 (file)
index 0000000..88a8843
--- /dev/null
@@ -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 (executable)
index 0000000..3145f64
--- /dev/null
@@ -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 (file)
index 0000000..79aeb14
--- /dev/null
@@ -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 (file)
index 0000000..fa80ed6
--- /dev/null
@@ -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"