입력 길이를 3으로 나눌 수없는 경우 base64 인코딩에 패딩이 필요한 이유는 무엇입니까?


101

base64 인코딩에서 패딩의 목적은 무엇입니까? 다음은 wikipedia에서 발췌 한 것입니다.

"인코딩 된 출력을 4 개의 정수 배수로 강제하는 데 사용할 수있는 추가 패드 문자가 할당됩니다 (또는 인코딩되지 않은 이진 텍스트가 3 바이트의 배수가 아닌 경우). 이러한 패딩 문자는 디코딩 할 때 삭제되어야하지만 입력 이진 길이가 3 바이트의 배수가 아닐 때 인코딩되지 않은 텍스트의 유효 길이를 계산할 수 있습니다 (패드가 아닌 마지막 문자는 일반적으로 마지막 6 비트 블록이 0이되도록 인코딩됩니다.) -최하위 비트에 패딩 된 경우 인코딩 된 스트림의 끝에 최대 2 개의 패딩 문자가 나타날 수 있습니다. "

나는 모든 문자열을 base64로 인코딩하고 base64로 인코딩 된 문자열을 디코딩 할 수있는 프로그램을 작성했습니다. 패딩으로 해결되는 문제는 무엇입니까?

답변:


210

패딩이 불필요하다는 결론은 옳습니다. 인코딩 된 시퀀스의 길이에서 입력 길이를 명확하게 결정할 수 있습니다.

그러나 패딩은 예를 들어 매우 간단한 네트워크 프로토콜에서 발생할 수있는 것처럼 개별 시퀀스의 길이가 손실되는 방식으로 base64로 인코딩 된 문자열이 연결되는 상황에서 유용합니다.

경우 패딩되지 문자열 연결됩니다, 각 개별 시퀀스의 끝에서 홀수 바이트의 수에 대한 정보가 손실되기 때문에 원래의 데이터를 복구하는 것은 불가능하다. 그러나 패딩 된 시퀀스를 사용하면 모호함이 없으며 시퀀스 전체를 올바르게 디코딩 할 수 있습니다.

편집 : 일러스트레이션

단어를 base64로 인코딩하고 연결하여 네트워크를 통해 보내는 프로그램이 있다고 가정합니다. "I", "AM"및 "TJM"을 인코딩하고 패딩없이 결과를 함께 끼워 전송합니다.

  • ISQ( SQ==패딩 포함)로 인코딩
  • AMQU0( QU0=패딩 포함)로 인코딩
  • TJMVEpN( VEpN패딩 포함)로 인코딩

따라서 전송 된 데이터는 SQQU0VEpN. 수신자 base64 I\x04\x14\xd1Q)는 의도 한 IAMTJM. 보낸 사람이 인코딩 된 시퀀스에서 각 단어가 끝나는 위치에 대한 정보를 파괴 했기 때문에 결과는 말도 안됩니다 . 발신자가 SQ==QU0=VEpN대신 전송했다면 수신자는 이를 3 개의 별도 base64 시퀀스로 디코딩하여 IAMTJM.

패딩을 사용하는 이유는 무엇입니까?

왜 각 단어 앞에 정수 길이를 붙이도록 프로토콜을 설계하지 않습니까? 그러면 수신기가 스트림을 올바르게 디코딩 할 수 있으며 패딩이 필요하지 않습니다.

인코딩을 시작하기 전에 인코딩 할 데이터의 길이를 알고 있는 한 좋은 생각 입니다. 하지만 말 대신 라이브 카메라에서 비디오 덩어리를 인코딩한다면 어떨까요? 각 청크의 길이를 미리 알지 못할 수도 있습니다.

프로토콜이 패딩을 사용했다면 길이를 전혀 전송할 필요가 없습니다. 데이터는 카메라에서 들어온대로 인코딩 될 수 있으며, 각 청크는 패딩으로 종료되며 수신기는 스트림을 올바르게 디코딩 할 수 있습니다.

