ToolDeck

رمزگذاری Base64

7 ابزار

رمزگذاری چیست؟

رمزگذاری فرآیند تبدیل داده از یک نمایش به نمایش دیگر است. در توسعه وب، رمزگذاری برای انتقال ایمن داده از طریق کانال‌هایی که برای مجموعه کاراکترهای محدود طراحی شده‌اند استفاده می‌شود — برای مثال، ارسال داده باینری از طریق یک پروتکل متن‌محور، یا درج کاراکترهای خاص در یک URL.

رمزگذاری کاراکتر مشخص می‌کند کاراکترهای متنی چگونه به بایت‌ها نگاشت می‌شوند. رمزگذاری Base64 داده باینری را به متن ASCII تبدیل می‌کند. رمزگذاری URL متن دلخواه را برای استفاده در URLها ایمن می‌سازد. درک این سه لایه رمزگذاری از باگ‌های پنهان و آسیب‌پذیری‌های امنیتی جلوگیری می‌کند.

تاریخچه رمزگذاری کاراکتر

رمزگذاری کاراکتر نگاشت میان کاراکترها (حروف، نمادها) و نمایش‌های باینری آن‌هاست. تکامل از ASCII به Unicode نشان‌دهنده جهانی‌شدن وب است:

ASCII1963
128 کاراکتر

کد استاندارد آمریکایی ۷ بیتی. ۱۲۸ کاراکتر: حروف انگلیسی، ارقام، علائم نگارشی و کدهای کنترلی. پایه‌ای‌ترین رمزگذاری که همه دیگران از آن گسترش یافته‌اند.

Latin-11987
256 کاراکتر

ASCII توسعه‌یافته برای زبان‌های اروپای غربی. ۱۲۸ کاراکتر اضافه کرد (حروف با لهجه، نمادها). برای اسکریپت‌های غیرلاتین مناسب نیست.

Unicode1991
149 186+ کاراکتر

مجموعه کاراکتر جهانی که تمام سیستم‌های نوشتاری دنیا را پوشش می‌دهد. کد پوینت برای بیش از ۱۴۹٬۰۰۰ کاراکتر در ۱۶۱ اسکریپت تعریف می‌کند. رمزگذاری تعریف نمی‌کند — آن UTF-8/16/32 است.

UTF-81993
تمام Unicode کاراکتر

رمزگذاری متغیر Unicode با ۱ تا ۴ بایت به ازای هر کاراکتر. سازگار با ASCII (اولین ۱۲۸ کد پوینت تک‌بایت هستند). رمزگذاری غالب در وب — بیش از ۹۸٪ وب‌سایت‌ها.

UTF-161996
تمام Unicode کاراکتر

رمزگذاری متغیر با ۲ یا ۴ بایت به ازای هر کاراکتر. به‌صورت داخلی در Windows، Java و رشته‌های JavaScript استفاده می‌شود. با ASCII سازگار نیست.

UTF-322000
تمام Unicode کاراکتر

رمزگذاری با عرض ثابت: همیشه ۴ بایت به ازای هر کاراکتر. ساده اما فضا هدر می‌دهد. در برخی پیاده‌سازی‌های داخلی پایگاه داده استفاده می‌شود. به‌ندرت در وب دیده می‌شود.

چرا UTF-8 برنده شد

UTF-8 به دلیل سازگاری با ASCII (۱۲۸ کاراکتر اول به شکل یکسان رمزگذاری می‌شوند)، خودهمگام‌ساز بودن (می‌توان مرزهای کاراکتر را با اسکن یافت) و کارایی فضایی برای متن لاتین، غالب شد. هر سند ASCII یک سند UTF-8 معتبر است. این مهاجرت را بی‌دردسر کرد.

رمزگذاری Base64

Base64 داده باینری را به نمایش متنی تبدیل می‌کند و تنها از ۶۴ کاراکتر ASCII قابل چاپ استفاده می‌کند: A-Z، a-z، 0-9، + و /. این امر زمانی ضروری است که داده باینری باید از کانال‌هایی عبور کند که فقط متن را می‌پذیرند — پیوست‌های ایمیل، URIهای داده، توکن‌های JWT و HTTP Basic Auth همگی از Base64 استفاده می‌کنند.

نحوه عملکرد

Base64 بایت‌های ورودی را به تکه‌های ۳ بایتی (۲۴ بیتی) گروه‌بندی می‌کند و هر تکه را به عنوان ۴ کاراکتر Base64 (هر کدام ۶ بیت) رمزگذاری می‌کند. اگر ورودی مضربی از ۳ بایت نباشد، کاراکترهای پدینگ = برای تکمیل آخرین گروه اضافه می‌شوند:

