Skip to content

Instantly share code, notes, and snippets.

@grenade
Last active November 9, 2024 20:40
Show Gist options
  • Save grenade/6318301 to your computer and use it in GitHub Desktop.
Save grenade/6318301 to your computer and use it in GitHub Desktop.
generate ed25519 ssh and gpg/pgp keys and set file permissions for ssh keys and config
#!/bin/bash
# generate new personal ed25519 ssh keys
ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/id_ed25519 -C "rob thijssen <[email protected]>"
ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/id_robtn -C "rob thijssen <[email protected]>"
# generate new host cert authority (host_ca) ed25519 ssh key
# used for signing host keys and creating host certs
ssh-keygen -t ed25519 -f manta_host_ca -C manta.network
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# set local file permissions
chmod 700 ~/.ssh
chmod 644 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/known_hosts
chmod 644 ~/.ssh/config
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 600 ~/.ssh/id_robtn
chmod 644 ~/.ssh/id_robtn.pub
# add key(s) to git/github
git config --global core.sshCommand "ssh -i ~/.ssh/id_robtn -F /dev/null"
# sudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
# sudo dnf install gh
gh ssh-key add ~/.ssh/id_ed25519.pub
gh ssh-key add ~/.ssh/id_robtn.pub
#!/bin/bash
# usage
# $ curl -sL https://gist.github.com/grenade/6318301/raw/02-backup-gpg-key.sh?$(uuidgen) | bash
backup_dir=${HOME}/key-backup
# backup old gpg key
key_name="Rob Thijssen (https://grenade.github.io) <[email protected]>"
key_fingerprint=$(if [[ $(gpg --list-keys "${key_name}") =~ ([A-F0-9]{40}) ]]; then echo ${BASH_REMATCH[1]}; fi)
if [ -n "${key_fingerprint}" ]; then
timestamp=$(date -u --iso-8601)
mkdir -p ${backup_dir}/${timestamp}/${key_fingerprint}
gpg --export --armor ${key_fingerprint} > ${backup_dir}/${timestamp}/${key_fingerprint}/public.asc
gpg --export-secret-keys --armor ${key_fingerprint} > ${backup_dir}/${timestamp}/${key_fingerprint}/private.asc
gpg --export-secret-subkeys --armor ${key_fingerprint} > ${backup_dir}/${timestamp}/${key_fingerprint}/subkeys.private.asc
gpg --export-ownertrust > ${backup_dir}/${timestamp}/${key_fingerprint}/ownertrust.txt
tar -C ~/ -zcvf ${backup_dir}/${timestamp}/${key_fingerprint}/.gnupg.tar.gz .gnupg
fi
#!/bin/bash
# references:
# - https://blog.josefsson.org/tag/ed25519/
# - https://www.gnupg.org/documentation/manuals/gnupg/OpenPGP-Key-Management.html
# use a new and unique key name.
# it will be necessary to have both old and new keys while transitioning.
# eg: for password-store re-encryption.
old_key_name="Rob Thijssen (https://grenade.github.io) <[email protected]>"
new_key_name="rob thijssen <[email protected]>"
# generate ed25519 master key with no expiration
gpg --quick-generate-key "${new_key_name}" ed25519 sign 0
old_key_fingerprint=$(if [[ $(gpg --list-keys "${old_key_name}") =~ ([A-F0-9]{40}) ]]; then echo ${BASH_REMATCH[1]}; fi)
new_key_fingerprint=$(if [[ $(gpg --list-keys "${new_key_name}") =~ ([A-F0-9]{40}) ]]; then echo ${BASH_REMATCH[1]}; fi)
if [ -n "${new_key_fingerprint}" ]; then
# generate elyptic curve encryption sub-key with no expiration
gpg --quick-add-key ${new_key_fingerprint} cv25519 encr 0
# generate ed25519 authentication sub-key with no expiration
gpg --quick-add-key ${new_key_fingerprint} ed25519 auth 0
# generate ed25519 signing sub-key with no expiration
gpg --quick-add-key ${new_key_fingerprint} ed25519 sign 0
# sign the new key with the old key
gpg --default-key ${old_key_fingerprint} --sign-key ${new_key_fingerprint}
# optionally sign the old key with the new key
# gpg --default-key ${new_key_fingerprint} --sign-key ${old_key_fingerprint}
# wip. don't use this.
# touch transition-statement.md
# gpg --digest-algo SHA512 --default-key ${new_key_fingerprint} --clearsign transition-statement.md
# tell git about signing key
# https://docs.github.com/en/github/authenticating-to-github/telling-git-about-your-signing-key
new_signing_key_id=$(if [[ $(gpg --list-secret-keys --keyid-format LONG ${new_key_fingerprint}) =~ ed25519/([A-F0-9]{16})[[:space:]]202[1-9]-[01][0-9]-[0-3][0-9][[:space:]]\[S\] ]]; then echo ${BASH_REMATCH[1]}; fi)
git config --global user.signingkey ${new_signing_key_id}
fi