분명히 그것은 매우 인위적인 예이지만 아마도 패딩이 일부 상황에서 왜 도움이 될 수 있는지 설명합니다.


22
+1 "설명 할 수없는 이유에 대한 자세한 내용과 중복성을 좋아하기 때문에"외에 실제로 합리적인 답변을 제공하는 유일한 답변입니다.
유효하지 않은

1
이것은 명확하게 인코딩 된 청크에 대해 정상적으로 작동하지만 디코딩 후 불가분하게 연결될 것으로 예상됩니다. U0FNSQ == QU0 =을 보내면 문장을 재구성 할 수 있지만 문장을 구성하는 단어를 잃게됩니다. 없는 것보다 낫다. 특히 GNU base64 프로그램은 연결된 인코딩을 자동으로 처리합니다.
마르셀 칸토

2
단어의 길이가 3의 배수이면 어떻게됩니까? 이 멍청한 연결 방법은 패딩 제거가 아니라 정보 (단어 끝)를 파괴합니다.
GreenScape

2
Base64 연결을 사용하면 인코더가 청크 크기를 3의 배수로 정렬하는 부담없이 병렬로 큰 청크를 처리 할 수 ​​있습니다. 마찬가지로 구현 세부 사항으로 3의 배수가 아닌 크기의 내부 데이터 버퍼를 플러시해야하는 인코더가있을 수 있습니다.
앙드레 D

1
이 답변을 통해 "SQ == QU0 = VEpN"과 같은 것을 디코더에 제공하여 디코딩 할 수 있다고 생각할 수 있습니다. 실제로는 할 수없는 것 같습니다. 예를 들어 javascript 및 php의 구현은이를 지원하지 않습니다. 연결된 문자열로 시작하여 한 번에 4 바이트를 디코딩하거나 문자를 채운 후 문자열을 분할해야합니다. 이러한 구현은 문자열 중간에 있더라도 패딩 문자를 무시하는 것처럼 보입니다.
Roman

38

관련 메모에서 내가 만든 임의의 기본 변환을위한 기본 변환기가 있습니다. 즐겨! https://convert.zamicol.com/

패딩 문자 란 무엇입니까?

패딩 문자는 길이 요구 사항을 충족하고 의미가 없습니다.

패딩의 10 진수 예 : 임의의 요구 사항이 모든 문자열의 길이가 8자인 경우 숫자 640은 "00000640"이라는 의미가 없기 때문에 선행 0을 패딩 문자로 사용하여이 요구 사항을 충족 할 수 있습니다.

바이너리 인코딩

바이트 패러다임 : 바이트는 사실상 표준 측정 단위이며 모든 인코딩 체계는 바이트와 다시 관련되어야합니다.

Base256 은이 패러다임에 정확히 맞습니다. 1 바이트는 base256의 한 문자와 같습니다.

16 진수 또는 16 진수 인 Base16 은 각 문자에 4 비트를 사용합니다. 1 바이트는 2 개의 base16 문자를 나타낼 수 있습니다.

Base64 는 base256 및 base16과 달리 바이트 패러다임에 균등하게 맞지 않습니다 (base32도 마찬가지). 모든 base64 문자는 전체 바이트보다 2 비트 짧은 6 비트로 표현할 수 있습니다.

base64 인코딩 대 바이트 패러다임을 분수로 나타낼 수 있습니다. 문자 당 6 비트, 바이트 당 8 비트 . 이 부분을 줄이면 4 자 이상 3 바이트입니다.

이 비율 (base64 문자 4 개당 3 바이트)은 base64를 인코딩 할 때 따르려는 규칙입니다. Base64 인코딩은 모든 바이트가 자체적으로 서있을 수있는 base16 및 base256과 달리 3 바이트 번들로만 측정 할 수 있습니다.

그렇다면 패딩 문자없이 인코딩이 잘 작동하더라도 패딩이 권장되는 이유 는 무엇입니까?

