普通视图

发现新文章,点击刷新页面。
昨天以前王玄的博客

将中文网页发送至 Kindle 的各种方法和坑

作者 Xuan
2024年12月29日 12:55

Update on Feb 28 2025: Kindle 新固件已经解决了字体设置不能持久生效的问题。中文显示问题比以前好解决了。对于大部分读者推荐使用 Instapaper。

Update on Jan 06 2025: 在比较列表中增加了「简悦」。

Kindle 退出中国之后,国区的微信推送和 Send to Kindle 服务都结束运营。还能用的网页推送服务大多 bug 很多,好用的不多。在此列举并比较一些有代表性的服务。目前的现成服务都不完美,如果要满足各种要求,折腾是免不了的。

服务概览

目前,还能用的服务包括但不限于以下这些:

  • Send to Kindle:由 Amazon 官方提供的服务,现在一般使用美区 amazon 帐户进行推送。
  • 简悦:国人开发的「阅读模式」和「稍后读」插件。
  • Pocket:Mozilla 旗下的热门「稍后读」服务。
  • Instapaper:在 Kindle 还热门的时候一度很火的「稍后读」服务,曾经最大亮点是推送到 Kindle 上的文章合集非常精致。
  • Wallabag:一个开源的「稍后读」服务,可以自己搭建服务器也可以使用官方服务。
  • Calibre:一款功能强大的电子书管理与转换工具,自带新闻抓取和邮件推送功能。
  • 微信读书: 如果要读微信公众号的话,可能是最方便的之一?也算是个歪门斜道的办法。
  • Word 文档之类的奇技淫巧。

需要考虑的问题和可能遇到的毛病

找一个能用的服务不难,找一个好用的服务还真有点折腾。能不能抓到要看的网页,推送到 Kindle 上后看起来舒服不舒服,各各有些不同。

1. 需要登录才能访问的网页

某些网页内容(如付费新闻或社交媒体)需要登录后才能查看。这类内容通常需要通过浏览器插件直接抓取,而不能把一个链接发给服务器让服务器来抓。1

大部分「稍后读」服务对此都或多或少有一些支持,但都需要 PC 端的 Chrome 或 Firefox 浏览器插件。在 iOS 设备上就比较挠头了。一般在 iOS Safari 上只能通过分享菜单把链接分享给对应 app,因此只能使用服务器端抓取。

目前支持浏览器抓取网页的服务及其插件表现:

  • Wallabag:官方浏览器插件 Wallabagger 支持用户自定义要通过浏览器抓取的站点。
  • Send to Kindle:全部通过浏览器抓取,但速度较慢。
  • 简悦:浏览器侧生成阅读模式后发送。
  • Instapaper:似乎也支持浏览器直接抓取。
  • Pocket:对部分网站(如《纽约时报》)有内置支持,但无法配置特定站点的浏览器抓取。对于不支持的网站就可能报服务器抓取失败。

2. 中文字符显示问题

这是一个 amazon 在 send to kindle 服务上取消 mobi 文件格式支持之后的新问题。由于这个问题出现的时候 amazon 已经官宣退出中国,对这个问题的讨论比较少。

现在用 send to kindle 服务的话,只能选择 epub 格式。而几乎所有服务推送的 epub 文件都把语言设置为英文。英文 epub 文件在转换并推送到 Kindle 上之后会出现诡异的中文字体问题,具体表现为:一部分中文字符是宋体,另一部分中文字符是黑体。与此同时,字体设置菜单只有英文字体可选,无法选择任何一款中文字体。仔细看的话,凡是日语中有的字符都是黑体,日语中没有的字符都是宋体,一看就是 fallback 时日文落在中文前面的老问题。Zotero 上也会有类似问题,在之前的文章中有过讨论。不知道为什么,原来 mobi 格式的文件就没有这个问题,也许那时候正好中文日文的默认字体都是宋体。

Kindle 在英文文档中的中文字体显示问题

可惜 Kindle 是个封闭系统,没有办法设置文字 fallback 的顺序。一种解决办法是手动安装一个支持 CJK 字符的字体,比如说 Noto Sans CJK (如果只看中文,安装 Noto Sans SC 就够了)。字体的安装比较简单,直接拷到 fonts 目录下就可以。

折磨人的点在什么地方呢?不知道是目前 Kindle 系统的 bug 还是怎么回事,每次打开文件的时候,都得重新设置一遍字体!甚至退出到主页、打开一下浏览器都会重设字体。实在是有点不能忍。

更新:在 Kindle 系统升级到 5.17.1.0.4 之后,这个 bug 已经消失。原 bug 发生于 5.17.1.0 固件。

如果不想折腾中文推送的话,现在可以通过安装支持中文显示的字体并保存一个新主题来部分解决这个问题。这样做之后,体验可以接近 KOReader。对于读所有书都喜欢用同一套字体的人来说,设置之后就基本无感了。对于英文中文书习惯用不同字体的人来说,会多一点切换字体主题的麻烦——因为这些推送来的网页声称自己是英文,调用专门设置的外置中文字体之后,再切换到其它英文读物时仍然会使用这套中文字体,就得再切一下主题才能切回喜欢的英文字体。KOReader 比 Kindle 好的点在于,KOReader 默认记忆这本书的主题设置,而不像 Kindle 的主题是全局生效。

由于下面为推送服务正确配置语言的办法大多比较折腾,如果读者对此要求不高,语言问题可以不用考虑,只考虑网页推送服务的抓取质量和阅读体验即可。

以下所有服务,统统都有这个语言设置错误的毛病:

  • Send to Kindle (美区)
  • Pocket (使用 Pocket to Kindle 服务)
  • Instapaper (使用自带 Kindle 推送)
  • Wallabag (直接导出 epub 的语言也是英语)

一劳永逸的解决方案有点折腾。有两个思路:

一个思路是,如果能用某种办法拿到生成的 epub 文件,修改语言不就是小菜一碟了吗?Wallabag 可以用 API 拿到每篇文章导出的 epub,Pocket to Kindle 的付费版可以发送到 kindle.com 之外的邮箱,同样有自行处理的余地,而 Pocket to Kindle 免费版和 Instapaper 只能发送到 kindle.com 邮箱,没有办法拿到他们生成的 epub 并做修改。

另一个办法就是用 Calibre 来抓取 Pocket 或者 Instapaper 的文章,然后再发送到 Kindle。在 Calibre 抓取的时候,可以轻松设置 epub 文件的语言。

无论是用什么办法,要想自动推送而不是手动抓,都得整个自己的服务器来定时抓取,设置好语言,再推送。对于不擅长技术的网友可能有些过于折腾。如果愿意把 Calibre 一直挂机的话,Calibre GUI 的配置倒是不麻烦。

3. 单篇网页,还是文章合集

最后一个问题是:Send to Kindle 这样的服务只能把单篇网页作为一本书推到 Kindle 上。要看的网页一多,就很乱。如果能推送文章合集的话,就会好很多。


具体服务比较

现在来看每个服务的问题在哪里。

Send to Kindle

这个 Amazon 提供的官方服务可以说是一切 Kindle 推送的基础。不过这里我们主要关心的是网页推送的能力。在 Chrome 浏览器上有插件可以推送网页,在手机端则是分享给 Kindle app,但是在手机端无法实现浏览器端抓取。

它既不支持文章打包,又有中文显示问题,还不支持 Firefox。除了偶尔推个长篇英文文章(比如说论文)可以凑合一用,我实在想不出有什么理由用 Amazon 自家的浏览器插件。

简悦

在写完本文之后才发现了「简悦」这个服务。试了一下,它推送的文章无论中英文显示都是正确的。如果不想自己折腾而只想用成品服务的话,它是我所知的唯一可以正确处理中文的服务。

和别家不同,「简悦」在推送单篇网页的时候使用的是单文件 HTML 格式。

简悦服务有几个小缺点

  • 需要付费版才能推送 Kindle。但相对于 Pocket to Kindle 和 Instapaper 的订阅价,简悦的买断价可以说非常便宜。
  • 不能仅用简悦的浏览器插件进行推送,还必须安装「简悦・同步助手」才能实现邮件推送。购买配置较为繁琐。如果只是为了 Kindle 推送的话,略有些折腾。
  • 推送也不是点一下插件图标,而是需要先进入简悦的阅读模式,再在二级菜单中选择推送到 Kindle。在推送之前必须先将阅读模式的主题设为浅色模式。如果阅读模式是深色,推送到 Kindle 的文章也是黑底白字。即使用键盘快捷键,也需要两次击键,两次点击,一次滚动,外加鼠标移动大半个屏幕的距离才能完成推送操作。
  • 似乎只有单篇网页推送,没有「稍后读」合集推送。

