رمزگذاری Base64
7 ابزار
رمزگذاری چیست؟
رمزگذاری فرآیند تبدیل داده از یک نمایش به نمایش دیگر است. در توسعه وب، رمزگذاری برای انتقال ایمن داده از طریق کانالهایی که برای مجموعه کاراکترهای محدود طراحی شدهاند استفاده میشود — برای مثال، ارسال داده باینری از طریق یک پروتکل متنمحور، یا درج کاراکترهای خاص در یک URL.
رمزگذاری کاراکتر مشخص میکند کاراکترهای متنی چگونه به بایتها نگاشت میشوند. رمزگذاری Base64 داده باینری را به متن ASCII تبدیل میکند. رمزگذاری URL متن دلخواه را برای استفاده در URLها ایمن میسازد. درک این سه لایه رمزگذاری از باگهای پنهان و آسیبپذیریهای امنیتی جلوگیری میکند.
تاریخچه رمزگذاری کاراکتر
رمزگذاری کاراکتر نگاشت میان کاراکترها (حروف، نمادها) و نمایشهای باینری آنهاست. تکامل از ASCII به Unicode نشاندهنده جهانیشدن وب است:
کد استاندارد آمریکایی ۷ بیتی. ۱۲۸ کاراکتر: حروف انگلیسی، ارقام، علائم نگارشی و کدهای کنترلی. پایهایترین رمزگذاری که همه دیگران از آن گسترش یافتهاند.
ASCII توسعهیافته برای زبانهای اروپای غربی. ۱۲۸ کاراکتر اضافه کرد (حروف با لهجه، نمادها). برای اسکریپتهای غیرلاتین مناسب نیست.
مجموعه کاراکتر جهانی که تمام سیستمهای نوشتاری دنیا را پوشش میدهد. کد پوینت برای بیش از ۱۴۹٬۰۰۰ کاراکتر در ۱۶۱ اسکریپت تعریف میکند. رمزگذاری تعریف نمیکند — آن UTF-8/16/32 است.
رمزگذاری متغیر Unicode با ۱ تا ۴ بایت به ازای هر کاراکتر. سازگار با ASCII (اولین ۱۲۸ کد پوینت تکبایت هستند). رمزگذاری غالب در وب — بیش از ۹۸٪ وبسایتها.
رمزگذاری متغیر با ۲ یا ۴ بایت به ازای هر کاراکتر. بهصورت داخلی در Windows، Java و رشتههای JavaScript استفاده میشود. با ASCII سازگار نیست.
رمزگذاری با عرض ثابت: همیشه ۴ بایت به ازای هر کاراکتر. ساده اما فضا هدر میدهد. در برخی پیادهسازیهای داخلی پایگاه داده استفاده میشود. بهندرت در وب دیده میشود.
چرا 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 6E | TWFu |
| "Ma" | 4D 61 | TWE= |
| "M" | 4D | TQ== |
کاراکترهای پدینگ = در انتها نشان میدهند چند بایت برای تکمیل آخرین گروه ۳ بایتی کم بود. یک = یعنی یک بایت پدینگ نیاز بود؛ == یعنی دو بایت. 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 استفاده کنید.
کجا رمزگذاری در توسعه وب ظاهر میشود
هدر Authorization: Basic اطلاعات اعتبارسنجی را به صورت Base64(نامکاربری:رمزعبور) رمزگذاری میکند. این رمزگذاری برای راحتی انتقال است، نه امنیت — Base64 به سادگی قابل معکوسسازی است. همیشه از HTTPS با Basic Auth استفاده کنید.
Data URIها محتوای فایل را مستقیماً در HTML یا CSS جاسازی میکنند: data:image/png;base64,.... رمزگذاری Base64 تصاویر و فونتها بهصورت درونخطی درخواستهای HTTP را حذف میکند، با هزینه افزایش اندازه سند (~۳۳٪ سربار).
ایمیل برای ASCII 7 بیتی طراحی شده بود. پیوستهای باینری (تصاویر، فایلهای PDF) قبل از انتقال توسط MIME با Base64 رمزگذاری میشوند. کلاینت ایمیل شما هنگام نمایش ایمیل آنها را بهصورت خودکار رمزگشایی میکند.
توکنهای JWT از رمزگذاری Base64url (نوعی که + را با - و / را با _ جایگزین میکند، بدون پدینگ) برای هر سه بخش (هدر، محموله، امضا) استفاده میکنند. این کار توکنها را بدون نیاز به percent-encoding اضافی برای URL ایمن میکند.
هر داده ارائهشده توسط کاربر در رشتههای کوئری URL باید percent-encoded شود. عدم رمزگذاری & یا = در یک مقدار بهطور پنهانی تجزیه رشته کوئری را خراب میکند. همیشه از encodeURIComponent برای مقادیر جداگانه استفاده کنید.
نامهای دامنه غیر ASCII (مثلاً münchen.de) با استفاده از Punycode (پیشوند xn--) برای سازگاری با سیستم DNS رمزگذاری میشوند. مرورگر شکل Unicode را نشان میدهد اما شکل Punycode را برای سرورهای DNS ارسال میکند.
سوالات متداول
خیر. Base64 رمزگذاری است، نه رمزنگاری. این یک تبدیل برگشتپذیر بدون کلید مخفی است. هر کسی که یک رشته Base64 ببیند میتواند آن را فوری رمزگشایی کند. هرگز از Base64 به عنوان اقدام امنیتی استفاده نکنید.
Base64 ورودی را در گروههای ۳ بایتی پردازش میکند. اگر ورودی مضربی از ۳ بایت نباشد، پدینگ = برای تکمیل آخرین گروه اضافه میشود. یک = یعنی یک بایت پدینگ؛ == یعنی دو بایت. برخی پیادهسازیها پدینگ را حذف میکنند (Base64url برای JWTها).
Base64url نوع URL-safe از Base64 است که + را با - و / را با _ جایگزین میکند، و معمولاً پدینگ = را حذف میکند. این آن را برای استفاده در URLها و هدرهای HTTP بدون percent-encoding ایمن میکند. JWTها از Base64url برای هر سه بخش استفاده میکنند.
از encodeURIComponent برای مقادیر جداگانه (مقادیر پارامتر کوئری، مقادیر بخش مسیر) استفاده کنید. از encodeURI برای یک رشته URL کامل استفاده کنید وقتی میخواهید کاراکترهای ساختاری URL (/، :، ?، #) را حفظ کنید. در صورت شک، از encodeURIComponent استفاده کنید.
UTF-8 با ASCII سازگار است و برای متن لاتین (اکثر URLها، تگهای HTML و کد ASCII هستند) کارایی فضایی دارد. UTF-16 برای محتوای ASCII فضا هدر میدهد و با ASCII سازگار نیست. HTTP و HTML به طور پیشفرض UTF-8 هستند.
رمزگذاری درصدی (رمزگذاری URL) کاراکترها را به صورت % به دنبال مقدار هگزادسیمال دو رقمی بایت آنها نمایش میدهد. برای مثال، یک فاصله %20 است (دسیمال ۳۲، هگز ۲۰). کاراکترهای چندبایتی UTF-8 هر بایت را جداگانه رمزگذاری میکنند: é به صورت %C3%A9 است.
Base64 اندازه داده را تقریباً ۳۳٪ افزایش میدهد و سربار پردازنده برای رمزگذاری/رمزگشایی اضافه میکند. برای سیستمهای با توانعملیاتی بالا، پروتکلهای باینری را ترجیح دهید. رمزگذاری URL سربار کمی اضافه میکند اما میتواند URLها را با وجود کاراکترهای خاص زیاد به طور قابل توجهی طولانیتر کند.
Punycode رمزگذاری برای نمایش کاراکترهای Unicode در سیستم DNS سازگار با ASCII است. نامهای دامنه بینالمللی مانند münchen.de در کوئریهای DNS به صورت xn--mnchen-3ya.de رمزگذاری میشوند. مرورگرها شکل Unicode را نشان میدهند اما از Punycode به صورت داخلی استفاده میکنند.