| 
						
						
						
						 |  | @@ -0,0 +1,224 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | # SPDX-License-Identifier: MIT | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | function ssh_keysuite_gen () { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if [[ "${#}" -eq '0' ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         printf -- '%s\n' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             'Usage:' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             'ssh_keysuite_gen \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    '"'"'ed25519'"'"' \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    '"'"'john.doe@example.com_ed25519_'"'"'"$(date +'%F')" \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    "$(date +'%F')" \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    "$(pwd)" \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    '"'"'John Doe <john.doe@example.com>'"'"'' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             'or for an RSA key (here with 4096 bits key size):' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             'ssh_keysuite_gen \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    '"'"'rsa:4096'"'"' \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    '"'"'john.doe@example.com_rsa2_4096_'"'"'"$(date +'%F')" \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    "$(date +'%F')" \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    "$(pwd)" \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    '"'"'John Doe <john.doe@example.com>'"'"'' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             'Option '"'"'rsa'"'"' without key size '"'"':<number>'"'"' will generate' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             'a key with 3072 bits key size.' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             'For an ECDSA key (here with 521 bits elliptic curve size):' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             'ssh_keysuite_gen \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    '"'"'ecdsa:521'"'"' \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    '"'"'john.doe@example.com_ecdsa_521_'"'"'"$(date +'%F')" \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    "$(date +'%F')" \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    "$(pwd)" \' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '    '"'"'John Doe <john.doe@example.com>'"'"'' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             '' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             'Option '"'"'ecdsa'"'"' without EC length '"'"':<number>'"'"' will generate' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             'a key with 256 bits elliptic curve length.' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fi | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # We're assuming coreutils and bash internals are available (chmod, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # command, cp, fmt, mktemp, printf etc.), we check for moderately | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # unconventional binaries | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_REQUIRED_CMDS=('grep' 'openssl' 'puttygen' 'sed' 'ssh-keygen') | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_MISSING_CMDS=() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     for ssh_required_cmd in "${SSH_REQUIRED_CMDS[@]}"; do | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         command -v "${ssh_required_cmd}" &> '/dev/null' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if [[ "${?}" -gt '0' ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             SSH_MISSING_CMDS+=("${ssh_required_cmd}") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         fi | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     done | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if [[ "${#SSH_MISSING_CMDS[@]}" -gt '0' ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         for ssh_missing_cmd in "${SSH_MISSING_CMDS[@]}"; do | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             printf -- 'Missing binary: '"'"'%s'"'"'\n' "${ssh_missing_cmd}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         done | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         printf -- '\n%s\n' 'Please make sure all required commands are available.' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fi | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     IFS= read -sp 'Enter password for new SSH key: ' 'SSH_KEY_PW' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     echo | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local TMPFILE="$(mktemp)" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local TMPFILE2="$(mktemp)" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     trap '[[ -f '"'${TMPFILE}'"' ]] && rm '"'${TMPFILE}'"'; [[ -f '"'${TMPFILE2}'"' ]] && rm '"'${TMPFILE2}'"';' RETURN | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     printf -- '%s' "${SSH_KEY_PW}" > "${TMPFILE}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     printf -- '%s' "${SSH_KEY_PW}" > "${TMPFILE2}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     sleep 1 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_ALGO="${1:-ed25519}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_BASENAME="${2:?'Arg 2 must be SSH key file base name such as '"'"'john.doe@example.com_ed25519_2025-09-15'"'"''}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_CREATION_TIMESTAMP="${3:-"$(date +'%F')"}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_OUTPUT_DIR="${4:-"$(pwd)"}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_PURPOSE="${5:?'Arg 5 must be SSH key purpose for use in key comment such as '"'"'John Doe <john.doe@example.com>'"'"''}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_PATH_RAW="${SSH_KEY_OUTPUT_DIR}"'/'"${SSH_KEY_BASENAME}"'.SSH_KEY_FORMAT.SSH_KEY_FILE_EXTENSION' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_COMMENT="${SSH_KEY_PURPOSE}"' ('"${SSH_KEY_CREATION_TIMESTAMP}"')' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if [[ "${SSH_KEY_ALGO}" =~ ^rsa ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_DO_RSA='true' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_RSA_KEY_LENGTH="${SSH_KEY_ALGO#*:}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if [[ "${#SSH_RSA_KEY_LENGTH}" -eq '0' || "${SSH_RSA_KEY_LENGTH}" == "${SSH_KEY_ALGO}" ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             SSH_RSA_KEY_LENGTH='' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         fi | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_KEY_ALGO='rsa' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     elif [[ "${SSH_KEY_ALGO}" =~ ^ecdsa ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_DO_ECDSA='true' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_EC_LENGTH="${SSH_KEY_ALGO#*:}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if [[ "${#SSH_EC_LENGTH}" -eq '0' || "${SSH_EC_LENGTH}" == "${SSH_KEY_ALGO}" ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             SSH_EC_LENGTH='' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         fi | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_KEY_ALGO='ecdsa' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fi | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if [[ "${SSH_DO_RSA}" || "${SSH_DO_ECDSA}" ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if [[ "${#SSH_KEY_PW}" -lt '5' ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             printf -- '%s\n' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 '' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 "$(fmt <<<'Key password must me at least 5 characters long as that is what '"'"'ssh-keygen'"'"' enforces for PEM-encoded private keys for example when converting from an OpenSSH-encoded private key.')" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             return | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         fi | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fi | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_FILE_LIST=() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # Gen OpenSSH-encoded private key | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # Can be OpenSSH-encoded private RSA key | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # Can be OpenSSH-encoded private EC key | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # (a wrapper around all keys supported by OpenSSH) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # BEGIN OPENSSH PRIVATE KEY | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_FORMAT='openssh-encoded' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_FILE_EXTENSION='key' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_PATH_OPENSSH="$(sed -r \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         -e 's'$'\x1''SSH_KEY_FORMAT'$'\x1'"${SSH_KEY_FORMAT}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         -e 's'$'\x1''SSH_KEY_FILE_EXTENSION'$'\x1'"${SSH_KEY_FILE_EXTENSION}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         <<<"${SSH_KEY_PATH_RAW}")" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     ssh-keygen -t "${SSH_KEY_ALGO}"$(if [[ "${SSH_DO_RSA}" && "${SSH_RSA_KEY_LENGTH}" ]]; then printf -- '%s' ' -b '"${SSH_RSA_KEY_LENGTH}"; elif [[ "${SSH_DO_ECDSA}" && "${SSH_EC_LENGTH}" ]]; then printf -- '%s' ' -b '"${SSH_EC_LENGTH}"; fi) -N "${SSH_KEY_PW}" -C "${SSH_KEY_COMMENT}" -f "${SSH_KEY_PATH_OPENSSH}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     SSH_KEY_FILE_LIST+=("${SSH_KEY_PATH_OPENSSH}") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     SSH_KEY_FILE_LIST+=("${SSH_KEY_PATH_OPENSSH}"'.pub') | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # Convert to PEM-encoded PKCS#1 key | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # (only RSA keys are PKCS#1) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # BEGIN RSA PRIVATE KEY | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if [[ "${SSH_DO_RSA}" ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_KEY_FORMAT='pem-encoded-pkcs1-rsa' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_KEY_PATH_PEM_PKCS1_RSA_PRIVATE="$(sed -r \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             -e 's'$'\x1''SSH_KEY_FORMAT'$'\x1'"${SSH_KEY_FORMAT}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             -e 's'$'\x1''SSH_KEY_FILE_EXTENSION'$'\x1'"${SSH_KEY_FILE_EXTENSION}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             <<<"${SSH_KEY_PATH_RAW}")" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         cp "${SSH_KEY_PATH_OPENSSH}" "${SSH_KEY_PATH_PEM_PKCS1_RSA_PRIVATE}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ssh-keygen -p -P "${SSH_KEY_PW}" -N "${SSH_KEY_PW}" -m 'pem' -f "${SSH_KEY_PATH_PEM_PKCS1_RSA_PRIVATE}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         SSH_KEY_FILE_LIST+=("${SSH_KEY_PATH_PEM_PKCS1_RSA_PRIVATE}") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fi | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # Convert to PEM-encoded PKCS#8 key | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # (a wrapper around both RSA and EC keys) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # BEGIN PRIVATE KEY | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # or | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # BEGIN ENCRYPTED PRIVATE KEY | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if [[ "${SSH_DO_RSA}" || "${SSH_DO_ECDSA}" ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_KEY_FORMAT='pem-encoded-pkcs8' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_KEY_PATH_PEM_PKCS8="$(sed -r \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             -e 's'$'\x1''SSH_KEY_FORMAT'$'\x1'"${SSH_KEY_FORMAT}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             -e 's'$'\x1''SSH_KEY_FILE_EXTENSION'$'\x1'"${SSH_KEY_FILE_EXTENSION}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             <<<"${SSH_KEY_PATH_RAW}")" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_KEY_FORMAT='pem-encoded-SubjectPublicKeyInfo' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_KEY_PATH_PEM_SPKI_PUBLIC="$(sed -r \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             -e 's'$'\x1''SSH_KEY_FORMAT'$'\x1'"${SSH_KEY_FORMAT}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             -e 's'$'\x1''SSH_KEY_FILE_EXTENSION'$'\x1'"${SSH_KEY_FILE_EXTENSION}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             <<<"${SSH_KEY_PATH_RAW}")" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         cp "${SSH_KEY_PATH_OPENSSH}" "${SSH_KEY_PATH_PEM_PKCS8}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ssh-keygen -p -P "${SSH_KEY_PW}" -N "${SSH_KEY_PW}" -m 'pkcs8' -f "${SSH_KEY_PATH_PEM_PKCS8}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ssh-keygen -e -P "${SSH_KEY_PW}" -f "${SSH_KEY_PATH_PEM_PKCS8}" -m 'pkcs8' > "${SSH_KEY_PATH_PEM_SPKI_PUBLIC}"'.pub' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         SSH_KEY_FILE_LIST+=("${SSH_KEY_PATH_PEM_PKCS8}") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         SSH_KEY_FILE_LIST+=("${SSH_KEY_PATH_PEM_SPKI_PUBLIC}"'.pub') | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fi | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # Convert to PEM-encoded Elliptic Curve key | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # (looks like PKCS#1 but is not) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # BEGIN EC PRIVATE KEY | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if [[ "${SSH_DO_ECDSA}" ]]; then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_KEY_FORMAT='pem-encoded-ec' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         local SSH_KEY_PATH_PEM_EC_PRIVATE="$(sed -r \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             -e 's'$'\x1''SSH_KEY_FORMAT'$'\x1'"${SSH_KEY_FORMAT}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             -e 's'$'\x1''SSH_KEY_FILE_EXTENSION'$'\x1'"${SSH_KEY_FILE_EXTENSION}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             <<<"${SSH_KEY_PATH_RAW}")" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         openssl ec -in "${SSH_KEY_PATH_PEM_PKCS8}" -out "${SSH_KEY_PATH_PEM_EC_PRIVATE}" -passin 'file:'"${TMPFILE}" -passout 'file:'"${TMPFILE2}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         SSH_KEY_FILE_LIST+=("${SSH_KEY_PATH_PEM_EC_PRIVATE}") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fi | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # Convert pub key to RFC4716 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_FORMAT='rfc4716-encoded' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_FILE_EXTENSION='key' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_PATH_RFC4716="$(sed -r \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         -e 's'$'\x1''SSH_KEY_FORMAT'$'\x1'"${SSH_KEY_FORMAT}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         -e 's'$'\x1''SSH_KEY_FILE_EXTENSION'$'\x1''key'$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         <<<"${SSH_KEY_PATH_RAW}")" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # Write a proper comment line. ssh-keygen by default writes key type | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # and local user account as comment when converting to RFC4716 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # format instead of using the comment already present in source | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # file. We write our own proper comment here. Break at 71 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # characters. End each line with a trailing backslash at position | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # 72. The first sed comment replaces all end-of-lines ($) with a | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # backslash (\). We have to escape the backslash so that the first | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # sed command inserts a literal backslash at the end of each line (\\). A | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # few lines further down we 'ssh-keygen | sed' again where we | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # replace the RFC4716 comment with ours (which now includes literal | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # trailing backslashes). In order to preserve literal trailing | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # backslashes in "${var}" when doing: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #     sed -r 's/g/'"${var}"'/g' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # we have to make sure that "${var}" contains three (3) literal | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # backslashes. That's why we do '\\\\\\' here. When we then do: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #     sed -r 's/g/'"${var}"'/g' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # three literal backslashes in "${var}" are interpreted to one. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_RFC4716_KEYTYPE="$(ssh-keygen -m 'RFC4716' -ef "${SSH_KEY_PATH_OPENSSH}"'.pub' | grep -Pio -- '^(Comment:[^,]+)')" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_RFC4716_COMMENT="$(fmt --width 71 <<<"${SSH_RFC4716_KEYTYPE}"', '"${SSH_KEY_COMMENT}"'"' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         | sed -r \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         -e 's'$'\x1''$'$'\x1''\\\\\\'$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         -e '$ s'$'\x1''\\+'$'\x1'''$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         )" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     ssh-keygen -m 'RFC4716' -ef "${SSH_KEY_PATH_OPENSSH}"'.pub' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         | sed -r 's'$'\x1''^Comment: [^\r\n\f]*'$'\x1'"${SSH_RFC4716_COMMENT}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         > "${SSH_KEY_PATH_RFC4716}"'.pub' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     SSH_KEY_FILE_LIST+=("${SSH_KEY_PATH_RFC4716}"'.pub') | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     # Convert to PuTTY PPK | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_FORMAT='putty-encoded' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_FILE_EXTENSION='ppk' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local SSH_KEY_PATH_PUTTY="$(sed -r \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         -e 's'$'\x1''SSH_KEY_FORMAT'$'\x1'"${SSH_KEY_FORMAT}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         -e 's'$'\x1''SSH_KEY_FILE_EXTENSION'$'\x1'"${SSH_KEY_FILE_EXTENSION}"$'\x1''g' \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         <<<"${SSH_KEY_PATH_RAW}")" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     puttygen "${SSH_KEY_PATH_OPENSSH}" --old-passphrase "${TMPFILE}" -o "${SSH_KEY_PATH_PUTTY}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     SSH_KEY_FILE_LIST+=("${SSH_KEY_PATH_PUTTY}") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     for file in "${SSH_KEY_FILE_LIST[@]}"; do | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         chmod --verbose '0600' "${file}" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     done | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } |