如何检查 SSH 公钥末尾何时需要 = 或 ==?

如何检查 SSH 公钥末尾何时需要 = 或 ==?

是否可以通过 ksh/bash 自动化,以便通过 schellscript 检查所有用户 ~/.ssh/authorized_keys 文件是否有错误的 = 或 == 结尾?

我的一位朋友删除了 SSH 密钥末尾的 = 和 ==,因此用户被锁定,因为这是他们密钥的一部分:)

它的模式是这样的(可能是 ssh-rsa 并具有不同的密钥长度):

from="1.2.3.4" ssh-dss AAAAB....0bOJKs= COMMENTHERE COMMENTHERE

对此:

from="1.2.3.4" ssh-dss AAAAB....0bOJKs COMMENTHERE COMMENTHERE

示例解决方案:密钥有固定长度吗?如何过滤掉坏钥匙?

答案1

=标记只是填充,用于填写 Base64 转换。您可以阅读更多相关内容

您可以自动修复/检查此问题,因为 base64 值中的字符总数(忽略那些外部编码(例如空格)将是 4 的倍数。

答案2

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

对于每一行(-n)将-a字段自动拆分( )为@F沿空格,然后找到包含键类型的字段,接下来就是键。用 4 减去长度模 4,得到我们需要添加的符号数量=,除非在字段已经是正确长度的情况下再取模将 4 转换为 0。

手册上说

协议 2 公钥由:选项、密钥类型、base64 编码密钥、注释组成。 options 字段是可选的;它的存在取决于该行是否以数字开头

但这不太正确,因为 v2 键类型也不以数字开头。选项字段包含空格,因此键类型的位置可以是任何位置。我们实际上应该解析选项以查找任何带引号的字符串,但应该试探性地查找已知的键类型。

答案3

cut -d: -f6 /etc/passwd | 
  while read oneuserraw; do
    if [ -s "${oneuserraw}/.ssh/authorized_keys" ]; then
      echo "${oneuserraw}/.ssh/authorized_keys"
    fi
  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)
      fi
      if [[ "$oneline" == ssh* ]]; then
        key=$(echo "$oneline" | cut -d' ' -f2)
      fi
      length=$(echo "$key" | awk '{ print length }')
      if ! (( $length % 4 == 0 )); then
        echo "$oneline"
      fi
    done
  done

我自己也写了一个检查器。

这甚至会抛出有人在 ex.: ssh key 中间按 Enter 键并且不能被 4 整除的错误行。

在 AIX/Linux 上测试了 ksh 和 bash。

相关内容