这些小毛病单拎出来都没什么,集合在一起就让人觉得用起来很不方便。

Pocket

如前述,现在它是 Mozilla 旗下,Firefox 原生集成,各平台都有 app 支持。

不打算自己折腾 Calibre 的话,第三方服务「Pocket to Kindle」可能是目前唯一的 Kindle 推送方案。这个服务如前所述,也有中文显示问题。

除了中文显示这个致命问题,还有一些小毛病:

  • 如果免费版功能不敷使用,要买高级会员的话,Pocket 高级版 $5/月,Pocket to Kindle $3/月。Pocket to Kindle 免费版每周仅可推送 5 次,对于高频使用者不太够用。但反正中文显示是个不堪用的状态,讨论一个不能用的服务的缺点也没什么意义。
  • 部分网页不能从浏览器端抓取,导致抓不到。

总之,如果很喜欢 Pocket 的跨平台支持,可以考虑用 Calibre 折腾一把。不然用起来很闹心。

Instapaper

虽然功能多年没有大的更新,仍然是个很好用也很有特色的「稍后读」平台。曾经很漂亮的排版在 amazon 停止 mobi 推送之后泯然众人矣。但相对于 Pocket to Kindle 免费版的每周五次的限额,Instapaper 的 Kindle 推送不限次数,依然领先同行。如果想买会员的话,每个月是 $6 。

可惜,Instapaper 也有中文显示问题,对于中文用户来说也属于不能用的状态。如果只有看英文网页的需求的话,Instapaper 是个不错的选择,比 Pocket 方案要划算。

对于中文用户,还是得用 Calibre 来折腾一把。

Wallabag

Wallabag 的浏览器插件是本文涉及的各种「稍后读」中最好用的。但它的移动端 app 有点寒碜。

在推送 Kindle 这件事上,它既不自带,也没有免费可用的第三方服务,全得靠自己折腾。

目前有两种折腾路线。

一种是使用 wallabag API 或者 python 包 wallabag-client 将其中的文章导出为 epub,再将 epub 文件中的 <dc:language>en</dc:language> 一行替换为 <dc:language>zh</dc:language>。最后再邮件发送到 Kindle。这个路线不太折腾,但是只能推送单篇文章,如果要推送文章合集的话,反而是 Calibre 方案更省力。

另一种办法是使用 Calibre 抓取 wallabag 的 RSS Feed 并推送文章合集。

如果不限于 Amazon 系统的话,可以给 Kindle 越狱装上 KOReader。KOReader 自带一个 wallabag 插件,还有人写了一个据说在 wallabag 里文章很多的时候性能更好的插件。KOReader 里的字体设置比 Kindle 自带系统细致得多,不需要设置文档语言也能调出可用的字体组合。

Calibre

Calibre 差不多算是 Kindle 用户必备软件了。它有一个很有用的 fetch news 功能,可以用来抓 RSS 订阅、新闻报纸和各种网站更新。它也支持把抓取后的 epub 文件邮件推送到 Kindle 上。

Calibre 里用来定义如何抓取新闻源的文件叫 recipe,如果用 Calibre 来抓取 wallabag/Pocket/Instapaper 的话,只需要选用合适的 recipe 之后,在 recipe 的 class 里设置好变量 language = 'zh' 就可以解决中文显示问题(当然此时英文会有一些小问题,但 Kindle 黑体下的英文还能看)。

如果有时间的话,也许会再写一篇详细介绍一下如何配置。

Wallabag 没有官方 recipe 但可以在配置 RSS 之后直接抓取。Instapaper 和 Pocket 都有官方 recipe,可以直接使用。不过我更喜欢另一个 Pocket recipe

由于 Pocket 的 API 不提供 Pocket 处理好的网页,只提供原始网页链接,Calibre 再去抓取网页做成 epub,会常常遇到被服务器拒绝抓取、抓取图片失败、版式错乱等问题。而 wallabag 的 RSS 是全文 RSS。因此 calibre 配合 wallabag 的使用体验要好于配合 Pocket 使用。

如果使用 Calibre GUI 的话,直接在 Fetch News 按钮下面配置就可以了。如果使用 Calibre 的命令行工具 ebook-convert 的话,可以写一个简单的脚本来定时抓取并发送邮件。

这样折腾的话有几个小缺点

  1. 如果要实现定时推送,要么有个电脑一直在运行 Calibre,要么找个服务器定时运行脚本。
  2. 需要自己写三五行代码来实现「如果没有新文章就不推送」的功能。而这个功能在 Pocket to Kindle 和 Instapaper 里都有。
  3. Pocket to Kindle 和 Instapaper 的官方推送在每篇文章前后都有 archive/favorite 按钮,而 calibre 生成的 epub 文件里没有这些功能,无法在读完之后标记「已读」。实现这个功能需要自己搭个中转服务器大大折腾一番。

对于第一点,其实也可以用免费的 GitHub Action 来部署。Calibre News Delivery 是一个已经做好的模板,直接部署并选择 recipe 后即可使用。作者也发布了一个教程

对于第二点,如果你使用这个 Pocket recipe 的话,可以参见附录我的代码。其它的 recipe 也可以参考这个思路。

最后一点确实有些折腾,如果觉得不太影响使用的话,可以不折腾。

微信读书等其它奇技淫巧

微信读书虽然不支持 Kindle 推送,但可以在 Kindle 上直接用浏览器打开 r.qq.com 来阅读,体验相当可以。而微信公众号直接在分享菜单里给微信读书留了一个位置。如果只是想看微信公众号的话,也许是最不折腾的方案。

另一个奇技淫巧是,把网页分享到手机上的 WPS,保存为 docx 文档之后再邮件发送给 Kindle。只要 WPS 里别点什么奇怪的配置,生成的 docx 文档的语言肯定是中文,也就不会有中文显示问题。但这个方法只适用于单篇文章,而且操作也有点太麻烦了。原则上手机上的 Office 也可以这么干,但是不知道为什么我手机上的 Office 总是顽固地试图分享 OneDrive 链接而不是实际的文档,不知道是不是我没找到路。

总结

综上,总结如下表。其中的「阅读模式」指的是,这些工具清理原网页的广告等干扰元素生成一个干净的「阅读视图」的能力。中文支持指的是推送到 Kindle 上的中文显示是否正常。

服务 浏览器抓取 文章合集 单篇文章 阅读模式 中文支持
Send to Kindle 一般 有问题
简悦 良好 优秀
Pocket 部分 通过 P2K 通过 P2K 尚可 有问题
Instapaper 优秀 有问题
Wallabag 通过 Calibre 可 DIY 一般 可折腾
Calibre 不好 良好
微信读书 优秀
WPS 良好

为 Kindle 越狱后装上 KOReader 的方案不算在上表中,因为所谓「中文支持」问题,仅仅是 Amazon 原生系统才有的问题。KOReader 支持 wallabag 同步和 calibre 无线同步。

最后我的推荐是:

  • 如果只看英文网页,推荐 Instapaper。
  • 如果有中文需求的话
    • 如果能接受安装一款新字体来解决中文显示问题,不折腾语言匹配的话,仍然推荐 Instapaper。
    • 如果对字体和操作便利性都比较挑剔的话
    • 怕折腾但很少有把网页推送到 Kindle 的需求,可以考虑微信读书或者 docx 这类奇技淫巧。
    • 能折腾的话,推荐 Calibre 配合 Wallabag。如果已经用惯了 Pocket 或者 Instapaper 懒得迁移数据,也可以考虑用 Calibre 配合它们使用,效果没有 wallabag 好。
    • 如果只用单篇网页推送的话,「简悦」也是一个方案。
    • 既不能折腾又有很多中文网页阅读需求,恐怕没有什么好办法了。

附录

参考

写作本文时,除正文中已经给出链接的引用外,还参考了以下资料:

为什么 Kindle 调用的字体和电子书语言不匹配

用 GitHub Actions 让 Calibre 定时推送新闻到 Kindle

I wrote a script that automatically sends unread wallabag articles to Kindle

