#openpgp #public-key #ssh #ssh-key #primary-key #pgp #command-line-tool

bin+lib sshd-openpgp-auth

用于创建和管理基于 OpenPGP 的 SSH 主机密钥信任锚点的命令行工具

4 个版本 (2 个破坏性)

0.3.0 2024 年 2 月 29 日
0.2.1 2024 年 2 月 10 日
0.2.0 2024 年 2 月 10 日
0.1.0 2024 年 1 月 19 日

#3 in #primary-key

Download history 14/week @ 2024-07-01

每月下载量 101 次

Apache-2.0 OR MITLGPL-2.0-or-later

66KB
1K SLoC

sshd-openpgp-auth

此工具提供服务器端功能,以创建和管理作为 SSH 主机密钥信任锚点的 OpenPGP 证书。

更具体地说,sshd-openpgp-auth 透明地管理 OpenPGP 证书的生命周期以及 SSH 主机密钥作为其认证子密钥的有效性。它功能丰富的命令行界面允许导入来自 SSH 公钥文件的宿主密钥以及 known_hosts 文件格式 的字符串,延长主密钥的有效期,撤销任何子密钥,并将密钥部署到 Web Key Directory (WKD)

作为补充客户端工具,ssh-openpgp-auth 用于验证由 sshd-openpgp-auth 创建的信任锚点和 OpenPGP 子密钥。

安装

要安装此工具,请使用 cargo

cargo install sshd-openpgp-auth

依赖项

此工具可以从系统上的现有 SSH 主机密钥添加子密钥。为此,只需访问 SSH 公钥即可。

在导入远程机器的公共 SSH 主机密钥(以 known_hosts 文件格式)时,可以直接使用 ssh-keyscan 的输出(通常是 OpenSSH 安装的一部分)。

使用 sshd-openpgp-auth

此工具不需要配置文件,并依赖于默认设置,这些设置可以在命令行和专用环境变量中覆盖。

默认情况下,SSH公钥在/etc/ssh/中查找,OpenPGP证书存储在/var/lib/sshd-openpgp-auth/中。因此,在默认的OpenPGP证书位置使用该工具时,应作为单独的系统用户运行!此存储库为sysusers.dtmpfiles.d提供了contrib目录中的集成,以支持此场景。

然而,通过使用--openpgp-dir--fingerprint选项来定义存储OpenPGP证书的目录和通过OpenPGP指纹识别特定的OpenPGP证书,完全可能管理其他主机的信任锚,并使用自己的用户进行此操作。

以下小节提供了对sshd-openpgp-auth提供的各种命令的广泛概述。对于更详细的概述,请参阅命令的--help输出。

初始化信任锚

要为主机的SSH设置开始提供基于OpenPGP的认证,需要创建一个OpenPGP证书,该证书作为信任锚。

为了演示目的,假设我们正在使用自定义的临时存储位置来存储我们的OpenPGP证书,不使用系统的SSH主机密钥(生成主机密钥需要ssh-keygen,通常为OpenSSH的一部分)并且想要在名为example.com的主机上工作。

export SSH_DIR="$(mktemp -d)"
export SOA_SSH_DIR="$SSH_DIR/etc/ssh/"
export LOCAL_SSH_DIR="$SOA_SSH_DIR"
export SOA_OPENPGP_DIR="$(mktemp -d)"
export LOCAL_OPENPGP_DIR="$SOA_OPENPGP_DIR"

mkdir -vp "$SOA_SSH_DIR"
ssh-keygen -A -f "$SSH_DIR"
sleep 2
sshd-openpgp-auth init "example.com"
sshd-openpgp-auth list

sq inspect --certifications "$SOA_OPENPGP_DIR/"*.tsk

添加SSH主机密钥

系统上的SSH主机密钥可以通过两种方式添加到OpenPGP证书中:本地和远程。

本地主机密钥

要添加本地SSH主机密钥,请使用add子命令。