update ~/.gitconfig

[user]
  ...
  signingkey = <signing key from `gpg --list-secret-keys --keyid-format LONG` goes here)
  ...

update password-store (re-encrypt everything)

cd ~/.password-store
pass init $new_key_fingerprint $old_key_fingerprint
ssh-keygen -t rsa -b 4096 -N '' -C "[email protected]" -f ~/.ssh/id_rsa
ssh-keygen -t rsa -b 4096 -N '' -C "[email protected]" -f ~/.ssh/github_rsa
ssh-keygen -t rsa -b 4096 -N '' -C "[email protected]" -f ~/.ssh/mozilla_rsa
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
ssh-add ~/.ssh/github_rsa
ssh-add ~/.ssh/mozilla_rsa
chmod 700 ~/.ssh
chmod 644 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/known_hosts
chmod 644 ~/.ssh/config
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/github_rsa
chmod 644 ~/.ssh/github_rsa.pub
chmod 600 ~/.ssh/mozilla_rsa
chmod 644 ~/.ssh/mozilla_rsa.pub
@apotek
Copy link

apotek commented May 2, 2019

Something that has always mystified me...

If ~/.ssh is set to 700 (only file owner can "read,write,execute(open)" the directory, then it seems setting 644 (owner can read/write, group and world can read) is pointless since the world and the group can't even get into the directory where the file is stored. Yet, 700 on the .ssh directory and 644 on authorized_keys is a common recommendation. It just doesn't make sense to me.

So... I was about to follow suit here, and then remembered that there is always man ssh, and the man file says this:

~/.ssh/
        This directory is the default location for all user-specific con-
        figuration and authentication information.  There is no general
        requirement to keep the entire contents of this directory secret,
        but the recommended permissions are read/write/execute for the
        user, and not accessible by others.


 ~/.ssh/authorized_keys
        Lists the public keys (DSA, ECDSA, Ed25519, RSA) that can be used
        for logging in as this user.  The format of this file is
        described in the sshd(8) manual page.  This file is not highly
        sensitive, but the recommended permissions are read/write for the
        user, and not accessible by others.


~/.ssh/id_dsa
 ~/.ssh/id_ecdsa
 ~/.ssh/id_ed25519
 ~/.ssh/id_rsa
        Contains the private key for authentication.  These files contain
        sensitive data and should be readable by the user but not acces-
        sible by others (read/write/execute).  ssh will simply ignore a
        private key file if it is accessible by others.  It is possible
        to specify a passphrase when generating the key which will be
        used to encrypt the sensitive part of this file using AES-128.

~/.ssh/id_dsa.pub
~/.ssh/id_ecdsa.pub
~/.ssh/id_ed25519.pub
~/.ssh/id_rsa.pub
        Contains the public key for authentication.  These files are not
        sensitive and can (but need not) be readable by anyone.

Based on this excerpt, it is required that the .ssh directory be 700 and the private key files be 600, but it is easier to remember, and will be fully functional, to be utterly restrictive and use 700 on the .ssh directory and 600 on ALL the files.

Thus:

 $ chmod 700 .ssh
 $ cd .ssh
 $ chmod 600 *

Should be all you need.

@cseder
Copy link

cseder commented Jun 18, 2019

Thus:

 $ chmod 700 .ssh
 $ cd .ssh
 $ chmod 600 *

Should be all you need.

Well, while this is probably a valid configuration for your user, you'll soon run into problems if your public-key files are not readable by applications and processes that possibly / often run in a different user context e.g. as a different "user" internally in the OS and needs to access your public keys for things like signing and / or verifying files using ssh.

The original gist has the most common and flexible enough permission setup, and is the way most systems, programmers and software expect the permissions to be set.

@shubhamwagh
Copy link

This certainly helped @grenade. Thanks!

@Soren-365
Copy link

thanks. saved me before the holiday ;-)

