| 1 | #!/usr/bin/env bash |
| 2 | # Desc: Gets gpg fingerprint but replaces uid email addresses with hashes |
| 3 | # Usage: bk-gpgfp-noemail 0xdc3469c9 74810B012346C9A6 |
| 4 | # Depends: gpg, b2sum |
| 5 | # Version: 0.0.3 |
| 6 | |
| 7 | yell() { echo "$0: $*" >&2; } # print script path and all args to stderr |
| 8 | die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status |
| 9 | try() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails |
| 10 | check_resembles_gpg_fingerprint() { |
| 11 | # Desc: Checks if input string looks like gpg fingerprint |
| 12 | # Usage: check_resembles_gpg_fingerprint arg1 |
| 13 | # Input: arg1: string |
| 14 | # Output: exit code: 0 if arg1 is fingerprint, 1 otherwise |
| 15 | # Depends: yell(), die(), try() |
| 16 | # Version: 0.0.1 |
| 17 | local pattern1 pattern2 input input_length |
| 18 | |
| 19 | # Check args |
| 20 | if [[ $# -ne 1 ]]; then |
| 21 | die "ERROR:Invalid number of arguments:$#"; |
| 22 | else |
| 23 | input="$1"; |
| 24 | fi; |
| 25 | |
| 26 | ## Trim leading `0x` |
| 27 | pattern1="(0x)(.*)"; |
| 28 | if [[ $input =~ $pattern1 ]]; then |
| 29 | input="${input:2}"; |
| 30 | #yell "DEBUG:input:$input"; |
| 31 | fi; |
| 32 | |
| 33 | ## Check if char count multiple of 8 |
| 34 | input_length="${#input}"; |
| 35 | if [[ ! $(( input_length % 8 )) -eq 0 ]]; then |
| 36 | yell "DEBUG:Length not a multiple of 8:$input_length:$input"; |
| 37 | return 1; |
| 38 | fi; |
| 39 | |
| 40 | ## Check if hexadecimal |
| 41 | pattern2="[0-9A-Fa-f]{8,40}"; |
| 42 | if [[ $1 =~ $pattern2 ]]; then |
| 43 | #yell "DEBUG:is a fingerprint:$arg"; |
| 44 | return 0; |
| 45 | else |
| 46 | #yell "DEBUG:Not a fingerprint:$arg"; |
| 47 | return 1; |
| 48 | fi; |
| 49 | }; # Checks if input string looks like gpg fingerprint |
| 50 | main() { |
| 51 | # Desc: main program |
| 52 | # Depends: gpg, b2sum |
| 53 | # Ref/Attrib: [1] Manipulating Strings. https://tldp.org/LDP/abs/html/string-manipulation.html |
| 54 | declare -a fingerprints |
| 55 | local gpg_text gpg_text_buffer pattern email |
| 56 | |
| 57 | # Check arguments |
| 58 | n=0; |
| 59 | for arg in "$@"; do |
| 60 | ((n++)); |
| 61 | #yell "DEBUG:n:$n"; |
| 62 | #yell "DEBUG:arg:$arg"; |
| 63 | |
| 64 | # Check if arg resembles gpg fignerprint |
| 65 | if check_resembles_gpg_fingerprint "$arg"; then |
| 66 | #yell "DEBUG:Resembles a gpg fingerprint:$arg"; |
| 67 | fingerprints+=("$arg"); |
| 68 | #yell "DEBUG:fingerprints:$(declare -p fingerprints)"; |
| 69 | else |
| 70 | die "ERROR:Doesn't resemble a gpg fingerprint:$arg"; |
| 71 | fi; |
| 72 | done; |
| 73 | |
| 74 | # Process fingerprints |
| 75 | for arg in "${fingerprints[@]}"; do |
| 76 | # Get gpg fingerprint text |
| 77 | gpg_text="$(gpg --fingerprint --fingerprint "$arg" 2>&1)"; |
| 78 | #yell "DEBUG:gpg_text:$gpg_text"; |
| 79 | |
| 80 | # Trim emails |
| 81 | gpg_text_buffer=""; |
| 82 | while IFS= read -r line; do |
| 83 | #yell "DEBUG:line:$line"; |
| 84 | ## Read $gpg_text line-by-line |
| 85 | |
| 86 | # Skip lines that don't start with 'uid' |
| 87 | pattern="^uid"; |
| 88 | if [[ ! $line =~ $pattern ]]; then |
| 89 | #yell "DEBUG:line doesn't start with \"uid\":$line"; |
| 90 | gpg_text_buffer="$(printf "%s\n%s" "$gpg_text_buffer" "$line")"; |
| 91 | continue; |
| 92 | fi; |
| 93 | |
| 94 | # Trim email from $line |
| 95 | ## Get email |
| 96 | email="$(expr match "$line" '.*\(<.*$\)')"; |
| 97 | #yell "DEBUG:email1:$email"; |
| 98 | email="${email%>*}"; |
| 99 | #yell "DEBUG:email2:$email"; |
| 100 | email="${email#*<}"; |
| 101 | #yell "DEBUG:email3:$email"; |
| 102 | |
| 103 | ## Strip email from $line |
| 104 | line="${line% <*}"; # See [1] |
| 105 | #yell "DEBUG:line1:$line"; |
| 106 | |
| 107 | ## Add hashed email if $email length non-zero |
| 108 | if [[ -n $email ]]; then |
| 109 | email_hash="$(echo -n "$email" | b2sum -l32 | cut -d' ' -f1)"; # hash email using b2sum |
| 110 | #yell "DEBUG:email_hash:$email_hash"; |
| 111 | line="$line <$email_hash>"; |
| 112 | #yell "DEBUG:line3:$line"; |
| 113 | fi; |
| 114 | |
| 115 | ## Append $line to $gpg_text_buffer |
| 116 | gpg_text_buffer="$(printf "%s\n%s" "$gpg_text_buffer" "$line")"; |
| 117 | done < <(echo "$gpg_text"); |
| 118 | echo "$gpg_text_buffer"; |
| 119 | done; |
| 120 | }; # main program |
| 121 | |
| 122 | main "$@"; |
| 123 | |
| 124 | # Author: Steven Baltakatei Sandoval |
| 125 | # License: GPLv3+ |
| 126 | |
| 127 | # Dependencies |
| 128 | |
| 129 | #1 |
| 130 | # b2sum (GNU coreutils) 8.32 |
| 131 | # Copyright (C) 2020 Free Software Foundation, Inc. |
| 132 | # License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. |
| 133 | # This is free software: you are free to change and redistribute it. |
| 134 | # There is NO WARRANTY, to the extent permitted by law. |
| 135 | |
| 136 | # Written by Padraig Brady and Samuel Neves. |
| 137 | |
| 138 | #2 |
| 139 | # gpg (GnuPG) 2.2.20 |
| 140 | # libgcrypt 1.8.8 |
| 141 | # Copyright (C) 2020 Free Software Foundation, Inc. |
| 142 | # License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html> |
| 143 | # This is free software: you are free to change and redistribute it. |
| 144 | # There is NO WARRANTY, to the extent permitted by law. |
| 145 | |
| 146 | # Home: /home/baltakatei/.gnupg |
| 147 | # Supported algorithms: |
| 148 | # Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA |
| 149 | # Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH, |
| 150 | # CAMELLIA128, CAMELLIA192, CAMELLIA256 |
| 151 | # Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224 |
| 152 | # Compression: Uncompressed, ZIP, ZLIB, BZIP2 |
| 153 | |
| 154 | #3 |
| 155 | # GNU bash, version 5.1.8(1)-release (x86_64-pc-linux-gnu) |
| 156 | # Copyright (C) 2020 Free Software Foundation, Inc. |
| 157 | # License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> |
| 158 | |
| 159 | # This is free software; you are free to change and redistribute it. |
| 160 | # There is NO WARRANTY, to the extent permitted by law. |