sshd-openpgp-auth add
sshd-openpgp-auth list

sq inspect --certifications "$SOA_OPENPGP_DIR/"*.tsk

unset SOA_SSH_DIR

远程主机密钥

假设我们正在codeberg.org,并希望使用sshd-openpgp-auth将服务的主机SSH公钥添加到另一个主机上的信任锚中。此示例需要ssh-keyscan

export PREV_SOA_OPENPGP_DIR="$SOA_OPENPGP_DIR"
export SOA_OPENPGP_DIR="$(mktemp -d)"

sshd-openpgp-auth init "codeberg.org"
sshd-openpgp-auth list
set +o pipefail
ssh-keyscan -t ecdsa,ed25519,rsa codeberg.org | sshd-openpgp-auth add --known-hosts
set -o pipefail
sshd-openpgp-auth list

sq inspect --certifications "$SOA_OPENPGP_DIR/"*.tsk

export REMOTE_OPENPGP_DIR="$SOA_OPENPGP_DIR"
export SOA_OPENPGP_DIR="$PREV_SOA_OPENPGP_DIR"

添加第三方证书

客户端工具ssh-openpgp-auth可以根据PGPKI(即信任网)验证主机的OpenPGP证书的真实性。在这种情况下,客户端工具的用户通常信任一个中央证书颁发机构(CA):另一个OpenPGP证书持有者,它为该主机的OpenPGP证书签名。

假设主机example.com将使用用户ID为admin@central-ca.com的OpenPGP证书进行认证。

export CA_TMPDIR="$(mktemp -d)"

# create a temporary CA key
sq key generate --userid 'SSH CA <[email protected]>' --output "$CA_TMPDIR/ca_key.tsk"
sq inspect --certifications "$CA_TMPDIR/ca_key.tsk"

# certify the host's key using the CA key
sq pki certify --output "$CA_TMPDIR/example_certification.pgp" "$CA_TMPDIR/ca_key.tsk" "$SOA_OPENPGP_DIR/"*.tsk "<[email protected]>"
sq inspect --certifications "$CA_TMPDIR/example_certification.pgp"

现在可以通过将其与主机的可转移密钥TSK)合并来直接导入创建的证书。

sshd-openpgp-auth merge "$CA_TMPDIR/example_certification.pgp"
sq inspect --certifications "$SOA_OPENPGP_DIR/"*.tsk

在主机的TSK中管理如上所述的第三方证书具有优点,即证书在将主机密钥导出到WKD时直接可用。

导出到Web密钥目录

《sshd-openpgp-auth》的一个优点是,它可以在现有的基于OpenPGP的生态系统中用于证书检索:WKD

使用export子命令,可以将证书导出到本地目录,该目录可以直接由Web服务器提供服务。

export SOA_WKD_OUTPUT_DIR="$(mktemp -d)"
sshd-openpgp-auth export "example.com"

export SOA_WKD_OUTPUT_DIR="$(mktemp -d)"
sshd-openpgp-auth export "example.com" --wkd-type "direct"

延长有效期

当使用此工具时,所有添加的子密钥都依赖于OpenPGP主密钥的有效期。

使用extend子命令可以延长主密钥的有效期。

假设管理员想要将OpenPGP证书的有效期延长到默认值以上。

sshd-openpgp-auth extend --threshold 365 --expiry 730
sshd-openpgp-auth list

sq inspect --certifications "$SOA_OPENPGP_DIR/"*.tsk

撤销认证子密钥

有时有必要撤销一个或所有认证子密钥。这样做的原因可能是管理员想要使用更强的加密算法创建新的SSH主机密钥,弃用旧的密钥,或者在最坏的情况下替换受损的密钥。

以下小节将探讨不同的场景。

密钥已被取代

这是默认的撤销操作,用于新OpenPGP认证子密钥替换旧密钥的场景。

