Executando verificação de segurança...
1

Base 64 - matemática e c#

Encoding vs hashing

Base 64 e os outros "bases" citados são uma forma de encoding, isso é, transformar um dado em uma sequência de caracteres, diferente de hashing que é uma função unidirecional, ou seja, não é possível recuperar o dado original a partir do hash.

Com isso, também é nítido que são usados para propósitos diferentes, o encoding é usado geralmente para transmitir dados, enquanto o hashing é usado para verificar a integridade dos dados ou para armazenar senhas de forma segura.

Como similaridade, ambas são determinísticas, ou seja, o mesmo dado de entrada sempre resultará no mesmo resultado.

Princípios matemáticos de hashing e encoding

Encoding

O encoding pode ser representado matematicamente como uma função f: A \to B, onde A é o conjunto de dados originais e B é o conjunto de dados codificados. O encoding é invertível (bijetivo), ou seja:
\exists f^{-1} : B \to A \mid f^{-1}(f(x)) = x, \quad \forall x \in A
Em outras palavras, existe uma função inversa f^{-1} que, quando aplicada ao resultado de f, recupera o dado original x de forma íntegra. Portanto, a relação entre f e f^{-1} é de identidade: f^{-1}(f(x)) = x para todo x em A.

Hashing

O hashing pode ser representado matematicamente como uma função h: A \to B, onde A é o conjunto de dados originais e B é o conjunto de hashes. O hashing é unidirecional (one-way), o que implica que não existe uma função inversa h^{-1} capaz de reverter o processo para todos os elementos:
\nexists f : B \to A \mid f(h(x)) = x, \quad \forall x \in A
Diferente do encoding, o hashing não é uma função injetora. Como o conjunto de destino B é finito e geralmente menor que o conjunto de origem A (|B| < |A|), aplica-se o Princípio da Casa dos Pombos, permitindo a existência de colisões:
\exists x_{1}, x_{2} \in A \mid x_{1} \n eq\ x_{2} \land h(x_{1}) = h(x_{2})
Portanto, a operação de inversão é logicamente impossível, pois um único hash b \in B pode estar associado a múltiplos valores de origem em A, tornando a recuperação do dado original x ambígua e computacionalmente inviável.

Base 64

Base 64 é um sistema de codificação que representa dados binários em formato de texto usando um conjunto de 64 caracteres. Ele é amplamente utilizado para transmitir dados binários, como imagens, arquivos e outros tipos de dados, em formatos que só aceitam texto, como e-mails e URLs.

É chamado de 64, pois existem 64 caracteres possíveis para representar os dados codificados. Cada caractere representa um valor de 6 bits, o que significa que cada grupo de 3 bytes (24 bits) é codificado em 4 caracteres de base 64.

Os caracteres são:

  • Letras maiúsculas (A-Z)
  • Letras minúsculas (a-z)
  • Dígitos (0-9)
  • Símbolos (+ e /)

Matematicamente, temos:

\frac{24 \text{ bits}}{8 \text{ bits/byte}} = 3 \text{ bytes}
\frac{24 \text{ bits}}{6 \text{ bits/caractere}} = 4 \text{ caracteres}

E isso explica o aumento de 33% no tamanho dos dados codificados em base 64, já que cada grupo de 3 bytes é representado por 4 caracteres.

Uso em c#

Imagine o cenário em que você tem um arquivo de imagem e deseja transmiti-lo por algum canal que só aceite texto. Você pode usar o base64 para codificar o arquivo de imagem em uma string de texto, que pode ser facilmente transmitida e depois decodificada para recuperar a imagem original.


string imagePath = "caminho/para/sua/imagem.jpg";

byte[] imageBytes = File.ReadAllBytes(imagePath);

//checar o tamanho do arquivo
Console.WriteLine($"Tamanho do arquivo original: {imageBytes.Length} bytes");

string base64String = Convert.ToBase64String(imageBytes);

//checar o tamanho do arquivo codificado
Console.WriteLine($"Tamanho do arquivo codificado: {base64String.Length} caracteres");


Console.WriteLine("Imagem codificada em Base 64:");
Console.WriteLine(base64String);


//razao de aumento de tamanho
double increaseRatio = (double)base64String.Length / imageBytes.Length;
Console.WriteLine($"Aumento de tamanho: {increaseRatio:P2}");