스트림의 길이를 알 수 없거나 데이터 스트림이 종료되는시기를 정확히 아는 것이 도움이 될 수있는 경우 패딩을 사용하십시오. 패딩 문자는 이러한 추가 스팟이 비어 있어야하며 모호함을 배제한다는 것을 명시 적으로 전달합니다. 패딩으로 길이를 알 수 없더라도 데이터 스트림이 끝나는 위치를 알 수 있습니다.

카운터 예로서 JOSE 와 같은 일부 표준 은 패딩 문자를 허용하지 않습니다. 이 경우 누락 된 항목이 있으면 암호화 서명이 작동하지 않거나 base64가 아닌 다른 문자 (예 : ".")가 누락됩니다. 길이에 대한 가정은 없지만, 뭔가 잘못되면 단순히 작동하지 않기 때문에 패딩이 필요하지 않습니다.

이것이 바로 base64 RFC가 말하는 것입니다.

경우에 따라 기본 인코딩 데이터에서 패딩 ( "=")을 사용할 필요가 없거나 사용되지 않습니다. 일반적으로 전송되는 데이터의 크기에 대한 가정을 할 수없는 경우 올바른 디코딩 된 데이터를 생성하기 위해 패딩이 필요합니다.

[...]

Base 64의 패딩 단계 [...]가 부적절하게 구현되면 인코딩 된 데이터가 중요하지 않게 변경됩니다. 예를 들어 입력이 기본 64 인코딩에 대해 하나의 옥텟 인 경우 첫 번째 심볼의 모든 6 비트가 사용되지만 다음 심볼의 처음 두 비트 만 사용됩니다. 이러한 패드 비트는 인코더를 준수하여 0으로 설정해야합니다. 이는 아래 패딩에 대한 설명에 설명되어 있습니다. 이 속성이 유지되지 않으면 기본 인코딩 된 데이터의 표준 표현이 없으며 여러 기본 인코딩 된 문자열을 동일한 이진 데이터로 디코딩 할 수 있습니다. 이 속성 (및이 문서에서 설명하는 다른 항목)이 유지되면 표준 인코딩이 보장됩니다.

패딩을 사용하면 손실 된 비트가 없다는 약속으로 base64 인코딩을 디코딩 할 수 있습니다. 패딩이 없으면 더 이상 3 바이트 번들로 측정하는 것에 대한 명시적인 승인이 없습니다. 패딩이 없으면 일반적으로 스택의 다른 곳 (예 : TCP, 체크섬 또는 기타 방법)에서 추가 정보 없이는 원래 인코딩의 정확한 재현을 보장 할 수 없습니다.

