Base64 编码与 Ascii85 编码

2022-09-02 20:57:06

我的工作项目是使用 Jackson JSON 序列化程序将一堆 Java 对象转换为字符串,以便将它们发送到 REST 服务。

其中一些对象包含敏感数据,因此我编写了自定义序列化程序,将这些对象序列化为 JSON 字符串,然后对其进行 gzip,然后使用AES;

这会将字符串转换为字节数组,因此我在编解码器中使用 Base64 编码器将字节数组转换为字符串。REST 接口后面的自定义反序列化器可反转此过程:Apache commons

base64 decode -> decrypt -> decompress -> deserialize using default Jackson deserializer.

Base64编码增加了输出的大小(序列化中的gzip步骤旨在帮助改善这种增长),所以我检查了Google,看看是否有更有效的替代方案,这使我找到了之前的stackoverflow线程,该线程将Ascii85编码作为更有效的替代方案 -

Base64将 33% 添加到输出大小,将 25% 添加到输出大小。Ascii85

我发现了一些Java Ascii85实现,例如Apache pdfbox,但我对使用编码有点谨慎 - 似乎几乎没有人使用或实现它,这可能只是意味着Base64具有更多的惯性,或者这可能意味着Ascii85存在一些不稳定的问题。

有没有人知道更多关于这个主题?Ascii85 是否存在任何问题,这意味着我应该改用 Base64?


答案 1

Base64更常见。在大多数情况下,大小上的差异实际上并不那么明显,如果您在HTTP级别添加(这将压缩base64)而不是在您的有效负载添加,您可能会发现差异完全消失了。

Ascii85 是否存在任何问题,这意味着我应该改用 Base64?

我强烈建议使用base64,因为它更普遍。这几乎是将二进制数据表示为文本的规范方式(当然,除非您想使用十六进制)。


答案 2

ASCII85是一个很好的编码,可以用来节省额外的空间。但它输出了许多字符,如果通过HTTP天真地发送,则需要转义这些字符。Base64编码有一个变体,可以通过HTTP发送而无需任何转义。

这是一个javascript ASCII85编码器,以防有人需要尝试:

// By Steve Hanov. Released to the public domain.
function encodeAscii85(input) {
  var output = "<~";
  var chr1, chr2, chr3, chr4, chr, enc1, enc2, enc3, enc4, enc5;
  var i = 0;

  while (i < input.length) {
    // Access past the end of the string is intentional.
    chr1 = input.charCodeAt(i++);
    chr2 = input.charCodeAt(i++);
    chr3 = input.charCodeAt(i++);
    chr4 = input.charCodeAt(i++);

    chr = ((chr1 << 24) | (chr2 << 16) | (chr3 << 8) | chr4) >>> 0;

    enc1 = (chr / (85 * 85 * 85 * 85) | 0) % 85 + 33;
    enc2 = (chr / (85 * 85 * 85) | 0) % 85 + 33;
    enc3 = (chr / (85 * 85) | 0 ) % 85 + 33;
    enc4 = (chr / 85 | 0) % 85 + 33;
    enc5 = chr % 85 + 33;

    output += String.fromCharCode(enc1) +
      String.fromCharCode(enc2);
    if (!isNaN(chr2)) {
      output += String.fromCharCode(enc3);
      if (!isNaN(chr3)) {
        output += String.fromCharCode(enc4);
        if (!isNaN(chr4)) {
          output += String.fromCharCode(enc5);
        }
      }
    }
  }

  output += "~>";

  return output;
}
<input onKeyUp="result.innerHTML = encodeAscii85(this.value)" placeholder="write text here" type="text">
<p id="result"></p>