https://www.xiaohongshu.com/explore/66bada96000000000d03300e (由于小红书的限制,必须在手机端打开此链接并跳转「小红书」 app 才可以查看内容)

修改 Pocket-Plus-Calibre-Plugin 使得无新文章则不推送

下面第一个 try 块是原 recipe 里本来就有的。搜索并找到之后将后面的代码粘进去就可以实现无新文章则不推送。别忘了定义 SESSION_DATA_DIR 变量并指向一个目录。

                try:
                    response = self.browser.open(request)
                    response = json.load(response)
                except HTTPError as e:
                    if e.code == 401:
                        # Calibre access has been removed
                        self.reauthorize()
                        raise e

                all_item_id = set()
                for item in dict(response['list']):
                    all_item_id.add(str(response['list'][item]['resolved_id']))
                # compare with previous saved ids
                if path.exists(path.join(SESSION_DATA_DIR,'pocket_ids.txt')):
                    with open(path.join(SESSION_DATA_DIR,'pocket_ids.txt')) as f:
                        # read in old_item_id
                        old_item_id = set(f.read().splitlines())
                else: 
                    old_item_id = set()

                # compare new and old
                if old_item_id != all_item_id:
                    with open(path.join(SESSION_DATA_DIR,'pocket_ids.txt'), 'w') as f:
                        f.write('\n'.join(all_item_id))
                else:
                    self.abort_recipe_processing('No new articles in the Pocket account "{}"'.format(self.config.user))

我的定时发送 Pocket 文章到 Kindle 的脚本

这个脚本我加到 cron 里了。

#!/bin/bash

echo "----------------------"
echo "Start fetching Pocket"

date

cd /path/to/your/pocket/data

# name the epub with date and time (to seconds)
EPUB_FILE_NAME=pocket_$(date +"%Y-%m-%d_%H-%M-%S").epub

# generate the epub
ebook-convert Pocket.recipe $EPUB_FILE_NAME

# if file exists
if [ -f $EPUB_FILE_NAME ]; then
    # send the file to kindle
    calibre-smtp -e SSL -u username -p password -r email.server.domain --port 465 --attachment $EPUB_FILE_NAME --subject "Pocket" "your_email_address" "your_own@kindle.com" "Pocket unread, fetched on $(date +"%Y-%m-%d %H:%M:%S")"
fi

echo "End fetching Pocket"
echo "----------------------"

  1. 这里的「服务器抓取」指的是把网页链接发送给某个在线服务,让它的服务器去访问和提取网页内容。但这种方法的问题是,「稍后读」服务器那边并没有你的登录信息,无法登录并查看这些需要登录才能查看的页面。与此相反,「浏览器抓取」方法是在你本地浏览器已经登录并有权限的情况下进行,直接把你正在查看的网页内容发给「稍后读」服务。 

The post 将中文网页发送至 Kindle 的各种方法和坑 appeared first on 王玄的博客.

passkey 指北

作者 Xuan
2024年11月4日 11:51

什么是 passkey

Passkey 的官方中文翻译是「通行密钥」,这实在不是个好的翻译。本来推广 passkey 的几大公司起这个名字,是和 password 相对应,password 是「用于通行的口令」,那么 passkey 就是「用于通行的钥匙」,简单好记。但 password 的中文已经约定俗成翻译为「密码」,「密钥」又另有所指,不得不起了这么一个蹩脚的翻译。四字短语永远会在广泛使用后有一个两字的缩写,不知道假以时日,会不会有人用「通钥」来简称 passkey。不过以今日中文网站对 passkey 的冷漠,这一天即使有大概也很遥远。

言归正传。天下人苦密码久矣。这些年有些时兴的 passkey 是又一波试图「消灭」密码的浪潮。

所有人都痛恨用户名-密码验证:总是记不住用户名、密码,试错几次锁帐户……每个月总有几次这样的时候让人想摔电脑。如果还有双因素认证,输完密码还要再输个验证码,人就更暴躁了。什么时候才能让这种证明「我是我」的过程不那么痛苦。

前些年国内网站在逐渐使用短信验证码来替换密码登录,可短信这个东西,仅作为一个验证手段都嫌不安全,作为唯一的登录凭据使用,简直是把脑袋挂在手机上。它成为中国主流的验证方式也是「自有实名制国情在此」。相对而言,公钥私钥验证,在密码学上早已成熟,在实际应用中久经考验,几十年来都被人认为是取代密码的最佳方案之一。在 SSH、PGP、PIV 卡等应用上,公钥认证已经广泛使用很多年。但是在网站登录上,由于易用性的原因,尽管已经有很多免密码登录的业界标准,却一直没有推广开来。

2022 年,Microsoft Google Apple 三大操作系统提供商,以及 Chrome Firefox 浏览器终于开始一致行动,推广免密码登录。虽然本质上是新瓶装旧酒,底层方案仍然是久已有之的东西,但一个好名字显然有助于推广,这个新名字就是 passkey。这之后,支持 passkey 登录的网站慢慢多起来。

Passkey 的目标不仅是取代密码,还要取代传统的两步验证(2FA)。对于两步验证,或者多因素验证来说,登入帐户需要两个凭证,一件是「用户知道的」,比如说密码,一件是「用户持有的」,比如说硬件密钥或者手机。如果有人偷了用户持有的东西,但是不知道密码,自然无法访问。如果有人偷窥到了密码,或者恶意软件记录了密码,只要没有把第二凭证拿到手,还是无法登入。Passkey 既然要取代两步验证,安全性自不能降低,还是要证明用户已经出示了两种凭证。

打个比方来说明一下什么是 passkey :一个网站或者其它需要验证身份的服务(relying party)(RP)要求用户出示某种凭证来证明身份:

军营前方,一骑快马奔来,军营守卫大喊「来者何人!」。如果用密码的话,来使在马上大喊「天王盖地虎!」守卫回去一看,好像确系皇帝所约定的暗语,于是放行。没想到使者见将军之后一剑刺死将军,大笑三声:「你们天天都是同一个口令,早就被我们密探听得一清二楚!」

如果使用 passkey 的话,只见来使从背后抱出一个沉重的密码箱,左拧右拧,露出一半虎符,将军让守卫传上来,和自己的那半虎符一对,严丝合缝,「果然是真使者!」

虎符只是个比方,实际使用的是更为安全的公钥私钥认证。在前述比喻中,实际发生的是:用户使用 PIN 或者指纹、面容解锁 passkey 设备(也就是上面比喻中的密码箱)之后,passkey 设备使用密码学上的公钥认证向 RP 发出证明:「兹证明,某用户在我这台设备上使用 PIN 解锁成功(既然您对我这款设备熟,您应该知道我只有在用户物理上持有我这台设备的时候才会发出证明,那个啥,第二因素认证就一并免了吧?)」。于是 RP 一方「收到,放行!」

如果要买个特制密码箱(passkey 设备)才能使用 passkey 的话,就不会有几个人用它了。老套的 OTP 验证之所以这两年来获得普及,就是因为在手机上装个 authenticator app 很方便,不需要 U 盾或者动态口令牌之类的专用设备。这次 passkey 的卷土重来,正是三大操作系统提供商陆续在操作系统层面加入了对 passkey 的支持:passkey 不再需要是某个专用设备,而可以是我们已经在使用的手机或电脑。既然手机电脑本来就需要 PIN 或者指纹解锁,又基本不离身,为什么不用作 passkey 呢?这次三家的联合推广使 passkey 成功破圈,以至于在绝大部分第一次听说 passkey 的人眼中,passkey 就是 iPhone 或者 Android 手机上的一个新功能。而那些专门的硬件设备如 Yubikey,在网站上愤愤不平地说:我们十几年前就可以当 passkey 用了!

相对于传统的用户名密码登录,passkey 无论是安全性和便捷性都要好很多。从安全性上来说,网站被拖库不会影响到用户的帐户,因为攻击者没有用户的私钥,即使获得网站数据库也无法假冒用户登入。从便捷性上来说,用户不需要记忆每个网站的密码,只需要记忆解锁 passkey 的密码,记忆负担大大减轻。十分建议本文读者尝试一下 passkey 登录:用过就回不去啦!

passkey 设备

粗糙地说,你可以把 passkey 设备看作前面比喻中的密码箱,而 passkey 就是密码箱里的虎符。(虽然 passkey 标准说,如果这个虎符没有放在密码箱里,而是随便什么人都能掏得到,它就不可以叫 passkey)由前所述,passkey 设备既可以是手机、电脑,也可以是一个单独的硬件密钥如 Yubikey。前者无疑比后者更便捷,因为手机每天都带在身边,但后者在抵抗网络攻击的安全性上更胜一筹。

Passkey 设备的安全性全系于它如何保护用户登录网站的私钥。如果 passkey 设备感染恶意软件,内部存储的私钥有可能会泄露。专门的外置硬件密钥一般无法被恶意软件感染,安全性更高。

不过,即使是手机、电脑,安全性也没有那么差。一般来说,现代操作系统会使用硬件安全模块来加密用户的私钥。这样的话,至少在用户设备关机之后,只要攻击者没有同时偷到解锁用的 PIN,不能解锁设备,私钥就是安全的。也就是说,一般情况下,已经关机的手机即使丢了也不需要担心。这方面 Windows Android iOS MacOS 没有太大的区别。实际中更可能遇到的风险是,设备在开机状态下感染恶意软件,比如说在访问恶意网站时受到感染。通常来说,恶意软件需要破坏操作系统的完整性才能隐藏输入 PIN 或指纹的弹窗,这种攻击比较困难,但并非没有可能。好在,网络攻击也遵守经济原则。这种「能偷到所有人电脑上所有 passkey」的漏洞的价值极高,攻击者一定会在漏洞被修复之前争分夺秒地攻击高价值目标。只要及时接受操作系统的安全更新,风险是可控的,普通用户不必过于担心。如果安全风险很高的话,三大操作系统厂商不会愿意联手推动系统内置 passkey 普及。

仅说理论上的风险的话,root 过的设备的风险远大于没有 root 过的设备,Windows Android 因为用户广泛,每年被利用的漏洞也多于 MacOS。而外置硬件密钥则还没有软件上被攻破的记录,只有侧信道攻击。这样说来,十分重视「绝对安全」的人,还是应该选择外置硬件密钥。不过,安全性也和线下的风险相关。手机一丢,立刻就会发现,而硬件密钥丢了,却未必见得会马上发现。

passkey 认证各方

其实,如果要把手机电脑当作 passkey 设备用的话,并不是只有操作系统提供的 passkey 功能可选。许多密码管理器也加入了对 passkey 的支持。如果我们说,passkey 的核心是这个「让用户输入密码或者按指纹之后就用私钥完成认证」的东西,它其实是个在 passkey 设备上运行的软件,在标准中称作 authenticator。如前所述,用户希望登入的网站或者 app 那一边,则叫作 relying party。

Passkey vs 密码管理器

如果不谈外置硬件密钥的话,完全基于软件的 passkey 和传统密码管理器相似度很高,所以传统密码管理软件也在纷纷加入 passkey 功能。假设某帐户同时提供密码和 passkey 登入选项,面对攻击时,用密码管理软件所管理的密码,会比 passkey 更安全吗?下面分情况讨论不同的威胁:

  • 如果网站数据库泄露,所谓的被「拖库」。原则上来说,存储在此网站的所有数据都不算安全,我们只关心我们的其它帐户是否有危险。如果使用密码管理器为每个网站设置单独的强密码,一样可以保证其它帐户的安全。Passkey 的更长的密钥长度在实际中不会有什么区别。可以认为两者在面对这类威胁时同等安全的。一定细究的话,passkey 有更好的防呆设计。如果用户在使用密码管理器时故意为不同网站设置同样的密码,密码管理器拦不住用户这么做。而 passkey 则完全不存在这个问题。
  • 如果用户选择将密码库和 passkey 同步到云端,当云端服务被攻破,且加密密钥泄露,无论哪个方案都会导致所有网站帐户陷入危险。攻击者可以很容易地枚举所有帐户并一个个登入。
  • 钓鱼网站。当攻击者仅仅在用户计算机以外设立了一个钓鱼网站,密码管理软件和 passkey 的 authenticator 都会校验 RP 一方的域名是否是正确的域名,都可以靠 HTTPS 防范中间人攻击。但如果用户的机器已经感染恶意软件,浏览器已经被篡改的话,两者都无能为力。
  • 如果讨论计算机已经被恶意软件感染的情况,事情就比较微妙了。相当一部分传统计算机安全专家认为一旦计算机已经感染恶意软件,一切全完。这种「全或无」的想法在实际中未免有些绝对。
    • 对于传统密码管理软件来说,对于运行于本地计算机的恶意软件的防范比较有限。但许多密码管理器都做了不同程度的防护:浏览器插件配对需要用户确认以免恶意软件冒名顶替,使用模拟键盘自动输入密码时乱序输入来防范 key logger,复制密码到剪贴板之后会定时清空剪贴板,解锁密码库时需要操作系统层面的 FaceID 或者 Windows Hello 授权,凡此等等。具体的实现每家密码管理器各不相同,需要仔细选择。
    • Passkey 相对来说,攻击面要小一些,passkey 根本不可能通过键盘输入,也就无需防范 key logger 和监听剪贴板的恶意程序。但仍然有一些攻击点:如果恶意软件冒充浏览器向 passkey authenticator 发出请求的话,它并不认证浏览器的合法性,而是依赖用户在输入 PIN 或者使用 FaceID 的时候察觉是否有不对劲。所以,即使伪装浏览器,恶意软件还需要有能力绕过操作系统的 PIN 或 FaceID 弹窗才能在用户不知不觉的情况下瞒天过海登入帐户,如前所述,这个难度并不低。有的用户不仔细看系统弹窗的显示内容,稀里糊涂就扫脸通过,那就很麻烦。
  • 设备被盗被抢。两者的情况大差不差。Passkey 是强制每次使用都需要解锁,如果使用 PIN 来保护 passkey 的话,在公共场合使用的时候容易被人偷拍到 PIN。而如果用 FaceID 或指纹的话,在被暴力胁迫时会直接解锁设备。而密码管理器也好不到哪里去,虽然提供了一些设置的灵活性,但如果设置每次输密码都要校验 FaceID 的话,就和 passkey 一样;如果一次解锁一直可用的话,如果设备在开机状态下被抢,直接就是裸奔。哪种更好,就要看你是认为自己的设备容易被附近的人在你不在的时候偷偷干点什么,还是更容易被人盯上之后蓄意抢走,还是……

总的来说,passkey 更标准化一些(虽然有很多非标实现),理论上来说更防呆。而密码管理器的可选设置选项更多,适合根据自己的 threat model 来定制。最坏情况下,在十分漠视安全的用户手中,密码管理器肯定更不安全。在最审慎的使用情况下,passkey 的安全性要略好一些,比如说完全免疫剪贴板监视程序。

而如果选择使用外置硬件密钥作为 passkey 设备,会比操作系统或密码管理软件提供的 passkey 功能更安全一些,相应地在便捷性上会有一些取舍。

passkey 类型

在目前的 passkey 推广过程中,即使是几家主要的厂商也常常对于他们是如何部署 passkey 验证语焉不详。如果对于安全有强迫症一样的追求的话,搞清楚「这家用的 passkey 到底有多安全」不是个容易的活。

反之,如果你只想要一个「比密码更安全的,用起来省心的登录方法」,大可以跳过此节,直接开始使用 passkey。

discoverable credential 和 non-discoverable credential

其实 passkey 只是 FIDO2 WebAuthn 换了个好听的新名字。对于 FIDO2 WebAuthn 来说,有两种凭证:discoverable credential 和 non-discoverable credential。以前叫作 resident key 和 non-resident key。现在说的 passkey,严格来说,应该只是 discoverable credential。不过也有一些网站比如说 Google 在管 non-discoverable credential 叫作 passkey。

就实际使用体验来说,discoverable credential 理论上连输入用户名都可以免掉。因为用户名、网站域名连同私钥一起存储在 passkey 当中。而 non-discoverable credential 则需要输入用户名之后再进行认证,passkey 设备本身并不存储该网站的登入用私钥。

简略而说,两者的工作模式是这样的:

  • 对于 discoverable credential,用户在网站选择使用 passkey 登入之后,网站会向 passkey 设备发出请求,设备检查自己是否存有该网站的登录凭证,如果有的话,就调取内部存储的私钥进行签名认证,没有就拒绝认证。如果有多个用户名的话,浏览器会提示用户选择其中一个用于登录。
  • 对于 non-discoverable credential,认证过程很像 FIDO U2F(虽然 U2F 通常用于 2FA 而非 passkey)。用户需要先输入用户名,网站调取记录,找到一段数据,将这个数据包发给 passkey 设备来进行下一步。这个数据(key handle)是和前述 discoverable credential 认证过程中的最大的不同点。它不仅仅包含网站的域名等信息,还包含用户私钥信息!不过它被 passkey 设备的公钥加密,只有 passkey 设备的私钥才能解密,所以网站无法读取或篡改其中的内容(这里说的 passkey 设备的私钥是它的 master 私钥,每个 passkey 设备上的每个 authenticator 只有一个,而非每个网站有不同的私钥)。这个数据解开之后,passkey 设备使用其中的数据重建「该网站认证专用」私钥,再以该私钥签名认证。如果仅仅用作第二因素认证的话,整个过程并不强制要求用户验证 PIN 。但如果是用作免密码登录的 passkey,用户必须要先输入 PIN 或者指纹解锁 passkey 设备,之后 authenticator 才会执行认证。

由上可见,discoverable credential 需要占用 passkey 设备的存储空间,而 non-discoverable credential 不需要。对于手机这样的设备来说,存储密钥所占的空间可以忽略不计,而对于 Yubikey 之类的外置硬件密钥来说,存储空间有限。5.7 版固件之前的 Yubikey 只支持存储 25 组 discoverable credentials,到底把这宝贵的 25 个槽用在哪些网站上就得琢磨一下了。

这两种认证方式的另一个区别是,最坏情况下,当 passkey 设备丢失,且 PIN 泄露,也就是说攻击者可以完全控制 passkey 设备时,攻击者可以直接枚举 passkey 设备中存储的所有 discoverable credential,然后逐一登录用户的每一个帐户。相反,攻击者完全无法获知这个 passkey 设备到底在哪些网站上注册了 non-discoverable credential,更不知道用户名,想控制用户的网络帐户还需要再花一番功夫。也就是说,在最坏情况下,用户有更多的时间去做亡羊补牢的工作。

遗憾的是,对于绝大多数网站来说,用户并没有选择到底是使用 discoverable credential 还是 non-discoverable credential 的自由,只能使用网站所提供的选项。

设备绑定的 passkey 和可以跨设备同步的 passkey

对于 passkey 认证来说,最核心的是用户的私钥。不同的私钥存储方式安全性不同。

最安全的私钥存储方式是:私钥在 passkey 设备上创建并只能在 passkey 设备上使用,永远不能离开 passkey 设备。这样做的缺点很明显:如果设备丢失的话,这个 passkey 就没了,需要使用其它方式登录后再创建一个 passkey。如果买了新手机,想在新手机中设置 passkey 的话,每个网站都要重新来一遍。

因此 FIDO2 标准并不禁止 passkey 设备将私钥传到云端。目前苹果设备上创建的 passkey 都会上传到 iCloud Keychain,而 Android 设备的 passkey 默认都会上传到 Google Password Manager。这样做的优点是用户买了新手机之后不需要重新设置,所有网站的登录凭证都自动下载下来立刻可用。但风险也因此增加:任何一个设备被攻击得手,所有存储于 iCloud Keychain 中的 passkey 都会泄露。整体的安全性等同于任何同步了私钥的 passkey 设备中安全性最低的那一个。比如说,如果手机端每次使用 passkey 都需要 FaceID 但 Mac 上只有开机的时候才需要验指纹,使用 passkey 的时候不需要的话,那么这个网站帐户的安全性就等同于它在 Mac 上登录时的安全性——也就是说任何人在 Mac 开机的时候偷走你的 Mac 就可以登入你的帐户 例子 。对于最重要的帐户,也许不要传到云端为妙。

目前 Apple 和 Google 默认都使用云端同步。而微软一方较为谨慎,Windows Hello 创建的 passkey 默认只存储在本地。

至少在目前,iCloud Keychain 无法在 Android 设备上使用。这带来了一点小麻烦:如果想在 iPhone 和 Android 上都使用 passkey 登录同一个网站,需要在两台手机上分别创建 passkey。一个办法是使用第三方密码管理器来同步 passkey,比如说 1Password,LastPass 和 Bitwarden,它们都同时支持 iOS 和 Android。但这些密码管理器并非操作系统组件,更容易被恶意软件攻击。

与此相对,外置硬件密钥提供了另一种思路:虽然密钥本身不同步到云端,但可以把硬件密钥插到不同设备上使用。使用 Yubikey 这样的硬件密钥,只需要在登入的时候把 Yubikey 插到(或者贴上)正在用的手机就可以了。因而,它既提供了最强的安全性,同时也提供了操作系统 passkey 所欠缺的一点跨平台同步的便捷性。

混乱的命名:passkey 和 security key

严格来说,只有 FIDO2 中的 discoverable credential (DC)才能称为 passkey。然而实际上,包括 Google 在内的网站依然将 non-discoverable credential (NDC)称为 passkey。所以遇到 passkey 一词时,唯一能确定的是,它是一种基于 FIDO2 WebAuthn 的免密码登录方式,可能是 DC 也可能是 NDC。

Security key,严格来说,指的是外接硬件密钥,它们可能支持 FIDO2,可能支持 U2F,也可能只支持老旧的 PIV 标准。这里的混乱要更大一些:在 Google 等许多网站中,security key 被特指为「使用 FIDO U2F 方式提供 2FA 认证的硬件密钥」。如果这个密钥可以被用作免密码登录,就会被改称为 passkey。也就是说,在这些网站上所称的 security key 是实际的 security key 的一个真子集,且和作为 passkey 使用的 security key 在使用场合上完全无重叠(虽然物理上可能是同一个设备)。比如说在 Google 帐户中,同一把 Yubikey,可以同时被登记为一把用于二次验证用的 security key 和一把用于免密码登录的 passkey。

另外一个定义上的混乱是,passkey 到底指的是存有 passkey 的设备(比如说手机、Yubikey)还是里面所存储的私钥?在实际中,passkey 常常模糊地指代两者。既可以看到「将手机用作 passkey」这种描述,也会看到「创建 passkey」这种描述。如果按前者,手机是 passkey,如果按后一种,手机里存储的私钥才是 passkey。准确地说,手机是 passkey 设备,里面存储的私钥是 passkey,而管理认证过程并存储 passkey 的软件,如前所述,是 authenticator。但在不致引起误解的前提下,将 passkey 设备和 authenticator 称作 passkey 似乎也没什么关系。

实际 在大部分网站中
手机、电脑里存储的 passkey 是 passkey 被称为 passkey
硬件密钥作为 2FA 凭证使用时 是 security key 被称为 security key
硬件密钥作为 passkey 设备使用时 既是 passkey 设备,也是 security key 被称为 passkey
设备中存储的 NDC 凭证 不是 passkey 可能被称为 passkey
任何使用 DC 免密码认证的设备 是 passkey 被称为 passkey

对于普通用户来说,没有必要搞清楚这些名词的区分。不过对于一些较真且在安全性上不愿意妥协的用户来说,本来这些网站在描述 passkey 时就常常语焉不详,这些名称上的混乱进一步增加了搞清楚问题的难度。

passkey 使用

本节可能会随各网站对 passkey 的支持情况而更新。最近一次更新于 2024 年 10 月。

可以用作 passkey 的设备

Windows

Windows 10 和 Windows 11 现在把 passkey 功能内置到了 Windows Hello 里,操作系统可以创建和管理 passkey。解锁 passkey 时可以使用 Windows Hello 所支持的任何 Windows 登录凭证,如 PIN,指纹等。

当在 Windows 设备上需要绑定 Yubikey 等外置硬件密钥时,需要注意弹出的提示到底是 Windows Hello 还是 Yubikey。通常 Windows Hello 会先弹出来,点击取消之后才会询问是否要绑定 Yubikey。使用外置硬件密钥来登入帐户倒没什么坑,不会有 Windows Hello 跳出来干扰。

iOS 设备

iOS 也已经支持 passkey 的创建和管理,系统创建的 passkey 会同步到 iCloud Keychain 中。在支持 passkey 登录的网站创建 passkey 之后,所有 iPhone iPad Mac 都可以用同一把 passkey 登录。支持使用 PIN,FaceID 或 TouchID 解锁 passkey。