@abarke
Copy link

abarke commented Oct 25, 2019

Got the gist of it 👍

@lirundong
Copy link

Bravo, nice gist!

@likueimo
Copy link

likueimo commented Nov 6, 2019

I think maybe add this
chmod 700 /home/$USER

I met a lot of users, type command like this
chmod -R 777 /home/$USER

@eriktdesign
Copy link

Thanks, this helped!

@wittrup
Copy link

wittrup commented Dec 2, 2019

Surely you must have meant? 😉

chmod 700 ~/.ssh
chmod 600 ~/.ssh/*
chmod 644 -f ~/.ssh/*.pub ~/.ssh/authorized_keys ~/.ssh/known_hosts

@alexw24
Copy link

alexw24 commented Jan 3, 2020

thanks

@hcch0912
Copy link

hcch0912 commented Feb 4, 2020

Thank you ,this helps me!

@mhshakouri
Copy link

A great time saver on every new env setup I have

@Howaids
Copy link

Howaids commented Apr 5, 2020

OMG after a weekend trying to work this out, you're a lifesaver @grenade!! I was holding my breath but hey, flawless code. Cheers!

@louwers
Copy link

louwers commented Apr 23, 2020

Don't forget the home directory!

@ZerooCool
Copy link

ZerooCool commented May 5, 2020

755 for the home directory /home/USER ? Y or N ?

For .SSH Folder :

cd ~/
sudo chmod -R 700 .ssh/
sudo chown -R user:user .ssh/

For .SSH Files

cd ~/.ssh/
sudo find . -type f -exec chmod 644 {} ;
sudo chmod -R 600 *.priv
sudo chmod -R 600 *.config

@ajorpheus
Copy link

chmod 644 ~/.ssh/config seems to be incorrect according to http://linuxcommand.org/lc3_man_pages/ssh1.html which says:

Because of the potential for abuse,
this file must have strict
permissions: read/write for the
user, and not accessible by others.

That should be chmod 600 ~/.ssh/config instead

@JRRS1982
Copy link

JRRS1982 commented Jul 9, 2020

Thanks!

@arthurpasquali
Copy link

Thanks a lot

@infinito84
Copy link

Thanks :)

@likueimo
Copy link

likueimo commented Aug 6, 2020

consider to add this

chmod g-w,o-w /home/$USER
or 
chmod g-w,o-w ~/

@Nicacioneto
Copy link

This is a great trick, always going back here to remember and to fix ssh permissions;

@gayan99x
Copy link

gayan99x commented Nov 2, 2020

Thank you ✌️

@TeijiW
Copy link

TeijiW commented Nov 15, 2020

Thank you so much for this gist man, amazing.

@KlausEverWalkingDev
Copy link

Thanks for those simple but important commands. It saved me from craziness :)

@cassie-nahar
Copy link

@ajorpheus

chmod 644 ~/.ssh/config seems to be incorrect according to http://linuxcommand.org/lc3_man_pages/ssh1.html which says:

Because of the potential for abuse,
this file must have strict
permissions: read/write for the
user, and not accessible by others.

That should be chmod 600 ~/.ssh/config instead

Beware that the man pages will vary from one version to another. For example, the man page on Ubuntu Bionic says:

 ~/.ssh/config
        This is the per-user configuration file.  The file format and configuration options
        are described in ssh_config(5).  Because of the potential for abuse, this file must
        have strict permissions: read/write for the user, and not writable by others.  It may
        be group-writable provided that the group in question contains only the user.

Which would mean either chmod 644 ~/.ssh/config or chmod 664 ~/.ssh/config if the file group contains only your user.

Overall, safer is better and you should lock the files down as much as possible for your environment.

@tornikesharia
Copy link

Works like a charm. Thanks dude!

@duynguyen-icw
Copy link

duynguyen-icw commented Mar 25, 2021

You saved my day, thanks a lot! xD

@fabiofrasson
Copy link

Thank you very much for sharing this information :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment