تغییرات اخیر

در اینجا اطلاعیه‌ها، نسخه‌ها و تغییرات جدید لیارا فهرست می‌شوند.

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


۲۶ دی ۱۴۰۴

خلاصه کنید:

openaigeminiperplexity

Base64 یک روش استاندارد برای تبدیل داده‌های باینری به متن است و در جاوا اسکریپت با توابع btoa() و atob() می‌توان آن را به سادگی رمزگذاری و رمزگشایی کرد. این تکنیک کاربرد زیادی در ارسال داده‌های پیچیده، مانند تصاویر یا فایل‌های رسانه‌ای، از طریق کانال‌های متنی دارد. در این مقاله، نحوه استفاده از Base64، محدودیت‌ها و راهکارهای مناسب برای کار با Unicode و محیط Node.js را بررسی می‌کنیم.

در ادامه خواهید خواند:

  • پیش نیاز
  • رمزگذاری Base64 چیست؟
  • نکات مهم در Node.js
  • کاربردهای عملی Base64
  • چالش‌ها و بهترین شیوه‌ها
  • جمع بندی

پیش نیاز

برای بهره‌مندی کامل از این آموزش، بهتر است که:

  • با رشته‌ها در جاوااسکریپت آشنایی پایه‌ای داشته باشید.
  • با توابع موجود در محیط‌های سراسری مانند Window یا WorkerGlobalScope آشنا باشید.
  • تجربه کار با کنسول توسعه‌دهنده مرورگر را داشته باشید.

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

رمزگذاری Base64 روشی است که داده‌های باینری را به مجموعه محدودی از کاراکترهای ACII تبدیل می‌کند. این مجموعه شامل 64 کاراکتر رایج است که برای انتقال در اکثر سیستم‌های مبتنی بر متن امن هستند. این کاراکترها شامل حروف بزرگ (A-Z)، حروف کوچک (a-z)، اعداد (9-0)، و دو کاراکتر ویژه (+ و /) می‌شود. همچنین، در صورت نیاز، یک کاراکتر پد (=) در انتهای رشته رمزگذاری‌شده اضافه می‌شود.

هدف اصلی Base64 این است که داده‌ها هنگام انتقال بدون تغییر باقی بمانند. این مسئله برای پروتکل‌‍‌هایی که فقط متن را پردازش می‌کنند اهمیت دارد، زیرا ممکن است توالی‌های خاصی از بایت‌ها به اشتباه به‌عنوان کاراکترهای کنترلی تفسیر شوند.

رمزگذاری رشته با btoa()

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

نام btoa برگرفته از دستور قدیمی یونیکس برای تبدیل “binary to ASCII” است.

مثال: رشته "Hello World!" را رمز‌گذاری می‌کنیم. می‌توانید این کد را در کنسول مرورگر خود اجرا کنید.

// Define a string.
const stringToEncode = 'Hello World!';

// Encode the string using btoa().
const encodedString = btoa(stringToEncode);

console.log(encodedString);

خروجی:

SGVsbG8gV29ybGQh

با اینکه btoa() استفاده ساده‌ای دارد، یک محدودیت مهم دارد: فقط با رشته‌های حاوی کاراکترهای ASCII به درستی کار می‌کند. اگر رشته‌ای شامل کاراکترهای غیر ASCII مانند é یا ü باشد، تابع خطای DOMException خواهد داد.

مثال:

// This will cause an error.
btoa('Hello, 世界!');

خروجی:

Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

رمزگشایی رشته Base64 با atob()

برای رمزگشایی یک رشته Base64، از تابع atob() استفاده می‌کنیم. این تابع عمل برعکس btoa() را انجام می‌دهد و رشته Base64 را به شکل اصلی آن بازمی‌گرداند.

نام atob برگرفته از دستور قدیمی یونیکس برای تبدیل “ASCII to binary” است.

مثال: با استفاده از رشته رمزگذاری‌شده 'SGVsbG8gV29ybGQh'، آن را به متن اصلی بازمی‌گردانیم:

