YubiKey Challenge-Response 如何在“本地”工作?

信息安全 验证 密码管理 优比键
2021-08-27 02:20:41

我最近有一个 YubiKey NEO(有点失望,你只能在所有列出的方法中激活两种激活的第二因素身份验证方法)。

在支持 YubiKey 的密码管理器中,Password Safe是开源的并且可以在本地工作。它可以配置为使用YubiKey HMAC-SHA1 Challenge-Response进行身份验证。我很困惑如何仅通过两方安全地建立安全的质询-响应机制:(1)我的本地 PC,和(2)YubiKey。相关文档

实际上,将 Master Password 发送到 YubiKey,获取响应并使用它解密数据库有什么好处?现在,YubiKey 响应是我们的静态密码,它在内存中以及 Master Password 可以泄露的所有地方都是可用的。

他们实现它是为了好玩吗?还是我遗漏了一些要点?

4个回答

Password Safe 的源代码是开源的,所以你可以自由地做我所做的事情:检查。

HMAC接受两个输入:密钥和数据。PS 对 YubiKey 的作用是将您的输入作为数据发送到 YubiKey。钥匙在 YubiKey 本身并留在那里。

因此,事件的顺序如下:

  1. 你输入你的密码。
  2. 该软件将该密码发送到 YubiKey
  3. YubiKey 使用您的密码作为输入和(内部存储的)密钥执行 HMAC。
  4. 结果值被发送回应用程序并用于解锁您的数据库。

因此,只要各种加密元素是安全的,系统仍然是安全的:数据库 REAL 密码是 HMAC 操作的结果,HMAC 由保留在您的 2FA 设备上的密钥和您自己的主密码组成,这您通过计算机输入。

你错过了一些观点。

如果有人窃取了您的密码安全数据库文件的副本,他们将无法解锁它,除非他们也实际拥有您的 yubikey(即使他们已经知道您的密码短语是什么)。

当然,如果攻击者对您的系统有一定程度的访问权限,他们可以读取内存,那么无论您拥有多少个 yubikey,只要您解锁 Password Safe 数据库,您就会被搞砸。

将您的 yubikey 链接到 Password Safe 的一个好处是,您可以将 Password Safe 数据库文件备份到云中感觉好一些。

我在这里没有专门解决有关 Yubikey with Password Safe 目的的任何原始问题,但我认为我进行的实验可以对这种情况有所了解。

我已经确认@Kousha 是正确的:Yubikey 响应只是变成了静态密码。

如下所述进行验证。(我想提供以下代码来帮助Source Forge 上 Password Safe的发帖人,但我没有这样做的帐户。)

来自密钥的密码安全 Yubikey 响应

可以使用 HMAC-SHA1 和 Yubikey 的密钥以直接的方式生成 Yubikey 响应,但是由于空字符和操作系统不兼容,生成密码安全 Yubikey 响应有点复杂。(本质上,必须在挑战中的每个原始字节之间插入一个空字节。)此外,Yubikey 挑战会被解析简而言之,在 Linux 计算机上,如果key以 40 位十六进制形式存储 Secret Key 并message存储挑战,则以下命令应返回 Password Safe Yubikey 响应:

printf $message |
  xxd -p | sed 's/../&00/g' |
  sed 's/00$//' | cut -c -63 | xxd -r -p |
  openssl dgst -sha1 -mac HMAC -macopt "hexkey:$key" -binary |
  xxd -p

如果可能,您可能想在 Yubikey 上写入一个临时密钥,并使用您的真实密码以外的挑战进行验证——我不熟悉计算机如何存储变量或其他相关的安全问题。(如果有人对此有所了解,我很乐意学习。)您至少可以使用stty. 以下脚本提示输入密钥和质询而不显示它们,然后输出密码哈希 Yubikey 响应。

#!/usr/bin/env bash
stty -echo
printf "shared secret key (40 hexits): "
read HMACSHA1_key
if [ -z "$HMACSHA1_key" ]; then
    stty echo
    printf '\n    Empty input. Exiting.\n'
    exit 1
fi
if [ ${#HMACSHA1_key} -ne 40 ]; then
    stty echo
    printf '\n    Need exactly 40 characters. Exiting.\n'
    exit 1
fi
HMACSHA1_no_space="${HMACSHA1_key/ /}"
if [ ${#HMACSHA1_no_space} -ne 40 ]; then
    stty echo
    printf '\n    No spaces. Exiting.\n'
    exit 1
fi
HMACSHA1_key_mod_hex=$(printf "$HMACSHA1_key" | sed 's/\([0-9]\|[a-f]\|[A-F]\)//g')
if [ -n "${HMACSHA1_key_mod_hex}" ]; then
    stty echo
    printf '\n    Invalid characters: %s\n' "${HMACSHA1_key_mod_hex}"
    printf '\n    Only 0-9, a-f, A-F allowed. Exiting.\n'
    exit 1
fi
printf "\n"
printf "message/challenge: "
read HMACSHA1_value
if [ -z "$HMACSHA1_value" ]; then
    stty echo
    printf '\n    Empty input. Exiting.\n'
    exit 1
fi

printf $HMACSHA1_value |
  xxd -p | sed 's/../&00/g' |
  sed 's/00$//' | cut -c -63 | xxd -r -p |
  openssl dgst -sha1 -mac HMAC -macopt "hexkey:$HMACSHA1_key" -binary |
  xxd -p

我无法证明上述命令和上述脚本的可移植性。至少,它们是对我有用的东西的精简版本。

基本上,您添加的内容就像密码存储的老式物理“密钥”。

一把锁匠无法复制的“钥匙”。

在您现有的模型中,“密码”是薄弱环节。如果您不小心泄露了它,或者有人在网上冲浪,或者记录了您的击键,或者您在一个不稳定的网站上重复使用它,攻击者可能会进入您的密码存储。

在新设置中,攻击者需要完成所有这些操作,并且可以访问您的物理密钥。