Z85 编码解码

将文本、十六进制字节或文件转换为 Z85,也可以反向解码。Z85 是 ZeroMQ 定义的 Base85 变体,其字母表可以直接放进源代码的字符串字面量中,无需转义。

完全在浏览器中运行,不会上传任何数据。

使用方法

  1. 选择“编码”把文本或字节转换为 Z85,或选择“解码”把 Z85 还原为数据。
  2. 处理密钥等二进制数据时,编码请把输入设为“十六进制”,解码请把输出设为“十六进制”。
  3. 输入、粘贴或打开文件,结果会随输入实时更新。
  4. 复制结果,或将结果下载为文件。

什么是 Z85?

Z85 由 ZeroMQ RFC 32 定义(这是 ZeroMQ 社区的规范,不是 IETF 的 RFC)。与其他 Base85 编码一样,它把每 4 个字节转换为 5 个字符:将每组字节按大端序读成一个 32 位整数,再从高位到低位写成 5 位 85 进制数。编码后体积增加 25%。

Z85 的特别之处在于字母表:0-9、a-z、A-Z 加上 23 个符号 .-:+=^!/*?&<>()[]{}@%$#。它没有使用单引号、双引号、反斜杠、反引号、逗号、分号、竖线、波浪号和下划线,这套字母表专为在源代码字符串中安全使用而设计,因此 Z85 编码结果可以直接放在 C、Python 或 JSON 的引号中,而不需要任何转义。

Z85 的使用场景

ZeroMQ 用 Z85 来表示 CurveZMQ 密钥。32 字节的公钥或私钥会编码成 40 个字符的 Z85 字符串,zmq_curve_keypair() 返回的就是这种形式,CURVE 安全机制的套接字选项也接受它。libzmq 还提供 zmq_z85_encode() 和 zmq_z85_decode(),pyzmq 等语言绑定中也有相同的函数。

// C(libzmq)
char text[41];                       // 32 字节 -> 40 个字符 + NUL
zmq_z85_encode(text, key, 32);

# Python(pyzmq)
from zmq.utils import z85
z85.encode(bytes.fromhex('864fd26fb559f75b'))   # b'HelloWorld'

最后一行是规范中给出的测试向量。

关于输入长度的说明

RFC 32 要求二进制输入的长度必须是 4 字节的整数倍,编码后的字符串长度必须是 5 的整数倍。规范没有定义填充,zmq_z85_encode() 等严格实现会拒绝其他长度。

本工具也接受其他长度,采用与 Ascii85 和 Base85 相同的规则:最后不足 4 字节的 n 个字节编码为 n + 1 个字符。这是非标准的扩展,这样得到的结果可能会被其他 Z85 解码器拒绝。如果需要兼容,请先把数据补齐到 4 字节的整数倍。CurveZMQ 密钥为 32 字节,本身就符合要求。

编码规格

字母表0-9 a-z A-Z .-:+=^!/*?&<>()[]{}@%$#
输出体积每 4 字节输出 5 个字符(125%)
填充无
标准ZeroMQ RFC 32
区分大小写是

编码示例

输入 (UTF-8)输出
Hello, World!nm=QNz.92jz/PV8aP
Base64.islsB}Dhz^42A@
你好<H}kFRm=

常见问题

Z85 和 Ascii85 有什么区别?
两者的计算方法相同,字母表不同。Ascii85 使用从 ! 到 u 的 ASCII 字符,其中包含引号和反斜杠,并有表示零字节的 z 缩写;Z85 避开了在字符串中需要转义的字符,也没有缩写。
Z85 有填充吗?

没有。规范只允许长度为 4 字节整数倍的输入。本工具对其他长度会用较短的最后一组进行编码,这不属于标准内容。

Z85 可以用在 JSON、XML 或 URL 中吗?
放进 JSON 字符串无需转义。在 XML 和 HTML 中,<、>、& 需要转义。Z85 不适合放进 URL,因为 ?、&、/、# 在 URL 中有特殊含义,这种场景请使用 Base64URL 或 Base58。
Z85 编码的 CurveZMQ 密钥有多长?

CurveZMQ 密钥为 32 字节,编码后正好是 40 个字符。如需查看原始密钥,可以在这里解码并选择十六进制输出。