[python] Python : base64 디코딩시 ‘잘못된 패딩’오류 무시

패딩 오류가 있어도 바이너리로 다시 변환하려는 base64로 인코딩 된 데이터가 있습니다. 내가 사용한다면

base64.decodestring(b64_string)

‘잘못된 패딩’오류가 발생합니다. 다른 방법이 있습니까?

업데이트 : 모든 피드백에 감사드립니다. 솔직히 말해서, 언급 된 모든 방법이 약간 안타 나거나 그리워서 openssl을 시도하기로 결정했습니다. 다음 명령이 효과가있었습니다.

openssl enc -d -base64 -in b64string -out binary_data



답변

다른 응답에서 언급했듯이 base64 데이터가 손상 될 수있는 다양한 방법이 있습니다.

그러나 Wikipedia가 말했듯이 패딩 (base64 인코딩 데이터의 끝에있는 ‘=’문자)을 제거하는 것은 “무손실”입니다.

이론적 인 관점에서 볼 때 누락 된 바이트 수는 Base64 자릿수에서 계산할 수 있으므로 패딩 문자가 필요하지 않습니다.

따라서 이것이 실제로 base64 데이터에 “잘못된”유일한 경우라면 패딩을 다시 추가 할 수 있습니다. WeasyPrint에서 “데이터”URL을 구문 분석 할 수 있도록이 방법을 생각해 냈습니다. 그 중 일부는 패딩없이 base64였습니다.

import base64
import re

def decode_base64(data, altchars=b'+/'):
    """Decode base64, padding being optional.

    :param data: Base64 data as an ASCII byte string
    :returns: The decoded byte string.

    """
    data = re.sub(rb'[^a-zA-Z0-9%s]+' % altchars, b'', data)  # normalize
    missing_padding = len(data) % 4
    if missing_padding:
        data += b'='* (4 - missing_padding)
    return base64.b64decode(data, altchars)

이 함수에 대한 테스트 : weasyprint / tests / test_css.py # L68


답변

필요에 따라 패딩 만 추가하면됩니다. 그러나 마이클의 경고에 유의하십시오.

b64_string += "=" * ((4 - len(b64_string) % 4) % 4) #ugh


답변

디코딩하기 전에 바이트에 패딩을 추가해야하는 것 같습니다. 이 질문에 대한 다른 많은 답변이 있지만 (적어도 Python 3.x에서는) base64.b64decode처음에 충분한 패딩이 있으면 여분의 패딩을자를 것임을 지적하고 싶습니다 .

따라서 다음과 같이 b'abc='작동합니다 b'abc=='( b'abc=====').

이것이 의미하는 바는 필요한 최대 패딩 문자 수 (3 ( b'===')) 만 추가 할 수 있으며 base64는 불필요한 문자를 자릅니다.

이렇게하면 다음과 같이 작성할 수 있습니다.

base64.b64decode(s + b'===')

다음보다 간단합니다.

base64.b64decode(s + b'=' * (-len(s) % 4))


답변

“잘못된 패딩”은 “누락 된 패딩”뿐만 아니라 (믿거 나 말거나) “잘못된 패딩”을 의미 할 수 있습니다.

제안 된 “패딩 추가”메소드가 작동하지 않으면 후행 바이트를 제거해보십시오.

lens = len(strg)
lenx = lens - (lens % 4 if lens % 4 else 4)
try:
    result = base64.decodestring(strg[:lenx])
except etc

업데이트 : 공백을 제거한 후에 패딩을 추가하거나 끝에서 불량 바이트를 제거하는 작업을 수행해야합니다. 그렇지 않으면 길이 계산이 잘못됩니다.

복구해야하는 데이터의 (짧은) 샘플을 보여 주 셨다면 좋은 생각이 될 것입니다. 질문을 수정하고의 결과를 복사 / 붙여 넣기하십시오 print repr(sample) .

업데이트 2 : 인코딩이 url-safe 방식으로 수행되었을 수 있습니다. 이 경우 데이터에서 마이너스 및 밑줄 문자를 볼 수 있으며 다음을 사용하여 디코딩 할 수 있어야합니다.base64.b64decode(strg, '-_')

데이터에서 마이너스 및 밑줄 문자는 볼 수 없지만 플러스 및 슬래시 문자는 볼 수 있다면 다른 문제가있는 것이므로 추가 패딩 또는 크랙 제거 트릭이 필요할 수 있습니다.

데이터에 마이너스, 밑줄, 플러스 및 슬래시가 모두 표시되지 않으면 두 개의 대체 문자를 결정해야합니다. 그들은 [A-Za-z0-9]에없는 것입니다. 그런 다음 두 번째 인수에서 사용해야하는 순서를 확인하기 위해 실험해야합니다.base64.b64decode()

업데이트 3 : 데이터가 “회사 기밀”인 경우 :
(a)는 당신이 그렇게 말을해야 앞까지의
(b)는 우리가 문자 대신 사용하는 것과 관련이있을 가능성이 높다 문제, 이해의 다른 도로를 탐색 할 수 있습니다 +/의를 인코딩 알파벳 또는 기타 형식화 또는 관련없는 문자.

그러한 방법 중 하나는 데이터에있는 비 “표준”문자가 무엇인지 조사하는 것입니다.

from collections import defaultdict
d = defaultdict(int)
import string
s = set(string.ascii_letters + string.digits)
for c in your_data:
   if c not in s:
      d[c] += 1
print d


답변

사용하다

string += '=' * (-len(string) % 4)  # restore stripped '='s

신용은 여기 어딘가에 주석으로 이동합니다.

>>> import base64

>>> enc = base64.b64encode('1')

>>> enc
>>> 'MQ=='

>>> base64.b64decode(enc)
>>> '1'

>>> enc = enc.rstrip('=')

>>> enc
>>> 'MQ'

>>> base64.b64decode(enc)
...
TypeError: Incorrect padding

>>> base64.b64decode(enc + '=' * (-len(enc) % 4))
>>> '1'

>>> 


답변

패딩 오류가 있으면 문자열이 손상되었음을 의미합니다. base64로 인코딩 된 문자열은 길이 4의 배수 여야합니다. 패딩 문자 ( =)를 직접 추가하여 문자열을 4의 배수로 만들 수 있지만 뭔가 잘못되지 않는 한 이미 포함되어 있어야합니다.


답변

디코딩하려는 데이터 소스의 설명서를 확인하십시오. base64.urlsafe_b64decode(s)대신 사용하려는 것이 가능 base64.b64decode(s)합니까? 이것이이 오류 메시지를 본 이유 중 하나입니다.

표준 Base64 알파벳에서 / 대신 + 및 _ 대신-를 대체하는 URL 안전 알파벳을 사용하여 문자열 s를 디코딩합니다.

예를 들어 Google의 Identity Toolkit 및 Gmail 페이로드와 같은 다양한 Google API의 경우입니다.