Last active
May 15, 2024 08:20
-
-
Save ChristopherA/33f095b3e7ba5763bbb745e7233e01fe to your computer and use it in GitHub Desktop.
Script to self-sign an SSH public key and verify the signature
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/zsh | |
# ./self-signed-ssh.sh <path_to_ssh_public_key> | |
# Script to sign an SSH public key and verify the signature | |
# Check if the script is called with the necessary public key path argument | |
# Parameters: | |
# $1 - Path to the SSH public key. | |
function check_arguments { | |
if [[ -z "$1" ]]; then | |
echo "Usage: $0 <path_to_ssh_public_key>" | |
exit 1 | |
fi | |
} | |
# Verify that the specified file exists | |
# Parameters: | |
# $1 - Path to the file to check. | |
function verify_file_exists { | |
if [[ ! -f "$1" ]]; then | |
echo "Public key file does not exist." | |
exit 1 | |
fi | |
} | |
# Read and parse the SSH public key from the first line of the file | |
# Parameters: | |
# $1 - Path to the SSH public key file. | |
# Output: | |
# Returns the key type and key data (space-separated). | |
function read_public_key { | |
read -r line < "$1" | |
echo $line | awk '{print $1, $2}' | |
} | |
# Calculate and display the fingerprint of the public key | |
# Parameters: | |
# $1 - Path to the SSH public key file. | |
# Output: | |
# Prints the fingerprint of the SSH key. | |
function calculate_fingerprint { | |
ssh-keygen -l -E sha256 -f "$1" | awk '{print substr($2, 8)}' | |
} | |
# Sign the public key using the corresponding private key and return the flattened signature | |
# Parameters: | |
# $1 - Public key data (key type and key). | |
# $2 - Path to the private key corresponding to the public key. | |
# Output: | |
# Returns the flattened SSH signature (single line, no formatting). | |
function prepare_signature { | |
local ssh_pub_key="$1" | |
local ssh_private_key_path="$2" | |
echo "$ssh_pub_key" > temp_pub_key | |
ssh-keygen -Y sign -n file -f "$ssh_private_key_path" -I key_identity < temp_pub_key > temp_signature | |
cat temp_signature | grep -v '^-.*' | tr -d '\n' | |
} | |
# Format the SSH signature with appropriate headers and footers | |
# Parameters: | |
# $1 - The flattened SSH signature string. | |
# Output: | |
# Returns the formatted SSH signature. | |
function format_signature { | |
local flattened_signature="$1" | |
local header="-----BEGIN SSH SIGNATURE-----" | |
local footer="-----END SSH SIGNATURE-----" | |
echo "$header\n$(echo "$flattened_signature" | fold -w 70)\n$footer" | |
} | |
# Verify the signed public key | |
# Parameters: | |
# $1 - Email or identifier for the signer. | |
# $2 - Type of the SSH key (e.g., ssh-rsa). | |
# $3 - SSH public key data. | |
# Output: | |
# Prints the result of the verification process. | |
function verify_signature { | |
local key_id="$1" | |
local key_type="$2" | |
local key_data="$3" | |
local key_comment="Local Signing Key of User" | |
echo "$key_id $key_type $key_data $key_comment" > temp_allowed_signers | |
ssh-keygen -v -Y verify -n file -f temp_allowed_signers -I "$key_id" -s temp_signature < temp_pub_key | |
} | |
# Clean up all temporary files created during the script execution | |
function cleanup { | |
rm temp_pub_key temp_signature temp_allowed_signers | |
} | |
# Main function encapsulating the script's primary execution flow | |
# Parameters: | |
# $1 - Command line argument representing the path to the SSH public key file. | |
function main { | |
local SSH_PUB_KEY_PATH="$1" | |
check_arguments "$SSH_PUB_KEY_PATH" | |
verify_file_exists "$SSH_PUB_KEY_PATH" | |
local SSH_PUB_KEY=$(read_public_key "$SSH_PUB_KEY_PATH") | |
echo "What is being signed:\n$SSH_PUB_KEY\n" | |
local SSH_PUB_KEY_FINGERPRINT=$(calculate_fingerprint "$SSH_PUB_KEY_PATH") | |
echo "The fingerprint of the key signing it:\n$SSH_PUB_KEY_FINGERPRINT\n" | |
local SSH_PRIVATE_KEY_PATH="${SSH_PUB_KEY_PATH%.*}" | |
local SSH_SIGNATURE=$(prepare_signature "$SSH_PUB_KEY" "$SSH_PRIVATE_KEY_PATH") | |
# local SSH_SIGNATURE_FULL=$(format_signature "$SSH_SIGNATURE") | |
# echo "The restored SSH_SIGNATURE_FULL:\n\n$SSH_SIGNATURE_FULL\n" | |
local RESULT=$(verify_signature "example@example.com" "$(echo $SSH_PUB_KEY | awk '{print $1}')" "$(echo $SSH_PUB_KEY | awk '{print $2}')") | |
echo "\nVerification Result:\n$RESULT\n" | |
cleanup | |
} | |
# Start the script by calling the main function with command line arguments | |
main "$@" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment