Por que uma string codificada em base64 possui um sinal = no final

322

Eu sei o que base64é codificação e como calcular a base64codificação em c #, no entanto, eu já vi várias vezes que, quando converto uma string em base64, existe uma =no final.

Surgiram algumas perguntas:

  1. Uma base64string sempre termina com =?
  2. Por que um =apêndice é anexado no final?
santosh singh
fonte
9
Isso não tem absolutamente nada a ver com c #.
BoltClock
19
Na verdade, ele está relacionado ao c #, nem todos os idiomas incluem o =, por exemplo, muitas bibliotecas perl omitem o =, portanto, conhecer o ambiente que o usuário está usando é realmente relevante.
Jacob
Parece que isso o torna um método menos efetivo de ofuscação em alguns casos, pois é bastante detectável.
dgo 25/02
6
@ user1167442 Base64 não é para ofuscação. É para transportar dados binários (ou cadeias com unicode e outros caracteres especiais) como uma cadeia.
NH.

Respostas:

270

Serve como preenchimento .

Uma resposta mais completa é que uma string codificada em base64 nem sempre termina com a =, ela só termina com uma ou duas =se forem necessárias para preencher a string no comprimento apropriado.

Andrew Hare
fonte
3
"Um caso em que caracteres de preenchimento são necessários é concatenar vários arquivos codificados em Base64."
André Puel 30/11
1
@ AndréPuel: ressincronizar um único =seria suficiente. Se você deseja encontrar os limites de volta, um terminador sempre deve estar presente (e ainda é necessário apenas um caractere). O conceito estofamento toda a Base64 é apenas um brainfart ...
6502
5
Esse link é completamente irrelevante para o base64.
NH.
1
Eu só gostaria que um link relevante e confiável fosse publicado, explicando o preenchimento de maneira base64eficiente, com ilustrações e exemplos. O link atual para a wikipedia é absolutamente irrelevante como @NH. mencionado.
precisa saber é o seguinte
1
@ Fr0zenFyr Se você quiser um link, en.wikipedia.org/wiki/Base64#Output_padding é muito bom. Mas a resposta de Badr é realmente melhor (ela ainda não chegou aos votos).
NH.
313

1-Não

2- Como resposta curta: O 65º caractere (sinal "=") é usado apenas como complemento no processo final de codificação de uma mensagem.

Você não terá um sinal de '=' se a sua string tiver um número múltiplo de 3 caracteres, porque a Base64codificação usa cada três bytes (8 bits) e os representa como quatro caracteres imprimíveis no padrão ASCII.

Detalhes:

(a) Se você deseja codificar

