#authenticator #otp #qr #cli

cli_google_auth_from_exported_qr_jpg

CLI从Google身份验证器导出的QR jpg图像生成2FA OTP代码

1个稳定版本

1.0.71 2023年3月26日

#868身份验证

MIT 许可证

33KB
231 代码行

cli_google_auth_from_exported_qr_jpg

CLI从Google身份验证器导出的QR jpg图像生成2FA OTP代码
版本:1.0.71 日期:2023-03-26 作者: bestia.dev 仓库: Github

Lines in Rust code Lines in Doc comments Lines in Comments Lines in examples Lines in tests

crates.io Documentation crev reviews Lib.rs License Rust

标签:#rust #rustlang #教程
我的GitHub项目更像是教程而不是成品: bestia-dev教程.
GitHub上的生成文档: https://bestia-dev.github.io/cli_google_auth_from_exported_qr_jpg/

动机

在我朋友度假时丢失手机后,我意识到双因素认证(2FA)可能是个巨大的麻烦。我背得所有的主要密码,但这已经不够了。
大多数严肃的互联网服务今天都使用某种双因素认证(2FA)。我的2FA主要与我的手机相关联,如果我丢失它,我就完了。最初,互联网服务在登录时会给我发短信。这是一个糟糕的想法。如果我丢失手机,我可以在几个小时之内买一个新手机,但要从我的运营商那里获得相同电话号码的SIM卡可能很棘手。尤其是如果我身处地球另一端的外国国家。更不用说短信因为任何原因根本不起作用的情况了。据说骗子可以通过社会工程绕过基于短信的2FA。

后来,所有服务都开始采用OTP(一次性密码)的概念进行2FA,主要是TOTP(基于时间的一次性密码)。基于时间的一次性密码(TOTP)是一种计算机算法,它使用当前时间作为唯一性的来源来生成一次性密码(OTP)。TOTP是开放式认证倡议(OATH)的基石,被许多双因素认证(2FA)系统使用。它已被采用为互联网工程任务组(IETF)标准。

我在安卓手机上使用Google身份验证器应用生成许多互联网服务的2FA TOTP。我觉得还可以。TOTP是一个标准,所以我不期望不同应用程序之间有太大差异。但遗憾的是,Google身份验证器只在安卓上运行。如果我丢失手机,我就无法使用Windows或Linux计算机生成我的TOTP。这正是我想要的。

有很多针对Windows和Linux的TOTP程序,但我只是需要找个理由自己写一个。毕竟,我是一名编程爱好者/教师。

Google身份验证器可以将单个TOTP定义“传输”或“导出”为二维码。在Android上,我无法截图这个二维码,但可以用另一部手机的相机拍照。老式的愚蠢技巧!所以现在我有一个jpg图像,包含在另一台设备上生成TOTP所需的所有种子数据。二维码中的文本类似于

otpauth-migration://offline?data=...

我想将这个jpg保存在某个安全的地方。将数据放在二维码jpg中而不是文本格式中,是一种小小的混淆想法。安全性永远不是100%,这只是使黑客更难理解所发生的事情的一系列步骤。

在需要的情况下,我想有一个简单的单文件CLI程序来读取jpg中的QR码并生成我的OTP。终端中永远不输入任何秘密,只有jpg文件名。

由于这个项目的教程性质,当然必须用Rust编写。

短名称

这个开发项目的名称非常长且表达性强 cli_google_auth_from_exported_qr_jpg。对于CLI,我希望有一个简短的名称,如 gajpg。为了实现这一点,我只需更改/src/bin/目录中的目录名称。然后我将使用如下行调用CLI

gajpg image1.jpg

测试数据

我仅在https://totp-online.tobythe.dev/上创建了一个TOTP种子以进行测试。

{
    "account":"test",
    "issuer":"tester",
    "secret":"w5eq3367bie6ux4onpi3vh2mr3k3lgu27sn",
    "period":30,
    "digits":6,
    "algorithm":"SHA-1"
}

然后我使用Android上的Google身份验证器创建了一个新的身份验证项。然后我“传输”或“导出”这个项,并在我的手机屏幕上获得了一个二维码。由于“安全性”,我无法截图。但可以用另一部相机拍照屏幕。

我将这个测试图像保存在这个项目中,命名为 image1.jpg

第一步从jpg中读取QR码

要从jpg中读取QR码,我将使用crate bardecoder。在我编辑图像使其干净、黑白且对比度良好、大约700x700像素之后,它才解码我的QR码。这是我本来不想接受的更多手动工作,但这并非不可能,并且只做一次。
这个jpg图像中的QR文本是

otpauth-migration://offline?data=CioKFbdJDe%2FfCgnqX45r0bqfTI7VtZqa%2FBILdGVzdGVyOnRlc3QgASgBMAIQARgBIAAo0tfy2Qc%3D

第二步从迁移代码中获取秘密

otpauth-migration中,Google放入了账户、发行者和秘密。我需要提取这些。我尝试了一些现有的crate,但没有成功。

注意:双因素认证代码是秘密,你应该像对待秘密一样对待它们!
https://alexbakker.me/post/parsing-google-auth-export-qr-code.html

首先我们需要解码base64。这不难。但然后我们有一个全新的“protobuf”协议缓冲消息。

Protobuf

协议缓冲是Google创建的一种语言无关、平台无关的可扩展机制,用于序列化结构化数据。他们声称它具有高性能和效率,比json和xml更好。他们不是通用的编码器/解码器,而是为每个特定的proto消息准备优化代码。他们为20种语言创建了代码生成器,但没有为Rust创建。有一个名为prost的crate,看起来它可以从.proto定义生成Rust代码。我创建了一个名为code_generator的子项目,用于从模式生成Rust代码。
生成的Rust代码被复制到gauth_migration_proto_mod.rs

第三步生成OTP

当我有了种子秘密,就很容易使用crate totp-rs生成TOTP。

自动化助手

我使用我的crate cargo-auto来编写自动化任务,如构建、发布、文档、测试等。所有这些都是用Rust代码完成的。很酷。从以下开始

cargo auto

然后按照详细的说明进行。然后继续使用明确的命令

cargo auto build

开源且免费如啤酒

我的开源项目免费如啤酒(MIT许可证)。

我简直热爱编程。

但是我也需要喝酒。如果你觉得我的项目和教程有用,请通过我的 paypal 赠送我一杯啤酒。

你知道你当地酒吧啤酒的价格;(-)所以我可以为了你的健康喝免费啤酒:(-)

Na zdravje! Alla salute! Prost! Nazdravlje! 🍻

依赖关系

~17–27MB
~218K SLoC