让我们再次想象我们是codeberg.org,并想用新的SSH主机密钥替换当前的密钥。我们将添加新创建的SSH主机密钥,然后撤销旧的密钥,同时附加一条指向新子密钥的消息。

export SOA_OPENPGP_DIR="$REMOTE_OPENPGP_DIR"
export SOA_SSH_DIR="$LOCAL_SSH_DIR"

sshd-openpgp-auth list
sshd-openpgp-auth add
sshd-openpgp-auth list

export REMOTE_SUBKEYS=( $(sshd-openpgp-auth list | grep '' | cut -f 2 -d ' ') )

sshd-openpgp-auth revoke --subkey-fingerprint "${REMOTE_SUBKEYS[0]}" --message "Superseded by ${REMOTE_SUBKEYS[1]}"
sshd-openpgp-auth revoke --subkey-fingerprint "${REMOTE_SUBKEYS[2]}" --message "Superseded by ${REMOTE_SUBKEYS[3]}"
sshd-openpgp-auth revoke --subkey-fingerprint "${REMOTE_SUBKEYS[4]}" --message "Superseded by ${REMOTE_SUBKEYS[5]}"
sshd-openpgp-auth list

sq inspect --certifications "$SOA_OPENPGP_DIR/"*.tsk

密钥已退役

在此示例中,假设我们只想退役单个SSH主机密钥(例如,因为我们不再支持相关的算法)。

export SOA_OPENPGP_DIR="$LOCAL_OPENPGP_DIR"

sshd-openpgp-auth list

export REMOTE_SUBKEYS=( $(sshd-openpgp-auth list | grep '' | cut -f 2 -d ' ') )

sshd-openpgp-auth revoke --subkey-fingerprint "${REMOTE_SUBKEYS[0]}" --reason retired --message "We stopped supporting RSA"
sshd-openpgp-auth list

sq inspect --certifications "$SOA_OPENPGP_DIR/"*.tsk

密钥已受损

让我们也来看看最坏的情况:我们的主机已被入侵,攻击者窃取了我们的SSH主机密钥,以便能够冒充我们的主机。

sshd-openpgp-auth revoke --all --reason compromised --message "This host has been compromised today!"
sshd-openpgp-auth list

sq inspect --certifications "$SOA_OPENPGP_DIR/"*.tsk

添加Keyoxide DNS证明

为了提高主机证书的可信度,还可以插入Keyoxide的真实性证明。

sshd-openpgp-auth proof dns add

上述操作将在证书中添加一个注释,表示关于证书所使用的域所有权的声明。客户端可以通过WKD或OpenPGP密钥服务器检索证书,并尝试验证此声明。

为了允许客户端验证附加注释的标识声明,必须在主机的DNS区域文件中添加特定的证明,格式如下TXT记录

openpgp4fpr:FINGERPRINT

其中FINGERPRINT是密钥指纹的小写十六进制表示。

几个授权密钥的示例

$ dig +short TXT metacode.biz
"openpgp4fpr:0e3bb828432962f4e33c9a74d1f809bb3f02ede9"
"openpgp4fpr:198c722a4bac336e9daaae44579d01b3abe1540e"
"openpgp4fpr:653909a2f0e37c106f5faf546c8857e0d8e8f074"

对于OpenPGP CA安装,OpenPGP CA证书的指纹也应出现在DNS区域的TXT记录中。

更多技术细节请参阅Keyoxide DNS证明页面。

资金来源

该项目由NGI Assure资助,该基金由NLnet设立,并得到欧洲委员会Next Generation Internet计划的支持。了解更多信息请访问NLnet项目页面

NLnet foundation logo NGI Assure Logo

许可证

该项目根据您的选择,受以下任一许可证的约束

贡献

除非您明确说明,否则您提交给本仓库的任何有意包含的贡献,根据Apache-2.0许可证的定义,应以上述双重许可,且不附加任何额外条款或条件。

依赖项

~19–28MB
~383K SLoC