다음은 RFC 4648 양식의 예입니다 ( http://tools.ietf.org/html/rfc4648#section-8 ).

"BASE64"함수 내의 각 문자는 1 바이트 (base256)를 사용합니다. 그런 다음이를 base64로 변환합니다.

BASE64("")       = ""           (No bytes used. 0%3=0.)
BASE64("f")      = "Zg=="       (One byte used. 1%3=1.)
BASE64("fo")     = "Zm8="       (Two bytes. 2%3=2.)
BASE64("foo")    = "Zm9v"       (Three bytes. 3%3=0.)
BASE64("foob")   = "Zm9vYg=="   (Four bytes. 4%3=1.)
BASE64("fooba")  = "Zm9vYmE="   (Five bytes. 5%3=2.)
BASE64("foobar") = "Zm9vYmFy"   (Six bytes. 6%3=0.)

다음은 사용할 수있는 인코더입니다. http://www.motobit.com/util/base64-decoder-encoder.asp


16
-1 숫자 체계가 어떻게 작동하는지에 대한 훌륭하고 철저한 게시물이지만 인코딩 없이도 완벽하게 작동 할 때 패딩이 사용되는 이유를 설명하지 않습니다 .
Matti Virkkunen 2014

2
질문도 읽었습니까? 올바르게 디코딩하기 위해 패딩이 필요 하지 않습니다 .
Navin 2015

3
나는이 답변이 실제로 여기에 명시된 이유를 설명했다고 생각합니다. "추가 정보 없이는 더 이상 원본 인코딩의 정확한 복제를 보장 할 수 없습니다." 정말 간단합니다. 패딩은 완전한 인코딩을 받았음을 알려줍니다. 3 바이트가있을 때마다 계속해서 디코딩해도 괜찮다고 가정 할 수 있습니다. 걱정할 필요가 없습니다. 윙윙 거리는 소리 ... 아마도 인코딩을 변경하는 데 1 바이트가 더 올 것입니다.
디디에 A.

@DidierA. base64 하위 문자열에 3 바이트가 더 없다는 것을 어떻게 알 수 있습니까? 를 디코딩하려면 char*문자열 크기 또는 null 종결자가 필요합니다. 패딩은 중복됩니다. 따라서 OP의 질문입니다.
나빈

4
@Navin base64 바이트를 스트림 디코딩하는 경우 3 바이트 패딩을 사용하여 길이를 알지 못하므로 3 바이트를 얻을 때마다 스트림 끝에 도달 할 때까지 4 문자를 처리 할 수 ​​있습니다. 이것이 없으면 다음 바이트로 인해 이전 문자가 변경 될 수 있으므로 역 추적해야 할 수 있습니다. 따라서 스트림 끝에 도달 한 후에 만 ​​올바르게 디코딩했는지 확인할 수 있습니다. 따라서 그다지 유용하지는 않지만 원하는 경우 몇 가지 경우가 있습니다.
Didier A.

1

현대에는 그다지 유익하지 않습니다. 그래서 이것을 원래의 역사적 목적이 무엇 이었을지에 대한 질문으로 봅시다 .

Base64 인코딩은 1993 년 RFC 1421에 처음 등장했습니다 .이 RFC는 실제로 이메일 암호화에 초점을 맞추고 있으며 base64는 하나의 작은 섹션 4.3.2.4에 설명되어 있습니다.

이 RFC는 패딩의 목적을 설명하지 않습니다. 원래 목적에 대해 가장 가까운 언급은 다음 문장입니다.

전체 인코딩 퀀텀은 항상 메시지 끝에서 완료됩니다.

연결 (여기에서 가장 높은 답변)이나 패딩의 명시 적 목적으로 구현의 용이성을 제안하지 않습니다. 그러나 전체 설명을 고려할 때 이것이 디코더가 입력을 32 비트 단위 ( "퀀타" )로 읽는 데 도움을주기위한 것이라고 가정하는 것은 합리적이지 않습니다 . 그것은 오늘날 유익하지 않지만 1993 년에 안전하지 않은 C 코드는 실제로이 속성을 이용했을 가능성이 큽니다.


1
패딩이없는 경우 첫 번째 문자열의 길이가 3의 배수가 아닐 때 두 문자열을 연결하려는 시도는 종종 겉보기에 유효한 문자열을 생성하지만 두 번째 문자열의 내용은 잘못 디코딩됩니다. 패딩을 추가하면 이러한 현상이 발생하지 않습니다.
supercat

1
@supercat 그게 목표라면 모든 base64 문자열을 "="하나로 끝내는 것이 더 쉬울까요? 평균 길이는 더 짧고 잘못된 연결을 방지합니다.
Roman Starkov

2
의 평균 길이는 b'Zm9vYmFyZm9vYg==' b'Zm9vYmFyZm9vYmE=' b'Zm9vYmFyZm9vYmFy' b'Zm9vYmFyZm9vYmFyZg==' b'Zm9vYmFyZm9vYmFyZm8=' b'Zm9vYmFyZm9vYmFyZm9v'b'Zm9vYmFyZm9vYg=' b'Zm9vYmFyZm9vYmE=' b'Zm9vYmFyZm9vYmFy=' b'Zm9vYmFyZm9vYmFyZg=' b'Zm9vYmFyZm9vYmFyZm8=' b'Zm9vYmFyZm9vYmFyZm9v='
Scott
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.