// Define a Base64 encoded string.
const stringToDecode = 'SGVsbG8gV29ybGQh';

// Decode the string using atob().
const decodedString = atob(stringToDecode);

console.log(decodedString);

خروجی:

Hello World!

مثل btoa()، تابع atob() نیز فقط با رشته‌هایی که در مجموعه کاراکترهای ASCII قرار دارند کار می‌کند.

با هاست Node.js لیارا، اپلیکیشن‌های Node خودت رو روی بستر سریع، پایدار و امن اجرا کن.
✅ نصب فوری✅ منابع اختصاصی✅ دسترسی کامل SSH
خرید و راه‌اندازی هاست Node.js

مدیریت Unicode و کاراکترهای غیر ASCII

چون btoa() و atob() کاراکترهای Unicode را پشتیبانی نمی‌کنند، برای برنامه‌های بین‌المللی باید از روش دیگر استفاده کرد. راه‌حل پیشنهادی استفاده از APIهای TextEncoder و TextDecoder است که می‌توانند از انواع مختلف کدگذاری‌ها از جمله UTF-8 را مدیریت کنند.

این فرآیند دو مرحله دارد:

  • ابتدا رشته Unicode با استفاده از TextEncoder به یک توالی بایت UTF-8 تبدیل می‌شود.
  • سپس این بایت‌ها به رشته Base64 تبدیل می‌شوند.

توابع زیر روش مطمئنی برای رمزگذاری و رمزگشایی رشته‌های UTF-8 به Base64 و بالعکس ارائه می‌دهند:

// Function to encode a UTF-8 string to Base64
function utf8ToBase64(str) {
    const encoder = new TextEncoder();
    const data = encoder.encode(str);

    const binaryString = String.fromCharCode.apply(null, data);
    return btoa(binaryString);
}

// Function to decode a Base64 string to UTF-8
function base64ToUtf8(b64) {
    const binaryString = atob(b64);
    // Create a Uint8Array from the binary string.
    const bytes = new Uint8Array(binaryString.length);
    for (let i = 0; i < binaryString.length; i++) {
        bytes[i] = binaryString.charCodeAt(i);
    }
    const decoder = new TextDecoder();
    return decoder.decode(bytes);
}

// Example usage
const unicodeString = 'Hello, 世界!';
const encodedUnicode = utf8ToBase64(unicodeString);
console.log(`Encoded: ${encodedUnicode}`);

const decodedUnicode = base64ToUtf8(encodedUnicode);
console.log(`Decoded: ${decodedUnicode}`);

خروجی:


Encoded: SGVsbG8sIOS4lueVjCE=
Decoded: Hello, 世界!

این روش قابل اعتمادتر است و برای برنامه‌هایی که با متن‌های چندزبانه کار می‌کنند مناسب است.

نکات مهم در Node.js

در محیط Node.js، توابع btoa() و atob() روش استاندارد برای کار با Base64 نیستند. اگرچه در نسخه‌های جدید Node.js این توابع به‌صورت سراسری اضافه‌ شده‌اند تا سازگاری حفظ شود، روش رایج و قدرتمند برای این کار استفاده از آبجکت داخلی Buffer است.

Buffer برای مدیریت داده‌های باینری به‌صورت بهینه طراحی شده و می‌‌تواند داده‌ها را بین انواع کدگذاری‌ها، از جمله UTF-8 و Base64، تبدیل کند.

مثال زیر نحوه رمزگذاری و رمزگشایی Base64 در Node.js را نشان می‌دهد:

// Example string, which can include Unicode characters
const originalString = "Hello, 世界! 😊";

// Encode to Base64
// 1. Create a Buffer from the string, specifying its original encoding (utf-8).
const buffer = Buffer.from(originalString, 'utf-8');
// 2. Convert the Buffer to a Base64-encoded string.
const encodedString = buffer.toString('base64');

console.log(`Encoded: ${encodedString}`);


// Decode from Base64
// 1. Create a Buffer from the Base64 string, specifying its encoding.
const decodedBuffer = Buffer.from(encodedString, 'base64');
// 2. Convert the Buffer back to a UTF-8 string.
const decodedString = decodedBuffer.toString('utf-8');