iOS 设备的 Safari 似乎不能为外置硬件密钥创建 passkey,但使用外置硬件密钥登入帐户的体验是很丝滑的,无论是用 NFC 还是 USB 接口。偶尔在系统更新之后会有一些问题,比如说 iOS 18.1 就有许多人反映 NFC passkey 不好用。

Android 设备

Android 同样已经支持创建和管理 passkey。系统创建的 passkey 会同步到 Google Password Manager 中。不过 Google Password Manager 曾经有许多十分糟糕的安全设计,在密码管理器当中只能算三流产品,不知道以前的老问题现在是否都已经修正。

同样,Android 系统也支持使用外置硬件密钥。

Yubikey 等外置硬件密钥

任何支持 FIDO2 的硬件密钥都可以用作 passkey。不过,它们只能存储有限个 discoverable credentials。

固件版本 5.7 之前的 Yubikey 支持 25 个 passkey,5.7 及之后的版本支持 100 个 passkey。目前的冠军是 token 2 的 PIN+ Release2 系列,支持存储 300 个 passkey。最新的 Google Titan Security Key 支持 250 个 passkey 但并未提供删除替换旧 passkey 的功能,所以不一定好用。当然,这里说的 passkey 都是 discoverable credential。对于 non-discoverable credential,如前所述,则没有数目上的限制。

支持 passkey 登录的网站

passkey.directory 可能是目前最全面的 passkey 支持网站列表,对于一些网站还有当前支持的情况说明。

下面汇总一些常见网站设置和使用 passkey 的体验,会比 passkey.directory 写的详细一些。

Microsoft

在操作系统御三家中,Microsoft 对免用户名密码登录的支持最早,也最全面。不过很长时间里一直在测试,时灵时不灵。目前来看已经比较完善可用,对于各种 passkey 设备都有所支持。微软只支持 discoverable credential 登录。即使在当年 Yubikey 只能作为 2FA security key 使用的时候,也会创建一个 discoverable credential。如果当年已经将 YUbikey 作为 2FA 凭证登记,之后会自动升级成 passkey。

如果要使用 passkey 登录,登入时不可填写用户名,而需要点击下方的 Sign-in Option 按钮,再选择「Face, fingerprint, PIN or security key」。

综上,微软对 passkey 的支持最为规范全面,几乎没有什么坑。总结:只支持 discoverable credential,不需要输入用户名,支持所有类型 passkey,支持所有浏览器。

微软旗下的不少网站,如 GitHub 等,对 passkey 的支持和微软自家网站相当。

Google

Google 对 2FA security key 的支持很早,但 passkey 功能上线之后有相当长的时间里这个功能极度混乱。目前 Google 的实现也是比较奇怪的。

如果使用操作系统内置 passkey 功能创建 passkey 的话,Google 应该创建的是 discoverable credential。而如果使用 Yuibkey 作为 passkey 设备的话,大部分情况下会创建 non-discoverable credential,虽然也有人说他们创建了 discoverable credential 但我从未成功过。什么时候是 discoverable credential 什么时候是 non discoverable credential 有些难以捉摸。Google 应该是为数不多的可以使用 non-discoverable credential 进行免密码登录的网站。遗憾的是这并不是 Google 文档中明文提供的选项,所以这种行为并不稳定,实际登记 passkey 的时候到底发生什么就 YMMV 了。

在登录 Google 帐户时,免用户名登录的选项比较隐蔽。如果浏览器支持 passkey,当光标停在用户名输入框的时候,会有一个小下拉菜单「Use a passkey」。不然的话,在输入用户名之后还有一次选择 passkey 登录的机会。如果用的是 non-discoverable credential,只能在输入用户名之后才可以用 passkey 登录。

Google 也是主流服务里少见的允许用户将一把硬件密钥同时登记为 2FA security key 和 passkey 的网站,当然这样也没什么用。目前来看,似乎只有在很久以前就在 Google 帐户中登记的 2FA security key 可以和 passkey 共存。如果用最新的硬件和最新的浏览器,一把硬件密钥只能在 2FA security key 和 passkey 中二选一。

在今天,如果想把 Yubikey 仅用于 2FA security key 的话,办法是先禁用 Yubikey 的 FIDO2 功能,再作为 security key 登记(否则会被登记为 passkey)。

一些小提示:

  • 如果帐户中既有 2FA security key 又有 passkey 的话,有些环节的交互逻辑会有些令人迷惑:比如说,在已经登入帐户的情况下,如果要访问一些敏感信息,仍然需要再次验证密码或 passkey,此时 2FA security key 不可以用于验证身份,必须使用密码或 passkey。如果用的 key 仅注册为 2FA security key 的话,用户可能会对验证失败的结果有些迷惑。
  • 在 Google 网页上创建 passkey 时,如果使用 create a passkey 选项,则只能使用操作系统内置 passkey 功能。如果需要注册外置硬件密钥,需要使用 Use another device 选项。

总结:支持免用户名登录,对外置硬件密钥支持有些奇怪,支持所有类型 passkey,支持所有浏览器。

Apple

Apple 对 passkey 的支持是御三家里最迟缓的。很长时间里,苹果即使对于 2FA 也是坚持使用自家平台的验证码推送。对于 passkey 来说,苹果同样选择尽可能把用户困在自己的生态环境里。

目前,没有任何办法为 Apple ID 手工创建 passkey。使用 iOS 17 以上的设备登录 Apple ID 时,会自动为用户创建 passkey,这个 passkey 在设置中不可见,无法删除。

在使用浏览器登入 Apple ID 时,在输入用户名之后有一个使用 passkey 登入的选项,然后可以使用 iPhone 扫码登入。这似乎是使用 passkey 登入苹果帐户的唯一途径。目前不支持 Firefox。

苹果支持使用 Yubikey 作为 2FA security key 但不支持将 Yubikey 用作 passkey。更讨厌的是,目前用 Yubikey 做 2FA 也很令人痛苦:许多旧设备和 Windows 客户端、Android 客户端会被踢下来无法登录。目前在非苹果平台上的客户端,只有 iCloud for Windows 已经明确支持 security key,其它的支持状态仍然不明,许多人反映,一旦启用 security key,Apple Music 无法在非苹果平台登录。往好里说,苹果至少做对了一点:如果你希望用 security key 来加强安全性,那么所有更不安全的登录方式都必须被禁用。但苹果迟缓的的软件开发进度使得 security key 目前体验不佳。

总结:没有免用户名登录,只能使用苹果设备,无法绑定第三方 passkey,不支持 Firefox。即使是 security key 的支持也有很多限制。

GitHub

作为微软旗下网站,对 passkey 的支持是一流的。如果之前已经把 Yubike 登记为 2FA security key 的话,在创建 passkey 时会提供「升级」为 passkey 的选项。在 Firefox 上,这个升级过程有一定概率出错,如果出错的话需要删除重加一下。和 Google 不同,同一把硬件密钥在帐户里只会显示为一把,要么是 2FA security key,要么是 passkey。

和其它微软服务一样,如果使用 passkey 登录的话,不要填写用户名,直接点下方的「Sign in with a passkey」。

总结:只支持 discoverable credential,不需要输入用户名,支持所有类型 passkey,支持所有浏览器。

Amazon

Amazon 对 passkey 的支持吧,说是不支持,它倒也支持。但这个支持实在是实现的脑洞清奇。

首先,amazon 对 passkey 的理解就很成问题。它的帮助文档里认为 passkey 「仅仅」是可以在云端漫游的 passkey ,所以你只需要一个 Apple 的,一个 Google 的,不需要更多了。视 Microsoft 和 Yubikey 为无物。虽然实际上也完全可以用 Windows Hello 和 Yubikey 绑定 passkey 。

其次,amazon 无法使用 passkey 绕过 2FA。passkey 只能省去输密码的麻烦,形同一个密码管理器(参见上文,可能它的技术团队真的觉得 passkey 和你把 amazon 密码存在 iCloud Keychain 里没什么区别)。如果你的 amazon 帐户开启了 2FA,那么你每次登入 amazon 需要解锁 passkey 之后再输入 2FA 验证码。这纯属脱了裤子放屁。2FA TOTP 验证码唯一的作用就是证明用户持有一个可以生成验证码的设备。如果按 amazon 的理解,passkey 就存在手机上,TOTP 也是手机上的 app, 多这一道手续不会增加任何安全性。