ورودیبایت‌های هگزBase64
"Man"77 61 6ETWFu
"Ma"4D 61TWE=
"M"4DTQ==

کاراکترهای پدینگ = در انتها نشان می‌دهند چند بایت برای تکمیل آخرین گروه ۳ بایتی کم بود. یک = یعنی یک بایت پدینگ نیاز بود؛ == یعنی دو بایت. Base64 استاندارد همیشه خروجی‌ای تولید می‌کند که طولش مضربی از ۴ است.

رمزگذاری URL

URLها تنها می‌توانند مجموعه محدودی از کاراکترهای ASCII ایمن داشته باشند. هر کاراکتر خارج از این مجموعه — شامل فاصله، علائم نگارشی، کاراکترهای غیر ASCII و کاراکترهای خاص URL مانند &، = و # — باید پیش از قرار گرفتن در URL به‌صورت percent-encoded (URL-encoded) درآید.

رمزگذاری درصدی هر بایت ناامن را با یک % به دنبال دو رقم هگزادسیمال که مقدار آن بایت را نشان می‌دهند جایگزین می‌کند. یک فاصله به %20، یک علامت & به %26 تبدیل می‌شود و به همین ترتیب.

کاراکترهای رایجاً رمزگذاری‌شده

کاراکتررمزگذاری‌شدهتوضیحات
Space%20رایج‌ترین؛ در ارسال فرم به عنوان + در application/x-www-form-urlencoded استفاده می‌شود
&%26جداکننده رشته کوئری؛ زمانی که به عنوان مقدار تحت‌الفظی استفاده می‌شود باید رمزگذاری شود
=%3Dجداکننده کلید-مقدار در رشته‌های کوئری؛ زمانی که به عنوان داده استفاده می‌شود رمزگذاری کنید
+%2Bدر application/x-www-form-urlencoded به عنوان فاصله تفسیر می‌شود؛ برای حفظ + تحت‌الفظی رمزگذاری کنید
#%23شناسه قطعه؛ زمانی که به عنوان داده تحت‌الفظی در یک مسیر یا کوئری استفاده می‌شود رمزگذاری کنید
/%2Fجداکننده بخش مسیر؛ زمانی که به عنوان داده تحت‌الفظی استفاده می‌شود نه جداکننده مسیر، رمزگذاری کنید
:%3Aجداکننده طرح؛ در مسیر و زمینه‌های کوئری رمزگذاری کنید
@%40در mailto: و احراز هویت استفاده می‌شود؛ زمانی که به عنوان داده تحت‌الفظی استفاده می‌شود رمزگذاری کنید

encodeURI در مقابل encodeURIComponent

