Base91을 인코딩하고 디코딩하는 방법
- 입력 · 텍스트에 텍스트를 입력하거나 붙여넣으세요. 출력 · basE91에 인코딩된 문자열이 나타납니다.
- 바이너리 데이터라면 변환 전을 Hex나 Base64로 설정하고 그 형식으로 붙여넣으세요.
- 디코딩하려면 방향 전환에서 basE91 → 텍스트를 누르세요. 입력의 줄 바꿈은 무시되며, 알파벳 밖의 다른 문자가 나오면 그 위치를 알려 주고 디코딩을 멈춥니다.
- 출력 복사나 다운로드로 결과를 가져가세요. 디코딩한 바이너리 데이터에는 바이트 저장을 쓰세요.
basE91의 작동 원리
basE91은 Joachim Henke가 발표했습니다. Base64는 6비트마다 문자 하나를 대응시키지만, basE91은 입력 비트를 큐에 모아 13비트씩 가져갑니다. 두 문자로 91 × 91 = 8281가지 값을 나타낼 수 있어 13비트에 필요한 8192보다 조금 많습니다. 남는 여유는 최적화에 씁니다. 다음 13비트의 값이 88 이하이면 인코더는 14비트를 가져가면서도 여전히 두 문자를 씁니다.
그래서 출력 길이가 내용에 따라 달라집니다. 랜덤 데이터에서는 14비트 그룹이 드물어서(전체 그룹의 1.1% 미만) 오버헤드가 16/13, 약 23%에 가깝습니다. 0 비트가 많은 데이터는 더 잘 압축됩니다. 0 바이트 1000개는 1143자로 인코딩되어 오버헤드가 14%입니다.
| 입력 | basE91 | Base64 |
|---|---|---|
test | fPNKd | dGVzdA== |
Hello | >OwJh>A | SGVsbG8= |
Hello World! | >OwJh>Io0Tv!8PE | SGVsbG8gV29ybGQh |
| 0 바이트 4개 | AAAAA | AAAAAA== |
| 랜덤 1000바이트 | 약 1230자 | 1336자 |
가변 그룹에는 부작용이 있습니다. 고정된 블록 크기가 없으므로 문자열 중간부터 디코딩하거나 아무 지점에서나 나눌 수 없습니다. Base64는 4의 배수인 어느 위치에서든 나눌 수 있습니다.
알파벳과 문제가 되는 곳
basE91 알파벳은 A–Z, a–z, 0–9와 다음 29개 문자입니다.
!#$%&()*+,./:;<=>?@[]^_`{|}~"
공백, ', -, \는 빠져 있습니다. 공백과 '는 셸과 따옴표로 감싼 문자열에서 문제를 일으키고, \는 거의 모든 곳에서 이스케이프 문자입니다. 큰따옴표는 <, >, &와 함께 여전히 들어 있어서 JSON, HTML, XML 안의 basE91은 이스케이프가 필요하고, 그 이스케이프가 Base64 대비 이득의 일부를 갉아먹습니다. 텍스트 파일, 작은따옴표로 감싼 셸 인수, 바이너리 안전 프로토콜 필드처럼 출력 가능한 ASCII를 모두 받는 곳에서 가장 잘 맞습니다.
Python으로 만든 basE91 인코더
표준 라이브러리에는 basE91이 없습니다. Henke의 알고리즘은 직접 넣을 수 있을 만큼 짧습니다.
ALPHABET = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~\"")
def b91encode(data: bytes) -> str:
out, queue, nbits = [], 0, 0
for byte in data:
queue |= byte << nbits
nbits += 8
if nbits > 13:
value = queue & 8191
if value > 88:
queue >>= 13
nbits -= 13
else:
value = queue & 16383
queue >>= 14
nbits -= 14
out += ALPHABET[value % 91], ALPHABET[value // 91]
if nbits:
out.append(ALPHABET[queue % 91])
if nbits > 7 or queue > 90:
out.append(ALPHABET[queue // 91])
return "".join(out)
b91encode(b"test") # 'fPNKd'
어떤 입력에 대해서도 이 페이지와 같은 출력을 냅니다. Python의 바이트 처리는 Python 페이지에서 더 다룹니다.
Base91을 골라야 할 때
출력의 바이트 하나하나가 중요하고 채널이 출력 가능한 ASCII를 거의 모두 받는다면 basE91을 고르세요. 간결한 로그나 길이 제한이 엄격한 텍스트 필드가 그런 경우입니다. JSON, URL, HTML, 이메일에 들어가는 데이터라면 Base64가 더 안전하고 길이도 거의 비슷합니다. 고정 블록에 25% 오버헤드를 원한다면 PDF와 PostScript에서 표준으로 쓰는 Ascii85가 있습니다.
자주 묻는 질문
Base91은 어떤 문자를 쓰나요?
출력 가능한 ASCII 문자 95개 중 공백, 아포스트로피 ', 하이픈 -, 백슬래시 \를 뺀 전부입니다. 영문자, 숫자, 큰따옴표를 포함한 문장 부호 29개가 남습니다.
Base91이 Base85보다 작나요?
조금 작습니다. 랜덤 데이터는 basE91에서 약 23%, Base85에서 정확히 25% 늘어납니다. 여기서 랜덤 100,000바이트는 122,976자가 되었고 Ascii85로는 125,000자였습니다. 0 바이트가 길게 이어지는 데이터는 더 줄어들어 오버헤드가 약 14%까지 내려갑니다.
Base91이 널리 쓰이지 않는 이유는 무엇인가요?
RFC가 없고, 출력에 " 등 JSON, 셸, HTML에서 이스케이프가 필요한 문자가 들어 있으며, 가변 비트 그룹 때문에 Base64보다 느리고 구현하기도 어렵습니다. 몇 퍼센트 줄어드는 이점이 이를 넘어서는 경우는 드뭅니다.
다른 라이브러리가 만든 Base91도 디코딩할 수 있나요?
대부분이 그렇듯 Henke의 basE91 알파벳과 비트 순서를 쓴 경우에만 됩니다. 일부 라이브러리는 자체 Base91 알파벳을 쓰는데, 그 출력은 여기서 오류 없이 디코딩되지만 잘못된 바이트가 나옵니다.