Pull to refresh

Base64, Base32 и Base16 кодировки в .NET

Reading time3 min
Views7.9K

BaseN кодировка

BaseN кодировки используются для кодирования двоичных данных в текстовый вид. Где N это размер текстового алфавита используемого для кодирования. Применяются BaseN кодировки для "подготовки данных" к передаче по текстовым протоколам (HTTP, SMTP) или нецифровым каналам (напр. печать на бумаге).

Самый популярный вариант такой кодировки это Base64. Сравниться по частоте применения может только Base16 известный как hexadecimal или просто hex. Инструменты для работы с ними есть в .NET еще с первых версий, но они не очень удобные.

Что есть в .NET Framework (Core)

System.Security.Cryptography

ToBase64Transform/FromBase64Transform

Пара классов для преобразования в/из Base64. С помощью вспомогательного класса CryptoStream его можно использовать для потоковой обработки Stream.

using System.Security.Cryptography;

var base64Transform = new ToBase64Transform();
var output = new MemoryStream();
var base64Encoder = new CryptoStream(output, base64Transform, CryptoStreamMode.Write);

base64Encoder.Write(new byte[] { 122 }, 0, 1);
base64Encoder.Close();
// output.ToArray() -> byte[4] { 101, 103, 61, 61 } aka "eg=="

System.Convert

ToBase64String/FromBase64String

Пара функции для преобразования массива байтов в Base64 строку и обратно.

using System;

var bytes = System.Convert.FromBase64String("eg==")
// bytes -> 122

System.BitConverter

BitConverter.ToString

Функция преобразования массива байтов в Base16 (hexadecimal) строку, где каждый байт разделен дефизом. Пример: 0A-C0-D3

using System;

var hexString = BitConverter.ToString(new byte[] { 122, 122 });
// hexString -> "7A-7A"

System.Runtime.Remoting.Metadata.W3cXsd2001

SoapHexBinary (Framework-only)

Класс позволяющий преобразовывать массив байтов в Base16 (hexadecimal) строку и обратно.

using System.Runtime.Remoting.Metadata.W3cXsd2001;

var result = SoapHexBinary.Parse("A012");
// result.Value -> byte[];

System.Buffers.Text

Base64 (Core or System.Memory package)

Удобный класс для работы Base64 в режиме потока. Можно толкать Span'ы с байтами и получать результат в свой Span байтов.

Что предлагает Nuget

Multiformats.Base - Base2, 8, 16, 32, 58, 64 (+variants), MIT

Удобная библиотека с очень большим набором вариантов BaseN кодировок. Простое API и есть тесты. Из недостатков: он работает только с массивами.

SimpleBase - Base16, 32, 58, 85 (+variants), streaming, span, Apache-2

Библитека с большим набором BaseN кодировок. Есть поддержка .NET Core и работа со Span'ами. Простое API, есть тесты.

Пакет deniszykov.BaseN

Конечно у всех этих классов и библиотек есть фатальный недостаток.

Помимо этого, большинство бросило поддержку .NET Framework 4.5.

С точки зрения фичей, только класс Base64 умеет в Span<byte> to Span<byte> преобразования (везде это char[] <-> byte[] преобразования). А это частый кейс, когда данные приходят из сети. Эти данные не могут быть "интерпретированы" из byte в char по тому, что char занимает 2 байта в памяти. Т.е. для их преобразования, вышеописанными библиотеками, требуется скопировать их во временный буфер вдвое большего размера чем исходные данные.

В этом пакете функции кодирования/декодирования принимают разные типы входящих данных:

  • byte[]

  • char[]

  • string

  • byte*

  • char*

  • Span<byte>

  • Span<char>

Все это лежит внутри двух классов BaseNDecoder/BaseNEncoder.

Поддерживаются следующие словари кодирования:

  • Base16 (hexadecimal/lower/upper)

  • Base32

  • ZBase32

  • Base64

  • Base64 Url-safe

using deniszykov.BaseN;

var bytes = Base64Convert.ToBytes("eg==");
// bytes[0] -> 122

Более богатый набор предлагает класс BaseNEncoding который реализует System.Text.Encoding.

using deniszykov.BaseN;

var count = BaseNEncoding.Base64Url.GetByteCount("eg=="); // -> 1
var bytes = BaseNEncoding.Base64Url.GetBytes("eg=="); // -> 122

var baseNEncoder = new BaseNEncoder(BaseNAlphabet.Base64Alphabet);
var input = "eg==";
var output = new byte[1024];
baseNEncoder.Convert(input, 0, 4, output, 0, 1, true, out var charsUsed, out var bytesUsed, out var completed);
// output[0] -> 122

Другие примеры "простого" использования лежат тут. Можно использовать свой словарь. Сложных примеров не будет, те кому это надо могут найти их в тестах :)

Install-Package deniszykov.BaseN

Tags:
Hubs:
Total votes 9: ↑7 and ↓2+5
Comments21

Articles