最后,amazon 创建的是 discoverable credential,但它依然要求输入用户名登录,无法实现免用户名登录。

综上,在 amazon 上使用 passkey 的唯一用途大概是「不输密码,避免被键盘监听软件偷密码」吧。

Adobe

Adobe 对 passkey 的支持也是比较奇特的。像 Google 一样,它在登录的时候在输用户名的地方有一个下拉框可以选择 passkey,此时只能使用 DC 登入,而输入用户名之后,还有一个使用 NDC passkey 登入的按钮。不过我只成功地创建 NDC passkey,不知道它到底支持不支持创建 DC passkey。

和 Amazon 一样,用 passkey 登入 Adobe 时不能跳过两步验证,登入过程十分麻烦。

最后,它甚至不提供为 passkey 重命名的功能!如果 passkey 丢失之后想删除的话,大概只能把所有 passkey 都一股脑删掉了帐。

总的来说,这个支持确实很差,和 Amazon 一样,唯一的用途就是「不输密码」。

ebay

ebay 对 passkey 的支持和 Adobe 有些相像,但是用户体验更差一些。见下面的第四条。

  • 它只支持 NDC,所以无法实现免用户名登入。
  • 在 passkey 管理页面也没有重命名选项,难以区分不同的 passkey,出问题的时候只能选择全部撤销。
  • 并不需要开启 2FA 就可以使用 passkey,它的 2FA 选项里也不包括 passkey。也就是说,它和 Amazon Adobe 在此问题上的观点是一样的:passkey 仅仅是密码的替代。
  • 用户名需要自行输入,在输入密码的地方,如果浏览器支持的话,有一个使用 passkey 的下拉框,选择之后可以使用 passkey 跳过密码。(其它几家都是在用户名输入框就有 passkey 下拉框)

总结:只支持 NDC,只能作为密码的替代。

NVidia

NVidia 对 passkey 的支持很早,但支持很奇特。登录的时候必须选择“Login with Secure Device”,之后可以用 passkey 免用户名登录,却仍然需要输入 2FA TOTP 验证码。

总结:使用 discoverable credential 支持免用户名登录,但仍然需要 TOTP 验证码。

Passkey 支持十分糟糕的网站

有一些网站,说是支持 passkey 吧,确实是支持的,但有些致命的问题。

  • CVS: CVS 的网站做的奇差无比。它只能登记一把 passkey 且不提供删除 passkey 的选项!你最好指望你的 passkey 永远不会丢……

The post passkey 指北 appeared first on 王玄的博客.

对 ProtonMail 及其它加密邮件服务的看法

作者 Xuan
2022年4月8日 05:36

这段时间在考察几个比较有名的加密邮件服务商,本文系把自己的笔记简单扩充而成。分成两部分,第一部分以 ProtonMail 为例讨论了目前加密邮件服务的问题。第二部分简单对比了一下几家著名的加密邮件服务商。

以 ProtonMail 为例讨论加密邮件服务

引言

很多注重隐私的人正在逃离 Gmail 这样的大公司服务而转向更重视隐私的加密邮件服务商。然而,固然这些服务商在降低加密技术的使用门槛上做了很大努力,也的确使得它们的服务相对于传统邮件加密工具显得更加平易近人,但使用者如果盲目信任它们而以为使用它们就完全安全,因而疏于防范,很可能会使自己陷入真正的危险中。尤其是对于某些不希望公权力侵犯自己的通讯隐私的人来说,这种虚幻的安全感可能更加危险。

端到端加密不是银弹

恰当地实践端到端加密总比喊口号更重要。而这不能只靠服务商来完成,也需要用户的参与。

Trust on First Use (TOFU) 是端到端加密的一个重要问题。对于任何端到端加密来说,第一步交换密钥是最为脆弱的时间,需要慎重验证密钥究竟是对方的真实密钥还是攻击者的假冒密钥,否则之后的所有安全就无从谈起。对于大多数人来说,无法在频繁更换密钥的同时每次都认真校验对方身份,对于他们来说,长期使用的密钥会更加安全。
我们姑且假设 ProtonMail 用户彼此通信时它的服务端软件足够可靠,和站外用户互通 PGP 加密邮件时,是否要信任对方的公钥,就完全仰赖用户自己的小心谨慎。
进一步说,即使是两个 ProtonMail 用户之间的通讯,也同样面临 TOFU 问题的变种:如何知道对应的邮箱地址是对方的真实邮箱地址而不是钓鱼邮件地址?整个邮件通讯的安全也就完全系于「获得这个邮件地址」的那一瞬——如果是从某人的个人网页上获得,则整个通讯的安全性就不会高于那个网站的安全性(当然,可能那个网站本来就是假的);如果是在其它聊天工具中获得邮件地址,那么任何有能力控制该聊天软件的人都可以变造假的邮件地址。
相比之下,使用传统 PGP/GPG 邮件加密的用户大多对于 TOFU 的风险有所了解,彼此的互信也完全不依赖于邮件服务商的软件安全性。只是用户友好度远不及 ProtonMail。

ProtonMail 用户的私钥保存在他们的服务器上。对于安全极端在意的用户很可能并不放心。虽然 ProtonMail 用户的私钥使用用户的密码进行加密,理论上只能被用户解开。但是在私钥泄露的情况下,比如说 ProtonMail 迫于法院命令交出私钥后,离线暴力破解的难度取决于密码的长度和复杂度。因此 ProtonMail 的密码必须设置得足够长。

安全不是一个人的事

ProtonMail 仅在通讯双方都使用 ProtonMail 或 PGP 时可以提供理想的加密保护。

用于收信时,外站发信方如果不使用 PGP 加密,邮件内容将对诸多相关方(比如发信人的邮件服务商)可见。此时 ProtonMail 与任何普通邮件服务商无异,除了它对于权力方的数据披露请求会抵抗得久一点之外——然而发信人的邮箱依然会被权力方检查,这种抵抗很可能是毫无意义的。用于发信时,外站收信方如果不使用 PGP 加密的话,就只能使用 ProtonMail 的网页加密服务,在 ProtonMail 的网页中输入密码来提取邮件。对于大多数人来说这很麻烦不说,还需要使用 back channel 传送解密密码,这也不一定是可靠的。

如果说 TOFU 问题对于大多数人来说还不算个问题,因为大多数人并不担心公权力会盯上自己(虽然我并不同意这一点,mass surveillance 本身就是对公民权利的侵害),而更关心 Google 会不会用自己的邮件对自己进行用户画像。那么「邮件往来的另一复本并未被保护」使得后一种目标也难以实现。

可惜的是,自己使用 ProtonMail 很容易,说服朋友一起使用 ProtonMail 或 PGP 很难。拿 ProtonMail 做主邮箱的话,其实大部分邮件仍然是得不到保护的。

不谨慎使用 ProtonMail 可能遇到的风险

ProtonMail 可能向执法者交出哪些信息?如果收到瑞士法院的搜查令,ProtonMail 可以向法院交出如下信息:

  • 用户的登录 IP。
  • 用户与哪些邮件地址有邮件往来,及往来邮件标题。
  • 密码保护的用户私钥。如果用户密码可以被破解,则可以据此解密用户的全部邮件。

不谨慎使用 ProtonMail 可能遭到的攻击举例

  • 和自己通讯的人的地址是假的,攻击者在中间代理收发。
  • 没有隐藏自己的 IP,或者在有很多个人信息的地方发布自己的邮箱,导致肉身被有关方面定位。
  • 使用 ProtonMail 来接受材料,但发送材料的人未使用 ProtonMail。发送材料的人被定位并受到人身威胁交出通讯往来。
  • 使用 ProtonMail 给其它邮箱发信,将加密密码与加密邮件发到同一邮箱中。对于可以获得对方邮箱数据的有关方来说,这种加密形同虚设。
  • 行为触犯所在国法律及瑞士法律,密码设置过短,在 ProtonMail 配合法院交出数据后,密码被破解。
    这类例子还可以举出几十种。

如果极端看重邮件安全、匿名和完全的隐私保护,应该注意以下几方面

  • 注意验证通讯方的公钥和身份
  • 设置足够长的密码
  • 要求通讯对方也使用 ProtonMail 或 PGP 对邮件加密
  • 注意验证 ProtonMail 的邮件地址真的属于目标联系人,否则无法避免中间人攻击
  • 注意使用 Tor 隐藏自己的 IP
  • 注意不要在发布邮箱地址的信道(无论是个人网站还是即时聊天工具)中泄露过多个人信息