byte[] decodedBytes = Convert.FromBase64String(base64String);

File.WriteAllBytes("caminho/para/sua/imagem_decodificada.jpg", decodedBytes);

Base 64 na URL

Base 64 URL é uma variação do base 64 que é projetada para ser segura para uso em URLs e nomes de arquivos. Ele substitui os caracteres '+' e '/' por '-' e '_', respectivamente, para evitar problemas de codificação em URLs.

Isso é, se usássemos o base 64 normal em uma URL, os caracteres '+' e '/' poderiam ser interpretados de forma errada, causando problemas na transmissão dos dados. Com a base 64 URL, esses caracteres são substituídos por '-' e '_', garantindo que a string codificada seja segura para uso em URLs.

O .NET 9 introduziu suporte nativo para base 64 URL, o que facilita a codificação e decodificação de dados usando esse formato.

string imagePathUrl = "dummy.jpg";
byte[] imageBytesUrl = File.ReadAllBytes(imagePathUrl);

string base64UrlString = Base64Url.EncodeToString(imageBytes);

Console.WriteLine($"Tamanho original: {imageBytes.Length} bytes");
Console.WriteLine($"Tamanho Base64Url: {base64UrlString.Length} caracteres");

//razao de aumento de tamanho
double increaseRatioUrl = (double)base64UrlString.Length / imageBytesUrl.Length;
Console.WriteLine($"Aumento de tamanho do base64Url: {increaseRatio:P2}");

// 2. Decodificar (Lida com a falta de '=' e caracteres de URL sem erro)
byte[] decodedUrlBytes = Base64Url.DecodeFromChars(base64UrlString);

File.WriteAllBytes("imagem_url.jpg", decodedUrlBytes);

Outras bases

Além do base 64 e base 64 URL, existem outras variações de codificação em diferentes bases, como base 62, base 58, entre outras. Cada uma delas tem suas próprias características e usos específicos, dependendo do contexto em que são aplicadas.

Base 62

O base62, por exemplo, é uma variação que utiliza um conjunto de 62 caracteres (letras maiúsculas, minúsculas e dígitos) para codificar dados. Ela é preferida em situações que exigem uma representação totalmente alfanumérica.

Base 58

Já o base 58 é uma variação que utiliza um conjunto de 58 caracteres (letras maiúsculas, minúsculas e dígitos, mas sem os caracteres '0', 'O', 'I' e 'l' para evitar confusões) para codificar dados. Ele é frequentemente usado em sistemas de criptomoedas para representar endereços de carteira de forma mais legível, evitando caracteres que possam ser confundidos visualmente.

Base 85

O base 85 é outra variação que utiliza um conjunto de 85 caracteres para codificar dados. Ele é mais eficiente do que o base 64 em termos de compactação, mas pode ser menos legível e mais difícil de transmitir em alguns contextos.

Carregando publicação patrocinada...
1

Como as bases 62 e 58 são mais compactas? Em que sentido?

S2


Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente (não vendo nada, é retribuição na minha aposentadoria) (links aqui).

1

Passou batido a parte do base62 ser mais compacta, era pra significar que são mais compactas em relação a bases menores, binarias, hexadecimais etc. Quanto ser mais compactas do que a base64 isso não é verdade, ela é menos compacta que a base64, porque cada caractere representa menos bits, e portanto apenas bases maiores que a base64 são mais compactas que ela, pois cada caractere consegue representar mais bits

1

Ah, você não leu o que a IA gerou? Ou leu e não entendeu que isso era errado?

Eu gosto de ver essas coisas porque mostra o buraco que a sociedade está se enfiando.

1

Essa parte passou batido, ué, meu trabalho não é escrever pro tabnews, estou documentando para aprender (no meu tempo livre, que é curto). Se você faz de alguma outra forma, bom pra você.

1

Não impede que você vá escrevendo aos poucos em algum arquivo .txt então copiar e colcar aqui. Conteúdo gerado por IA é muito mal aceito por aqui (com razão)

1

Cara, pior que nao escrevi com IA, claro que utilizei para algumas coisas, mas minha principal fonte de referencia foi o livro "C# 13 and .NET 9 – Modern Cross-Platform Development Fundamentals"

0