JavaScript دو تابع رمزگذاری با حوزه‌های متفاوت ارائه می‌دهد. encodeURI یک URL کامل را رمزگذاری می‌کند — کاراکترهایی که در URLها معنا دارند (:، /، ?، #، @) را بدون تغییر می‌گذارد. encodeURIComponent یک مؤلفه URL (مقدار یک پارامتر کوئری تکی یا بخش مسیر) را رمزگذاری می‌کند — تمام کاراکترها را به جز A-Z، a-z، 0-9، -، _، .، ~ رمزگذاری می‌کند. همیشه برای مقادیر جداگانه از encodeURIComponent و برای URLهای کامل از encodeURI استفاده کنید.

کجا رمزگذاری در توسعه وب ظاهر می‌شود

احراز هویت پایه HTTP

هدر Authorization: Basic اطلاعات اعتبارسنجی را به صورت Base64(نام‌کاربری:رمزعبور) رمزگذاری می‌کند. این رمزگذاری برای راحتی انتقال است، نه امنیت — Base64 به سادگی قابل معکوس‌سازی است. همیشه از HTTPS با Basic Auth استفاده کنید.

Data URIها

Data URIها محتوای فایل را مستقیماً در HTML یا CSS جاسازی می‌کنند: data:image/png;base64,.... رمزگذاری Base64 تصاویر و فونت‌ها به‌صورت درون‌خطی درخواست‌های HTTP را حذف می‌کند، با هزینه افزایش اندازه سند (~۳۳٪ سربار).

پیوست‌های ایمیل MIME

ایمیل برای ASCII 7 بیتی طراحی شده بود. پیوست‌های باینری (تصاویر، فایل‌های PDF) قبل از انتقال توسط MIME با Base64 رمزگذاری می‌شوند. کلاینت ایمیل شما هنگام نمایش ایمیل آن‌ها را به‌صورت خودکار رمزگشایی می‌کند.

توکن‌های JWT

توکن‌های JWT از رمزگذاری Base64url (نوعی که + را با - و / را با _ جایگزین می‌کند، بدون پدینگ) برای هر سه بخش (هدر، محموله، امضا) استفاده می‌کنند. این کار توکن‌ها را بدون نیاز به percent-encoding اضافی برای URL ایمن می‌کند.

پارامترهای رشته کوئری

هر داده ارائه‌شده توسط کاربر در رشته‌های کوئری URL باید percent-encoded شود. عدم رمزگذاری & یا = در یک مقدار به‌طور پنهانی تجزیه رشته کوئری را خراب می‌کند. همیشه از encodeURIComponent برای مقادیر جداگانه استفاده کنید.

نام‌های دامنه بین‌المللی

نام‌های دامنه غیر ASCII (مثلاً münchen.de) با استفاده از Punycode (پیشوند xn--) برای سازگاری با سیستم DNS رمزگذاری می‌شوند. مرورگر شکل Unicode را نشان می‌دهد اما شکل Punycode را برای سرورهای DNS ارسال می‌کند.

سوالات متداول

آیا Base64 نوعی رمزنگاری است؟

خیر. Base64 رمزگذاری است، نه رمزنگاری. این یک تبدیل برگشت‌پذیر بدون کلید مخفی است. هر کسی که یک رشته Base64 ببیند می‌تواند آن را فوری رمزگشایی کند. هرگز از Base64 به عنوان اقدام امنیتی استفاده نکنید.

چرا خروجی Base64 گاهی با == پایان می‌یابد؟

Base64 ورودی را در گروه‌های ۳ بایتی پردازش می‌کند. اگر ورودی مضربی از ۳ بایت نباشد، پدینگ = برای تکمیل آخرین گروه اضافه می‌شود. یک = یعنی یک بایت پدینگ؛ == یعنی دو بایت. برخی پیاده‌سازی‌ها پدینگ را حذف می‌کنند (Base64url برای JWTها).

تفاوت Base64 و Base64url چیست؟

Base64url نوع URL-safe از Base64 است که + را با - و / را با _ جایگزین می‌کند، و معمولاً پدینگ = را حذف می‌کند. این آن را برای استفاده در URLها و هدرهای HTTP بدون percent-encoding ایمن می‌کند. JWTها از Base64url برای هر سه بخش استفاده می‌کنند.

چه وقت باید از encodeURI در مقابل encodeURIComponent استفاده کنم؟

از encodeURIComponent برای مقادیر جداگانه (مقادیر پارامتر کوئری، مقادیر بخش مسیر) استفاده کنید. از encodeURI برای یک رشته URL کامل استفاده کنید وقتی می‌خواهید کاراکترهای ساختاری URL (/، :، ?، #) را حفظ کنید. در صورت شک، از encodeURIComponent استفاده کنید.

چرا UTF-8 برای وب از UTF-16 بهتر است؟

UTF-8 با ASCII سازگار است و برای متن لاتین (اکثر URLها، تگ‌های HTML و کد ASCII هستند) کارایی فضایی دارد. UTF-16 برای محتوای ASCII فضا هدر می‌دهد و با ASCII سازگار نیست. HTTP و HTML به طور پیش‌فرض UTF-8 هستند.

رمزگذاری درصدی چیست؟

رمزگذاری درصدی (رمزگذاری URL) کاراکترها را به صورت % به دنبال مقدار هگزادسیمال دو رقمی بایت آن‌ها نمایش می‌دهد. برای مثال، یک فاصله %20 است (دسیمال ۳۲، هگز ۲۰). کاراکترهای چندبایتی UTF-8 هر بایت را جداگانه رمزگذاری می‌کنند: é به صورت %C3%A9 است.

آیا رمزگذاری روی عملکرد تأثیر می‌گذارد؟

Base64 اندازه داده را تقریباً ۳۳٪ افزایش می‌دهد و سربار پردازنده برای رمزگذاری/رمزگشایی اضافه می‌کند. برای سیستم‌های با توان‌عملیاتی بالا، پروتکل‌های باینری را ترجیح دهید. رمزگذاری URL سربار کمی اضافه می‌کند اما می‌تواند URLها را با وجود کاراکترهای خاص زیاد به طور قابل توجهی طولانی‌تر کند.

Punycode چیست؟

Punycode رمزگذاری برای نمایش کاراکترهای Unicode در سیستم DNS سازگار با ASCII است. نام‌های دامنه بین‌المللی مانند münchen.de در کوئری‌های DNS به صورت xn--mnchen-3ya.de رمزگذاری می‌شوند. مرورگرها شکل Unicode را نشان می‌دهند اما از Punycode به صورت داخلی استفاده می‌کنند.