ABCDEFG <=> [ ABC] [ DEF] [G

Base64lidará (produzindo 4 caracteres) com o primeiro bloco e o segundo (à medida que estiverem completos), mas, para o terceiro, adicionará um dobro ==na saída para concluir os 4 caracteres necessários. Assim, o resultado será QUJD REVG Rw == (sem espaço)

(b) Se você deseja codificar ...

ABCDEFGH <=> [ ABC] [ DEF] [GH

Da mesma forma, ele adicionará apenas um =no final da saída para obter 4 caracteres, o resultado será QUJD REVG R0g = (sem espaço)

Badr Bellaj
fonte
26
Isso é mais completo e claro do que outras respostas e até a Wikipedia e deve merecer mais votos do que a resposta aceita, que não faz nada além de apontar para o link da Wikipedia. Parabéns a você! Voto a favor!
ANewGuyInTown 30/01
2
@ANewGuyInTown o link da wikipedia na solução aceita está incorreto, não tem nada a ver com preenchimento na base64. A página correta foi vinculada por Legolas em sua resposta abaixo
Fr0zenFyr
Outra boa resposta
spottedmahn 28/01
66

Da Wikipedia :

A sequência final '==' indica que o último grupo continha apenas um byte e '=' indica que continha dois bytes.

Portanto, isso é algum tipo de preenchimento.

Legolas
fonte
16
  1. Não.
  2. Para preencher a seqüência de caracteres codificada em Base64 para um múltiplo de 4 caracteres, para que ela possa ser decodificada corretamente.
Ian Kemp
fonte
3
Eu removi o =no final e testei isso para 1 milhão de strings. A decodificação sempre correspondia.
vivek_23 9/04/19
15

É definido no RFC 2045 como um caractere de preenchimento especial se menos de 24 bits estiverem disponíveis no final dos dados codificados.

iandotkelly
fonte
11

O sinal de igual (=) é usado como preenchimento em certas formas de codificação base64. O artigo da Wikipedia sobre base64 tem todos os detalhes.

Sam Holloway
fonte
2
Você poderia explicar a lógica de por que "==" tem 1 byte e "=" tem 2 bytes? Eu simplesmente não consigo entender. Como é que entra: "qualquer prazer carnal". poderia obter o resultado "YW55IGNhcm5hbCBwbGVhc3VyZS4 =", enquanto "qualquer prazer carnal" poderia obter o resultado "YW55IGNhcm5hbCVwc3VyZQ =="?
null
14
Não é o caso de '==' ter 1 byte e '=' ter 2 bytes. É o caso de você sempre ter um múltiplo de 4 bytes em toda a cadeia. Então, você preenche os sinais '=' até conseguir isso. A primeira string possui mais um caractere que a segunda, portanto, é necessário menos '=' de preenchimento.
Sam Holloway
2
Esta resposta deveria ser um comentário?
precisa saber é o seguinte
9

Está estofando. Em http://en.wikipedia.org/wiki/Base64 :

Em teoria, o caractere de preenchimento não é necessário para decodificação, pois o número de bytes ausentes pode ser calculado a partir do número de dígitos da Base64. Em algumas implementações, o caractere de preenchimento é obrigatório, enquanto em outras não é usado. Um caso em que os caracteres de preenchimento são necessários é concatenar vários arquivos codificados em Base64.

Thomas Leonard
fonte
1
A parte sobre "Um caso em que caracteres de preenchimento são necessários é concatenar vários arquivos codificados em Base64". está errado. Por exemplo, ao concatenar dois arquivos base64, em que os bytes de origem de cada arquivo têm 3 bytes, as cadeias base64 terão 4 caracteres e não terão bytes de preenchimento. Quando você concatena essas duas cadeias base64, não há como saber onde uma inicia e outra para com base na sequência concatenada. Portanto, confiar no preenchimento da base64 para ajudar com isso não vai funcionar. Esse problema existirá para qualquer arquivo com tamanho de bytes igualmente divisível por 3.
Ron C
1
Eu acho que significa o caso em que o resultado final deve ser a concatenação das entradas. por exemplo, decode(encode(A)+encode(B))=A+Bfunciona com preenchimento, mas não sem.
Thomas Leonard
talvez, mas esse uso limitado não permita que o (s) caractere (s) de preenchimento (s) sejam invocados no caso geral de separar cadeias codificadas quando as cadeias codificadas são concatenadas juntas. Eu apenas o mencionei para ajudar os desenvolvedores que podem estar pensando que podem usá-lo dessa maneira.
Ron C
1
Acho que sua objeção realmente apenas destaca a diferença entre os conceitos de preenchimento e delimitação. Geralmente, não se espera que os resultados da concatenação incluam informações suficientes para torná-las reversíveis. Você não saberá se "c3dpenpsZXJz" era originalmente "c3dpenps" + "ZXJz" ou "c3dp" + "enpsZXJz". Mas você também não sabe se "swizzlers" era originalmente "swi" + "zzlers" ou "swizzl" + "ers".
precisa
1
Copiar meu comentário de uma resposta relacionada ao preenchimento do Base64 :> A concatenação do Base64 [com preenchimento '='] permite que os codificadores processem grandes pedaços em paralelo, sem o ônus de alinhar os tamanhos dos pedaços a um múltiplo de três. Da mesma forma, como um detalhe de implementação, pode haver um codificador por aí que precisa liberar um buffer de dados interno de um tamanho que não seja múltiplo de três.
Andre D
7

http://www.hcidata.info/base64.htm

Codificando "Mary had" para a Base 64

Neste exemplo, estamos usando uma string de texto simples ("Mary had"), mas o princípio é válido independentemente dos dados (por exemplo, arquivo gráfico). Para converter cada 24 bits de dados de entrada em 32 bits de saída, a codificação Base 64 divide os 24 bits em 4 pedaços de 6 bits. O primeiro problema que notamos é que "Mary tinha" não é um múltiplo de 3 bytes - tem 8 bytes. Por esse motivo, o último grupo de bits tem apenas 4 bits. Para remediar isso, adicionamos dois bits extras de '0' e lembramos desse fato colocando um '=' no final. Se a sequência de texto a ser convertida na Base 64 tivesse 7 bytes, o último grupo teria 2 bits. Nesse caso, teríamos acrescentado quatro bits extras de '0' e lembrado desse fato colocando '==' no final.

Dev
fonte