console.log(`Decoded: ${decodedString}`);

خروجی:

Encoded: SGVsbG8sIOS4lueVjCEg8J+YgA==
Decoded: Hello, 世界! 😊

استفاده از API Buffer برای تمامی عملیات Base64 در Node.js توصیه می‌شود، زیرا این روش:

  • قدرتمند و مطمئن است،
  • از Unicode به‌صورت بومی پشتیبانی می‌کند،
  • و با سایر APIهای Node.js مانند fs برای کار با فایل‌ها یکپارچه است.

مقایسه btoa(), atob() و Buffer

ویژگیbtoa() / atob() (مرورگر)Buffer (Node.js)
محیطمرورگرNode.js
پشتیبانی از Unicodeخیر (نیاز به روش جایگزین)بله (UTF-8 به‌صورت بومی)
نوع دادهرشته‌ها (Latin1)داده‌های باینری، رشته‌ها، فایل‌ها
کاربرد اصلیرمزگذاری و رمزگشایی ساده رشته‌هاپردازش داده‌های باینری با کارایی بالا

کاربردهای عملی Base64

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

مقدمه‌ای بر الگوریتم رمزنگاری Base64
Base64

جاسازی فایل‌ها در HTML و CSS

یکی از رایج‌ترین کاربردهای Base64، جاسازی فایل‌های کوچک به‌صورت مستقیم در HTML یا CSS با استفاده از Data URIها است . این روش برای تصاویر کوچک، آیکون‌ها و فونت‌هایی که برای بارگذاری اولیه صفحه حیاتی هستند، بسیار موثر است.

نحوه کار: با رمزگذاری فایل به Base64 و جاسازی آن، مرورگر نیازی به درخواست HTTP جداگانه برای دریافت آن فایل ندارد. این کار می‌تواند زمان بارگذاری اولیه صفحه را کاهش دهد.

مثال HTML: به جای لینک دادن به یک فایل تصویر، می‌توانید آن را مستقیما در تگ <img> قرار دهید.

<img src="/path/to/logo.png" alt="My Logo">

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..." alt="My Logo">

مثال CSS: می‌توانید تصاویر پس زمینه را در استایل‌ها جاسازی کنید.

.icon-user {
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ....");
}

نکته: این روش تعداد درخواست‌های HTTP را کاهش می‌دهد، اما حجم فایل HTML یا CSS را افزایش می‌دهد و ممکن است بر کش مرورگر تاثیر بگذارد، زیرا فایل جاسازی شده نمی‌تواند به‌صورت جداگانه کش شود. بنابراین این روش برای فایل‌های بسیار کوچک و حیاتی مناسب است.

ارسال داده‌های باینری در قالب‌های مبتنی بر متن

APIهایی که از قالب‌های متنی مانند JSON یا XML استفاده می‌کنند، نمی‌توانند داده‌های باینری را به‌صورت مستقیم پردازش کنند. اگر نیاز دارید فایلی مانند عکس پروفایل آپلود شده توسط کاربر یا PDF تولید شده را ارسال کنید، Base64 راه‌حل استاندارد است.

نحوه کار: فایل باینری در سمت کلاینت به رشته Base64 تبدیل می‌شود. این رشته سپس به‌عنوان یک فیلد استاندارد در شی JSON قرار می‌گیرد. سرور JSON را دریافت کرده، رشته Base64 را استخراج و دوباره به فایل باینری اصلی تبدیل می‌کند.

مثال JSON:

{
"username": "alex_doe",
"email": "alex@example.com",
"profilePicture": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQ...",
"pictureMimeType": "image/jpeg"
}

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

روش احراز هویت پایه HTTP از Base64 برای رمزگذاری نام کاربری و رمز عبور استفاده می‌کند. نام کاربری و رمز عبور در قالب username:password ترکیب شده و Base64 می‌شوند، سپس در هدر Authorization ارسال می‌شود.

نحوه کار: کلاینت اطلاعات را رمزگذاری کرده و با هر درخواست ارسال می‌کند.

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

