Could it be automated via ksh/bash, so via a schellscript to check all users ~/.ssh/authorized_keys file for bad = or == ending?

One of my friend deleted the = and the == from the end of the SSH keys, so users got locked out, because that was the part of their key :)

pattern it went from this (it could be ssh-rsa and with different key length):


to this:


example solution: is there a fix length for the keys? how to filter out the bad keys?

  • 6
    I would say string must be multiple of 4, either one or two =
    – Archemar
    Commented Sep 16, 2016 at 9:22
  • 1
    What is your question? If you can automate fixing them? Sure you can.
    – Num Lock
    Commented Sep 16, 2016 at 11:26
  • 2
    @NumLock, that's like the mathematicians answer from the joke: completely accurate, and totally useless...
    – ilkkachu
    Commented Sep 16, 2016 at 11:47
  • 1
    @ilkkachu Well, to all other questions OP was asking he already stated in the comments (of the top voted answer) that he already knows everything about it. So yeah, I don't get what the question is. If he wants to know how to automate this, I would have expected some initial effort. That's common for StackExchange btw.
    – Num Lock
    Commented Sep 19, 2016 at 7:27

3 Answers 3


The = mark is just padding, to fill out a base64 conversion. You can read more about that in

You could automate a fix/check for this because the total number of characters in a base64 value (disregarding those outside the encoding such as whitespace) would be a multiple of 4.

  • 1
    that wasn't my question. I know about it, but my friend just learnt that :)
    – Peter84753
    Commented Sep 16, 2016 at 9:19
  • 12
    @Peter84753 Actually that was exactly your question. "is there a fix length for the keys?". Regarding that other question "how to filter out the bad keys?" and since you apparently know about the sizing: What have been your efforts towards solving that? Your question doesn't show any efforts.
    – Num Lock
    Commented Sep 16, 2016 at 11:24
  • 2
    @Peter84753 By the way, the answer to "Could it be automated via ksh/bash, so via a schellscript to check all users ~/.ssh/authorized_keys file for bad = or == ending?" is yes.
    – Num Lock
    Commented Sep 16, 2016 at 11:25

A quick fix in Perl:

perl -lane '$a = -1; for(0..$#F) {$a = $_ + 1 if $F[$_] =~ /^ssh-|^ecdsa-/; };
    die if $a == -1;  $p = (4 - length($F[$a]) % 4) % 4; 
    $F[$a] .= "=" x $p;  print join " ", @F' < authorized_keys > authorized_keys2

For each line (-n) Autosplit (-a) the fields to @F along spaces, then find the field that contains the key type, the next is the key. Subtract from 4 the length modulo 4 to get the number of = signs we need to add, except take another modulo to turn a 4 to a 0 in case the field is already the correct length.

The manual says that

Protocol 2 public key consist of: options, keytype, base64-encoded key, comment. The options field is optional; its presence is determined by whether the line starts with a number or not

but that's not quite right since v2 key types don't start with numbers either. The options field an contain spaces so the position of the key type can be anything. We should actually parse the options to find any quoted strings, but heuristically looking for the known key types should do.

  • 1
    If you used (4 - length($F[$a]) % 4) % 4 it would not add unnecessary 4 equal signs in the first place :-)
    – Bergi
    Commented Sep 16, 2016 at 11:24
  • @Bergi, actually I did that first, then decided the alternative may be simpler to understand. (maybe it's just me)
    – ilkkachu
    Commented Sep 16, 2016 at 11:51
  • It isn't. Either way you have to compute a length modulo 4.
    – user207421
    Commented Sep 17, 2016 at 0:17
cut -d: -f6 /etc/passwd | 
  while read oneuserraw; do
    if [ -s "${oneuserraw}/.ssh/authorized_keys" ]; then
      echo "${oneuserraw}/.ssh/authorized_keys"
  done |
  perl -pe 's/\/\//\//g' |
  while read oneuser; do
    echo checking: "$oneuser"
    cat "$oneuser" | while read oneline; do
      if [[ "$oneline" == from* ]]; then
        key=$(echo "$oneline" | cut -d' ' -f3)
      if [[ "$oneline" == ssh* ]]; then
        key=$(echo "$oneline" | cut -d' ' -f2)
      length=$(echo "$key" | awk '{ print length }')
      if ! (( $length % 4 == 0 )); then
        echo "$oneline"

I wrote a checker myself too.

This even throws out the bad lines where someone hit enter at the ex.: middle of the ssh key AND not divisible with 4.

tested on AIX/Linux so ksh and bash.

  • 5
    Just a point on presentation: with a script of that length, you may want to split to several lines, as SE doesn't split lines on code blocks (luckily). It's a bit hard to read a single line of 300 characters.
    – ilkkachu
    Commented Sep 16, 2016 at 11:49
  • 1
    There's a lot about this code that's very unnecessarily inefficient. ${#key} gives the length of that key, for instance. read _ key _ <<<"$oneline" reads the second whitespace-separated item from oneline into the variable named key without needing a subprocess and a tool like cut. You could use the same tool to not need cut to read the password file: while IFS=: read name password uid gid class change expire gecos home_dir shell _; do ...; done </etc/passwd, for instance, reads each field from /etc/passwd into a different shell variable using only builtins. Commented Sep 16, 2016 at 16:25
  • Also, consider using a case statement rather than multiple if statements -- that gives you equivalent behavior to your if [[ $oneline = from* ]] without depending on non-POSIX behavior. Commented Sep 16, 2016 at 16:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .