Кодировка Base64 против кодировки Ascii85

Мой проект на работе использует сериализатор Jackson JSON для преобразования набора Java-объектов в строки для отправки их в службы REST.

Некоторые из этих объектов содержат конфиденциальные данные, поэтому я написал собственные сериализаторы для сериализации этих объектов в строки JSON, затем скопировал их, затем зашифровал их, используя AES;

Это превращает строки в байтовые массивы, поэтому я использую кодировщик Base64 в Apache commons кодек для преобразования байтовых массивов в строки. Пользовательские десериализаторы за интерфейсами REST обращают этот процесс в обратную сторону:

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

Base64 кодирование увеличивает размер вывода (шаг gzip в сериализации предназначен для того, чтобы помочь уменьшить это увеличение), поэтому я проверил Google, чтобы найти более эффективную альтернативу, которая привела меня к этому предыдущему потоку stackru, который вызывал кодировку Ascii85 как более эффективная альтернатива -

Base64 добавляет 33% к размеру вывода, Ascii85 добавляет 25% к размеру вывода.

Я нашел несколько реализаций Java Ascii85, например Apache pdfbox, но я немного опасаюсь использовать кодировку - кажется, что почти никто не использует или не реализует ее, что может просто означать, что Base64 имеет большую инерцию, или что вместо этого может означать, что есть некоторая странная проблема с Ascii85.

Кто-нибудь знает больше на эту тему? Есть ли проблемы с Ascii85, которые означают, что я должен использовать Base64 вместо этого?

3 ответа

Решение

Base64 намного более распространен. Разница в размере на самом деле не так уж значительна в большинстве случаев, и если вы добавите на уровне HTTP (который будет сжимать base64), а не в пределах вашей полезной нагрузки, вы вполне можете обнаружить, что разница полностью исчезает.

Есть ли проблемы с Ascii85, которые означают, что я должен использовать Base64 вместо этого?

Я бы настоятельно рекомендовал использовать base64 только потому, что он гораздо более распространен. Это в значительной степени канонический способ представления двоичных данных в виде текста (если, конечно, вы не хотите использовать hex).

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>

Вот соответствующий ASCII85 декодер AKA Base85 (для пользователя Qwerty) в JavaScript:

function decode_ascii85(a) {
  var c, d, e, f, g, h = String, l = "length", w = 255, x = "charCodeAt", y = "slice", z = "replace";
  for ("<~" === a[y](0, 2) && "~>" === a[y](-2), a = a[y](2, -2)[z](/\s/g, "")[z]("z", "!!!!!"), 
  c = "uuuuu"[y](a[l] % 5 || 5), a += c, e = [], f = 0, g = a[l]; g > f; f += 5) d = 52200625 * (a[x](f) - 33) + 614125 * (a[x](f + 1) - 33) + 7225 * (a[x](f + 2) - 33) + 85 * (a[x](f + 3) - 33) + (a[x](f + 4) - 33), 
  e.push(w & d >> 24, w & d >> 16, w & d >> 8, w & d);
  return function(a, b) {
    for (var c = b; c > 0; c--) a.pop();
  }(e, c[l]), h.fromCharCode.apply(h, e);
}
<input onKeyUp="result.innerHTML = decode_ascii85(this.value)" placeholder="insert encoded string here" type="text">
<p id="result"></p>
example: <xmp><~<+oue+DGm>@3BW*D/a<&+EV19F<L~></xmp>

Другие вопросы по тегам