【问题标题】:encode / decode binary data in a qr-code using qrencode and zbarimg in bash在 bash 中使用 qrencode 和 zbarimg 对二维码中的二进制数据进行编码/解码
【发布时间】:2020-03-03 11:26:34
【问题描述】:

我有一些二进制数据,我想在二维码中编码然后能够解码,所有这些都在 bash 中。搜索后,看起来我应该使用qrencode 进行编码,使用zbarimg 进行解码。经过一番故障排除后,我仍然无法解码我编码的内容

知道为什么吗?目前我最接近解决方案的是:

$ dd if=/dev/urandom bs=10 count=1 status=none > data.bin
$ xxd data.bin
00000000: b255 f625 1cf7 a051 3d07                 .U.%...Q=.
$ cat data.bin | qrencode -l H -8 -o data.png
$ zbarimg --raw --quiet data.png | xxd
00000000: c2b2 55c3 b625 1cc3 b7c2 a051 3d07 0a    ..U..%.....Q=..

看起来我不是很远,但仍有一些事情发生。

编辑 1:一种可能的解决方法是使用 base64 包装,如@leagris 的回答中所述。

编辑 2:使用 base64 编码会使消息的大小加倍。我首先使用二进制的原因是为了节省大小,所以我想避免这种情况。不接受@leagris 的答案,因为我希望它是“完整的二进制”,抱歉。

编辑 3:截至 2020 年 3 月 3 日,这似乎是 zbarimg 的一个众所周知的问题,并且正在提出解决此问题的拉取请求:

https://github.com/mchehab/zbar/pull/64

编辑 4:如果您知道 Linux 上的另一个命令行工具能够解密具有二进制内容的二维码,请随时告诉我。

【问题讨论】:

    标签: bash binary decode qr-code encode


    【解决方案1】:

    我的拉取请求是applied。 ZBarversion 0.23.1 及更新版本将能够解码二进制二维码:

    zbarimg --raw --oneshot -Sbinary qr.png
    zbarcam --raw --oneshot -Sbinary
    

    二维码有多种编码模式。最简单、最常用和得到广泛支持的是适合简单文本的字母数字编码。字节编码允许在 QR 码中存储任意 8 位数据。 ECI 模式类似于 8 位模式,但具有额外的元数据,告诉解码器使用哪个字符集将二进制数据解码回文本。 Here's a list 的已知 ECI 值及其代表的字符编码。例如,当解码器遇到 ECI 26 模式 QR 码时,它知道将二进制数据解码为 UTF-8。

    qrencode 工具正确地完成了它的工作:它正在创建一个字节模式的二维码,其中包含您提供的数据作为其内容。问题是大多数解码器被明确设计为首先处理文本数据。原始二进制数据的检索充其量只是一个细节。

    zbar 库的当前版本会将字节模式 QR 码视为未知 ECI 模式 QR 码。 If a character set isn't specified, it will attempt to guess the encoding and convert the data to it. 这很可能会破坏二进制数据。正如您所指出的,我在issue #55 中提出了这个问题,一段时间后设法提交a pull request 来改进它。如果它被合并,库将具有binary 解码器选项,它将指示解码器返回原始二进制数据而不进行转换。数据处理的另一个来源是命令行工具倾向于在输出中添加换行符。 I submitted a pull request 允许用户阻止这种情况,它已经被合并了。

    zxing-cpp 库 will also try to guess the encoding of binary data in QR codes. cmets 建议 QR 码规范要求解码器选择编码而不指定默认值或允许它们返回原始二进制数据。为了实现这一点,the binary data is copied to a byte array 可以通过DecoderResult 访问。当我有空的时候,I intend to write zximg and zxcam tools 这个库支持二进制解码。

    始终可以将二进制数据编码为 base 64,并将结果编码为字母数字二维码。但是,base 64 编码会增加数据的大小,并且字母数字模式不允许使用 QR 码的最大容量。在评论中,您提到了您打算将二进制二维码用于:

    我想要一个包,以一种易于恢复的格式有效地转储一些 gpg 内容。

    这正是我试图通过拉取请求启用的确切用例:更易于恢复的paperkey。 4096 位 RSA 密钥可以直接以 8 位模式进行 QR 编码,但不能以字母数字模式作为 base 64 编码数据。

    【讨论】:

    • 是的,100% 同意,我也想要一个“更好的纸钥匙”:)
    • 顺便说一句 @MatheusMoreira 我正在研究我的纯 bash 小“二维码纸钥匙”。希望几天之内有一些看起来像东西的代码,到时我会告诉你的。
    • @Zorglub29 顺便说一下,--oneshot 功能很有用,即使您尝试按顺序读取多个条码。当您运行zbarcam 并将二维码放在相机前面时,它有可能会多次解码该二维码。这将导致数据在输出中重复,从而损坏您尝试恢复的文件。单次模式强制zbarcam 在准确读取一个条形码后终止,允许您在脚本尝试读取下一个条形码之前进行编程。这让您有时间准备下一个条形码。
    • 我开始使用“bash 包”来帮助在此处倾倒一系列二维码:github.com/jerabaul29/qrdump。它仍然非常原始/丑陋/功能失调,但我希望它会在几周内变得更好。我让你知道。
    • 我认为 qrdump 开始看起来很合理。随意评论 API 等,现在我有一个工作示例,计划是 1)稳定 API 2)重构内部代码。
    【解决方案2】:

    另请参阅:Storing binary data in QR codes

    看起来zbarimg 只支持可打印字符并添加换行符

    printf '%s' 'Hello World!' >data.bin
    xxd data.bin
    qrencode -l H -8 -o data.png -r data.bin
    zbarimg --raw --quiet data.png | xxd
    

    我认为更好更便携的选择是在 qr 编码之前对二进制数据进行 base64 编码。

    像这样:

    dd if=/dev/urandom bs=10 count=1 status=none > data.bin
    xxd data.bin
    base64 <data.bin | qrencode -l H -8 -o data.png
    zbarimg --raw --quiet data.png | base64 -d | xxd
    

    【讨论】:

    • 是的,我知道换行符,我想我可以写这对我来说不是问题。所以你认为问题在于 zbarimg 而不是 qrencode,听起来不错?
    • 这行得通,非常感谢 :) 一个小问题:你知道这里需要 base64 编码的“深层”解释是什么吗? :)
    • 生成的二进制二维码是正确的。错误在于zbar 错误地解码为字符串。由于许多解码器无法正确处理二进制,因此您的二进制 qr 代码将存在可移植性问题。请参阅我链接的帖子,该帖子解释了它可以通过修补 zbarimg 来完成。我不知道你的实施计划,但如果你有太多的数据,它不适合大小合适的二维码,你可能应该用二维码来代替记录 ID,并从数据库中的记录 ID 中检索长数据.
    • 好的,谢谢。我让它打开的时间长一点,希望有人知道答案/也许是另一个解码。我也会考虑看看解码,看看我是否可以修改一下。我想要一个包来有效地以一种易于恢复的格式转储一些 gpg 内容。有一些解决方案“在一定程度上”有效,但也不完全符合我的要求。这很快就会变成几 kB,因此大小很重要。
    猜你喜欢
    • 1970-01-01
    • 2011-01-30
    • 2014-08-09
    • 2012-03-19
    • 1970-01-01
    • 2011-11-02
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    相关资源
    最近更新 更多