سرور مقدار dXNlcm5hbWU6cGFzc3dvcmQ= را دوباره رمزگشایی کرده و برای احراز هویت استفاده می‌کند.

نکته مهم: این روش برای اتصال HTTP ناامن امن نیست، زیرا Base64 به راحتی قابل برگشت است. بنابراین فقط باید روی HTTPS استفاده شود، جایی که تمام درخواست، شامل هدرها، رمزگذاری می‌شود.

ذخیره داده‌های باینری در فیلدهای متنی

برخی سیستم‌ها، مانند برخی تنظیمات پایگاه داده، سیستم‌های قدیمی یا فرمت‌های فایل پیکربندی (مثلا فایل‌های .env)، فقط متن را پشتیبانی می‌کنند. Base64 به شما اجازه می‌دهد داد‌ه‌‌های باینری کوچک را در این سیستم‌ها ذخیره کنید.

  • مثال کاربردی: ممکن است نیاز داشته باشید یک تصویر کوچک، فایل کلید پیکربندی یا امضای دیجیتال را مستقیما در یک ستون متنی پایگاه داده ذخیره کنید.
  • نمونه: ذخیره آیکون کوچک آواتار در یک فیلد TEXT پایگاه داده. برنامه قبل از ذخیره تصویر را به Base64 تبدیل و بعد از بازیابی دوباره آن را رمزگشایی می‌کند.
۱۰ ترفند جاوا اسکریپت که فقط توسعه‌دهندگان حرفه‌ای از آن‌ها خبر دارند!
۱۰ ترفند جاوا اسکریپت 

چالش‌ها و بهترین شیوه‌ها

اگرچه Base64 استانداردی راحت و پرکاربرد است، استفاده نادرست از آن می‌تواند منجر به مشکلات امنیتی و عملکردی شود. شناخت محدودیت‌های آن برای استفاده صحیح و ضروری است.

امنیت: Base64 رمزنگاری نیست

یک تصویر رایج اشتباه این است که ظاهر عجیب و رمزگونه یک رشته Base64، امنیت ایجاد می‌کند. این تصور غلط است و می‌تواند باعث پیاده‌سازی‌های ناامن شود.

اشتباه رایج:

Base64 یک روش کدنویسی (Encoding) است، نه الگوریتم رمزنگاری. این فرآیند عمومی و قابل برگشت است. هیچ کلید مخفی برای رمزگشایی آن لازم نیست و هرکسی که رشته کد شده را داشته باشد، می‌تواند آن را به شکل اصلی خود بازگرداند. بنابراین استفاده از Base64 برای محافظت از داده‌های حساس مثل پسورد، کلید API یا اطلاعات شخصی، امنیت واقعی ایجاد نمی‌کند.

بهترین روش‌ها:

  • هرگز از Base64 برای مخفی کردن یا محافظت از داده‌های حساس استفاده نکنید.
  • برای محرمانگی داده‌های از الگوریتم‌های رمزنگاری مناسب مانند AES استفاده کنید.
  • برای ذخیره پسوردها، از الگوریتم‌های قوی یک‌طرفه با Salt مانند Argon2 یا bcrypt استفاده کنید.
  • همیشه داده‌ها را از طریق کانال امن مثل HTTPS منتقل کنید، اما به یاد داشته باشید که این کار محافظت از داده‌ها را زمانی که به‌صورت Base64 ذخیره یا لاگ شده‌اند، تضمین نمی‌کند.

عملکرد: حجم داده و پهنای باند

رمزگذاری Base64 همیشه حجم داده‌ها را افزایش می‌دهد. فرمول ساده است: 3 بایت داده باینری به 4 کاراکتر متنی تبدیل می‌شود.

اشتباه رایج:

این موضوع باعث افزایش حدود 33% حجم داده (به‌علاوه مقدار کمی برای Padding) می‌شود.

  • یک تصویر 100 کیلوبایتی تقریبا به 133 کیلوبایت تبدیل می‌شود.
  • یک ویدیو 10 مگابایتی تقریبا به 13.3 مگابایت می‌رسد.

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

