Skip to content

Instantly share code, notes, and snippets.

@ChristopherA
Last active May 15, 2024 08:20
Show Gist options
  • Save ChristopherA/33f095b3e7ba5763bbb745e7233e01fe to your computer and use it in GitHub Desktop.
Save ChristopherA/33f095b3e7ba5763bbb745e7233e01fe to your computer and use it in GitHub Desktop.
Script to self-sign an SSH public key and verify the signature
#!/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