ProtonMail 的隐私保护实现所带来的使用不便

ProtonMail 与传统邮件客户端的互操作性很差,必须使用 ProtonMail Bridge 来连接第三方邮件客户端。而传统 PGP 或 S/MIME 加密都有广泛的客户端支持。

因为 ProtonMail 的服务器无法看到邮件内容,这带来两点不便:
ProtonMail 的服务端不支持邮件全文搜索。目前它的邮件搜索是通过在用户端进行索引而实现的。也就是说临时使用他人电脑时,无法在短时间内获得全文搜索。
加密必然意味着服务器端无法过滤加密垃圾邮件。虽然目前发送加密垃圾邮件的人不多,这还没有成为一个现实问题。

同样,从 ProtonMail 发出的加密邮件也无法被目标邮件服务器的反垃圾引擎检查。为了避免自身被列入垃圾邮件黑名单,ProtonMail 对于发信有苛刻的标准,每日发送邮件有限额,帐号注册也有很大限制。

从很多年前开始,从外网发到中国境内的加密邮件就有很大的概率掉信。这不是 ProtonMail 的问题,而是任何加密邮件的问题:只要收信人的邮件服务器在中国大陆,就难以通邮。这也是我建议所有朋友至少持有一个服务器在大陆以外地区的邮箱的原因之一。

所以使用 ProtonMail 没有意义吗?

不,虽然我上面列举了很多 ProtonMail 的缺点,我绝不认为使用 ProtonMail 毫无意义。相反,我推荐朋友们使用 ProtonMail 这样的加密邮件服务。

当我们选择加密邮件服务的时候,我们常常以为它可以同时提供安全、隐私保护、匿名等所有需求。本文意在破除这种幻想。但很多时候,只要在某一点上比已有的主流服务强,就值得我们考虑使用。我们也并非所有时候都需要绝对的隐私和匿名,而会为了沟通的便利而牺牲一些隐私和匿名。比如说,严格来说,越经常被使用的联系方式,越不可能做到完全的匿名。而用于期刊投稿、找工作之类的邮箱,更是与我们的线下身份完全绑定。

在合理使用的情况下,加密邮件服务至少可以让各种想看到我们邮件内容的人挠头,无论他们是广告系统、小至公司大至政府机关的各类监视系统还是一些有偷窥欲的人。达到这个目的并不难。
真正困难的是彻底匿名的需求,加密并不必然带来匿名。虽然大部分人都想要一定的匿名性,但考虑到实现它的巨大代价,大部分人最终会放弃彻底的匿名。

总结

综上,对于没有经验的小白来说,ProtonMail 固然带来了更佳的安全性,但小白也往往因此忽略了其它安全措施,像许多 Telegram 的使用者一样,因这种虚幻的安全感而降低了防御心,反而对自身带来更大的危险。
而对于有经验,懂技术的人来说,ProtonMail 并不是必须的。Tor+Gmail+GPG 就可以提供足够的安全性——甚至更安全。

它最有用的场合是:对于不愿意配置 PGP 加密的通讯双方,在使用可靠的方式认证彼此的身份后,双方约定都使用 ProtonMail 通讯。然而在这种情况下,它并不比 Keybase、Signal 之类的端对端即时通讯更方便。本来 Email 的一大优点是互通性,不像即时聊天工具,必须要求通讯对方也一起注册。但 ProtonMail 在与非 ProtonMail 用户通信时,配置端到端加密的门槛仍然不低,它的易用性与互通性仍然不可兼得。注册一个 ProtonMail 并不比注册 Signal 更方便,所以很多人干脆选择 Signal 之类的聊天软件。

特别危险的一点是,若作为个人主力邮箱,兼用于注册各种网站,ProtonMail 将完全无法实现「匿名性」。除非在各种网站上完全不暴露 IP 地址等个人信息(然而,这非常难),否则权力方很容易通过合并诸多网站上的信息获知此邮箱地址主人的肉身信息。届时,权力方只需要强迫与此邮箱地址通信的其它邮箱服务商交出邮件数据,邮件往来就无所遁形。这里的权力方不仅仅是公权力,也包括手握大量网站数据的互联网巨头。

综上,ProtonMail 基本上只适合个人通信,最好和其它 ProtonMail 用户通信使用。也可以用于有经验的 PGP 用户和加密邮件新手之间的加密通讯。
本文的大部分观点也适用于 Tutanota 等其它端到端加密邮件服务商。

加密邮件服务商概述与比较

综述

以下所有服务商对私钥的管理都是一样的,都是选择将私钥存在服务器,使用用户密码进行加密。也就是说仍然是 Web 优先,牺牲一点安全性。

如果对此很在意,想自行保管私钥,这些服务商都不能用,而只能用前文提到的,使用 PGP 之类的协议进行邮件加密。这些工具一般被认为用户友好性欠佳。如果想实现和 ProtonMail 一样的 Web 界面操作,可以使用 Mailvelope 这样的浏览器插件。如果这样做的话,就不得不使用 Gmail 的之类的大邮件服务商,插件的支持才会比较好。
PGP+Mailvelope+Gmail 这一方案的优点是密钥更加安全,缺点一个是少了同服务商网络内的默认加密,一个是收到的外站未加密邮件不会被加密存储。

前面已经讨论过,由于收发邮件的另一方使用加密邮件的极少,无论使用加密邮件的目的是为了保护自身隐私,对抗 mass surveillance,还是单纯讨厌互联网巨头,我们都很难靠自己一个人的努力来使自己更安全。在多大程度上倚重加密邮件,是否努力向周围朋友宣传使用加密技术的意义,是非常个人的选择。

虽然一般来说,加密邮件服务商都努力实现端到端加密,这样即使被执法人员要求交出数据,用户的损失也有限,但由前面所讨论的,我们仍然不希望这种情况发生。所以服务商所在的国家也是一个重要的因素。一般来说,最不可信任的是某些法律上公民隐私保护很差的国家,然后是著名的五眼联盟,这些国家的邮件服务商面临的法律风险和监视风险比较大。目前欧盟国家在隐私保护上的信誉要好一些。

很多人认为,开源的邮件服务商更值得信赖。

ProtonMail

上文已作详细讨论。服务器在瑞士,是对于隐私保护最好的国家之一,依法院命令交出用户数据的情况极少。
客户端代码开源。

Mailfence

比利时的一个邮件服务商,主要用户在欧洲。

代码暂不开源。可选 PGP 加密,而非强制。相对于 ProtonMail 功能要多一点,支持 POP3 IMAP,想来与普通 PGP 邮件在客户端的互操作性要好一些。

Tutanota

德国的一家加密邮件服务商。

客户端开源。使用 AES 和 RSA 加密,而非 PGP。这样它无法和其它 PGP 用户和 PGP 邮件服务商互通信,从而进一步限制了它的使用——基本上只有 Tutanota 用户之间的邮件可以有比较好的加密保护。完全不支持 IMAP。

mailbox.org

和 Mailfence 定位相近的一家邮件服务商,在德国。

可选 PGP。对于各种客户端支持良好。

The post 对 ProtonMail 及其它加密邮件服务的看法 appeared first on 王玄的博客.

梦中梦一则

作者 Xuan
2020年4月3日 02:01

今天早上做了一个梦中梦。梦见 Trump 总统躺在担架上,据说是死于新冠病毒。他脸色一如既往地红润,一头金毛还如平常一样地不羁,只是难得地闭上了他的嘴,显露出半是不屑半是安详的神色。遗体身着黑色西装,脚上却没有鞋子。我被人叫来把他抬走,却没有人给我口罩,我并不抱怨,内心感到非常平静。

一睁眼发现我在一张床上,宿舍区的美国大妞们完全没有保持 social distance 而在大喊大叫跑来跑去。一个两年没见的老朋友远远喊我赶紧下床出去吃饭,我在床上懒洋洋地应着:“刚刚我梦见特朗普死了!这么好的梦,谁愿意醒啊!”

似乎意识到特朗普之死不过是一个梦,这个梦也就不美,于是我真正地醒来,回到了自己的床上。

The post 梦中梦一则 appeared first on 王玄的博客.

❌
❌