4个版本
0.2.1 | 2023年10月21日 |
---|---|
0.2.0 | 2023年10月20日 |
0.1.1 | 2023年10月18日 |
0.1.0 | 2023年10月18日 |
919 在 命令行工具 中排名
每月下载 23 次
93KB
1K SLoC
totp-qr
命令行工具,用于从QR图像中提取otpauth字符串并生成相应的TOTP
为什么?我需要将之前保存的QR图像、截图和Google Authenticator导出图像中的文本SECRET编码导入到其他应用中(例如 KeePassXC,Proton Pass)
这个项目的动机始于密码管理。我对我的密码管理工具很满意,如 KeePassXC,pass,iTerm2密码管理器(现在不能没有它了),但我缺乏对TOTP参数和密码的可见性和便携性。
此工具使用
- 出色的 rqrr crate 从大多数图像类型中提取otpauth数据
- 反向工程 protobuf
- 的 file-format crate 对stdin进行分类
- 感谢 totp-rs 的简洁字节切片和 Algorithm Enum;两者都被使用。 MIT许可证
项目状态
- 等待解决 SIGPIPE 的一般CLI Unix工具以避免“broken pipe”。
- 解决方案是修改stdout并使用 writeln!(stdout)? 而不是 println!(),如下所示
pub fn reset_sigpipe() -> Result<(), Box<dyn std::error::Error>> {
#[cfg(target_family = "unix")]
{
use nix::sys::signal;
unsafe {
signal::signal(signal::Signal::SIGPIPE, signal::SigHandler::SigDfl)?;
}
}
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// behave like a typical unix utility
general::reset_sigpipe()?;
let mut stdout = io::stdout().lock();
...
TOTP-QR
在shell函数中使用totp-qr安全地查看令牌
- 安装
totp-qr
,例如cargo install totp-qr
或构建cargo install --path .
- 将您的QR图像收集到一个目录中
- 运行
scripts/mk-totp-func.sh 目录
- 检查、复制并添加到您的 ~/.bashrc
创建shell函数,操作步骤
图像目录包含2个示例二维码
- otpauth-totp-qr.jpg 包含1个账户: "otpauth://totp/..."
- otpauth-migration-qr.jpg 包含3个账户: "otpauth-migration://offline?data=..."
$> totp-qr --uri images/otpauth-totp-qr.jpg
otpauth://totp/Example:[email protected]?issuer=Example&period=30&secret=JBSWY3DPEHPK3PXP
$> totp-qr --uri images/otpauth-migration-qr.jpg
otpauth-migration://offline?data=Ci0KCkhlbGxvId6tvu8SEnRlc3QxQGV4YW1wbGUxLmNvbRoFVGVzdDEgASgBMAIKLQoKSGVsbG8h3q2%2B8BISdGVzdDJAZXhhbXBsZTIuY29tGgVUZXN0MiABKAEwAgotCgpIZWxsbyHerb7xEhJ0ZXN0M0BleGFtcGxlMy5jb20aBVRlc3QzIAEoATACEAIYASAA
otpauth数据应保持私密,可以使用 OpenSSL 加密数据(密码:foo)
$> totp-qr --uri images/* | openssl aes-256-cbc -e -pbkdf2 -a
enter AES-256-CBC encryption password:
Verifying - enter AES-256-CBC encryption password:
U2FsdGVkX18lfKZ20uQn/AcAWa85hUmcJzQ8mvS9JX0BJb7qVDddrCjbjPxagIw6
hwHeLBPWx1U0GbA7zszAYKNa6FB2I53ldNET/tnutUBNmQeuxqbiVH8A0or9Ni8+
Lj8onivfmaGzcBGGGMtz3wliD/LL+iUhkG+A2FZpIE2mIf9QdwofI9jSAhDhAW3y
d+AXZWWsHRRVs5MvIA++CcchKLG+FOza3fcBIt7RtqkdISQYDw+TgMGLN8NS5/ak
tk8PcuO+QfjmtNXh0/96mn5jYCGdD1NvioeDkwBu7883q2ChHXcOLRuPqqlJAR/2
T+DwgtEyCO5ZhQPn3nj9E1Gy1xXAm+4Yt8CueXvuBS5SJJLQd94Q+HT1SsyMhYB0
FGVb6YifAjV3Snsk3UO/60quJ8cfQxjDW5Pef/a0LjtMZL2d+jaYImFcLEMUrnlI
FRGDcbHR1oAmdonyuSNJBQ==
scripts/mk-totp-func.sh 加密URI并输出名为totp()的Bash函数
$> ./scripts/mk-totp-func.sh images/
enter AES-256-CBC encryption password:
Verifying - enter AES-256-CBC encryption password:
totp() {
openssl aes-256-cbc -d -pbkdf2 -a << EOF | totp-qr $1 | sort -t, -k2
U2FsdGVkX1+gVAFEnnQVFQVmzDUU47Sl6NIqFOAQaM85dspvn8gt2hueK272RRi4
vdWDBLsFeKM4qp7Jq2TSV2Lca2/29cwPcZtAVnaz02VbxO2m/e3b4RjB9AxjRk1R
iTPdTzG+BO2GYHjdz515Dc/N4+HD5UMVJr7yAsypdJ/ThRN3CWCjUYd3mAGx9/g7
0GCwTJ6psw4CtwbgL3hg66cZq9w43Wwj0P+S3eL87ueZRHHfr10hEtLTsJQLuRDl
479WZpzFFPTyrr3jVQFMqmhgEXKXf2VnFp4aLvCk6OKP93iQU3fE5aRWTEpQytYF
+F/AvpAQUnEOvAAivFFa2SBXZPHDscENzG16P0O8i3hWoyJizoAJIOMOPsA3HgMZ
1kxCFBnME1Pd1dlrSTsfhFNpjfbaURWxI5pwMS/fAKMIoRLWydeGJOukNIv+zPmI
PPJXNNa5fQP647srICuCnw==
EOF
}
整合所有内容
$> ./scripts/mk-totp-func.sh images/ >> ~/.bashrc
$> . ~/.bashrc
$> type -a totp
totp is a function
totp ()
{
openssl aes-256-cbc -d -pbkdf2 -a <<EOF |
...
EOF
totp-qr $1 | sort -t, -k2
}
提示:如果您正在使用Mac的 iTerm2,请查看 密码管理器(快捷键:⌥ ⌘ F)以提供密码
totp()按发行者排序显示令牌
$> totp
enter AES-256-CBC decryption password:
757676, Example
757676, Test1
255080, Test2
476239, Test3
使用totp -e查看账户详情作为JSON
$> totp -e | jq
enter AES-256-CBC decryption password:
[
{
"secret": "JBSWY3DPEHPK3PXP",
"issuer": "Test1",
"sha": "SHA1",
"digits": 6,
"period": 30
},
{
"secret": "JBSWY3DPEHPK3PXQ",
"issuer": "Test2",
"sha": "SHA1",
"digits": 6,
"period": 30
},
{
"secret": "JBSWY3DPEHPK3PXR",
"issuer": "Test3",
"sha": "SHA1",
"digits": 6,
"period": 30
},
{
"secret": "JBSWY3DPEHPK3PXP",
"issuer": "Example",
"sha": "SHA1",
"digits": 6,
"period": 30
}
]
使用totp -u查看URI
$> totp -u
enter AES-256-CBC decryption password:
otpauth-migration://offline?data=Ci0KCkhlbGxvId6tvu8SEnRlc3QxQGV4YW1wbGUxLmNvbRoFVGVzdDEgASgBMAIKLQoKSGVsbG8h3q2%2B8BISdGVzdDJAZXhhbXBsZTIuY29tGgVUZXN0MiABKAEwAgotCgpIZWxsbyHerb7xEhJ0ZXN0M0BleGFtcGxlMy5jb20aBVRlc3QzIAEoATACEAIYASAA
otpauth://totp/Example:[email protected]?issuer=Example&period=30&secret=JBSWY3DPEHPK3PXP
通用用法
Usage: totp-qr [OPTIONS] [FILES]...
Arguments:
[FILES]... image-file|stdin, filename of "-" implies stdin
Options:
-a, --auth <AUTH> "otpauth-migration://offline?data=..." or "otpauth://totp/...?secret=SECRET"
-v, --verbose Verbose output
-e, --export Export account information as JSON
-i, --import Import JSON accounts
-u, --uri Output extracted URI's
-h, --help Print help
-V, --version Print version
详细输出(-v, --verbose)
$> totp-qr -v images/*.jpg
otpauth = otpauth-migration://offline?data=Ci0KCkhlbGxvId6tvu8SEnRlc3QxQGV4YW1wbGUxLmNvbRoFVGVzdDEgASgBMAIKLQoKSGVsbG8h3q2%2B8BISdGVzdDJAZXhhbXBsZTIuY29tGgVUZXN0MiABKAEwAgotCgpIZWxsbyHerb7xEhJ0ZXN0M0BleGFtcGxlMy5jb20aBVRlc3QzIAEoATACEAIYASAA
237769, Account { secret: "JBSWY3DPEHPK3PXP", issuer: "Test1", sha: "SHA1", digits: 6, period: 30 }
734660, Account { secret: "JBSWY3DPEHPK3PXQ", issuer: "Test2", sha: "SHA1", digits: 6, period: 30 }
021109, Account { secret: "JBSWY3DPEHPK3PXR", issuer: "Test3", sha: "SHA1", digits: 6, period: 30 }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
otpauth = otpauth://totp/Example:[email protected]?issuer=Example&period=30&secret=JBSWY3DPEHPK3PXP
237769, Account { secret: "JBSWY3DPEHPK3PXP", issuer: "Example", sha: "SHA1", digits: 6, period: 30 }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
认证链接(-a, --auth)
$> totp-qr --auth="otpauth://totp/ACME%20Co:[email protected]?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30"
970700, ACME Co
从stdin解码
$> echo 'secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ' | totp-qr
970700,
$> totp-qr < images/otpauth-migration-qr.jpg
237769, Test1
734660, Test2
021109, Test3
导入(-i, --import)/导出(-e, --export)JSON账户
$> totp-qr -e images/*.jpg | totp-qr -iv
939954, Account { secret: "JBSWY3DPEHPK3PXP", issuer: "Test1", sha: "SHA1", digits: 6, period: 30 }
561818, Account { secret: "JBSWY3DPEHPK3PXQ", issuer: "Test2", sha: "SHA1", digits: 6, period: 30 }
787732, Account { secret: "JBSWY3DPEHPK3PXR", issuer: "Test3", sha: "SHA1", digits: 6, period: 30 }
939954, Account { secret: "JBSWY3DPEHPK3PXP", issuer: "Example", sha: "SHA1", digits: 6, period: 30 }
依赖项
~22MB
~186K SLoC