بهترین روش‌ها:

  • از Base64 برای فایل‌های بزرگ استفاده نکنید. به‌طور کلی برای فایل‌های بیش از چند ده کیلوبایت بهتر است جایگزین دیگری پیدا کنید.
  • برای انتقال فایل‌ها، آپلودهای کاربر، از multipart/form-data استفاده کنید. این مکانیزم استاندارد HTTP برای ارسال داده باینری بدون افزایش حجم اضافی است.
  • برای ارائه فایل‌های رسانه‌ای بزرگ، آن‌ها را مستقیم لینک دهید تا مرورگر مدیریت دریافت و کش را انجام دهد.

عملکرد: مصرف CPU

فرآیند تبدیل داده باینری به رشته Base64 نیاز به منابع محاسباتی دارد.

اشتباه رایج:

با اینکه CPUهای مدرن عملیات Base64 را برای داده‌ای کوچک سریع انجام می‌دهند، این فرآیند می‌تواند برای داده‌های بزرگ به یک گلوگاه عملکردی تبدیل شود.

مثال‌ها:

  • سمت کلاینت: رمزگذاری یک فایل بزرگ (مثلا تصویر چند مگابایتی) در مرورگر ممکن است باعث شود رابط کاربری موقتا فریز شود.
  • سمت سرور: API که مرتبا حجم‌‌های بزرگ Base64 را رمزگذاری یا رمزگشایی می‌کند، ممکن است با مصرف بالای CPU مواجه شده و زمان پاسخ‌دهی و هزینه سرور افزایش یابد.

بهترین روش‌ها:

  • عملکرد برنامه را پروفایل کنید. اگر مشکلات عملکردی مشاهده شد، بررسی کنید آیا عملیات Base64 عامل آن است یا خیر.
  • هر زمان که ممکن بود، مستقیما با داده باینری کار کنید، مثلا استفاده از Blob در مرورگر یا Buffer streams در Node.js تا از چرخه‌های رمزگذاری و رمزگشایی غیرضروری جلوگیری شود.
12 پروژه متن‌ باز فول‌ استک جاوا اسکریپت که نباید از دست بدهید!
پروژه متن‌ باز فول‌ استک

کش مرورگر: تاثیر داده‌های جاسازی شده

جاسازی منابع‌ به‌صورت Data URI می‌تواند با مکانیزم کش مرورگر تداخل ایجاد کند.

اشتباه رایج:

هنگامی که یک منبع در CSS یا HTML جاسازی می‌شود، بخشی از آن فایل محسوب می‌شود. مرورگر نمی‌تواند منابع را به‌صورت جداگانه کش کند. اگر بخشی از فایل اصلی تغییر کند؛ کل فایل باید دوباره دانلود شود. در مقابل، منابع‌های لینک‌شده به‌صورت خارجی می‌توانند به‌طور مستقل و طولانی کش شوند.

بهترین روش‌ها:

  • از Data URI برای فایل‌های کوچک و حیاتی که برای بارگذاری اولیه صفحه ضروری هستند (مانند لوگو یا آیکون بالای صفحه) استفاده کنید.
  • برای منابع‌های بزرگ، غیرضروری یا پرکاربرد، آن‌ها را به‌صورت فایل جداگانه لینک دهید تا مرورگر بتواند به‌صورت موثر کش کند و زمان بارگذاری در بازدیدهای بعدی کاهش یابد.

جمع بندی

Base64 برای تبدیل داده‌های باینری به متن مفید است، اما نباید به‌عنوان روشی برای امنیت از آن استفاده شود؛ چون هر کسی می‌تواند داده را به‌راحتی بازگرداند. همچنین این روش باعث افزایش حجم داده و کاهش کارایی می‌شود. بنابراین، فقط در موارد خاص مثل تصاویر یا آیکون‌های کوچک از Base64 استفاده کنید و برای داده‌های حساس، از رمزنگاری و انتقال امن مانند HTTPS بهره بگیرید.

به اشتراک بگذارید