رمزنگاری لایه انتقال در شبکه‌های خصوصی مجازی نیازمند الگوریتم‌های متقارنی است که توان پردازشی بالا را با مقاومت در برابر کانال‌های جانبی سخت‌افزاری ترکیب کنند. برای سال‌ها، الگوریتم استاندارد رمزگذاری پیشرفته در حالت گالوا/شمارنده (AES-GCM) گزینه پایه در پروتکل‌های سازمانی مانند IPsec و OpenVPN بود. با این حال، در دستگاه‌هایی که فاقد دستورالعمل‌های سخت‌افزاری اختصاصی هستند، AES-GCM با افت سرعت و خطرات امنیتی مواجه می‌شود.

هنگامی که پیاده‌سازی‌های نرم‌افزاری بر روی مسیریاب‌های تعبیه‌شده یا تراشه‌های فاقد شتاب‌دهنده AES-NI یا ARMv8 اجرا می‌شوند، ناچار به جداول جستجوی حافظه (S-box) وابسته هستند. دسترسی به این نشانی‌های حافظه نوسان‌های زمانی ایجاد می‌کند و کلیدهای محرمانه را در معرض تحلیل زمانی حافظه پنهان قرار می‌دهد. علاوه بر این، ضرب GHASH در میدان گالوا $\mathbb{F}_{2^{128}}$ بدون واحدهای سخت‌افزاری ضرب بدون رقم نقلی (PCLMULQDQ) فشار سنگینی به پردازنده تحمیل می‌سازد.

پروتکل WireGuard با استانداردسازی انحصاری روی الگوریتم ChaCha20-Poly1305 AEAD که در RFC 8439 تعریف شده، این وابستگی را از میان برداشته است. این الگوریتم با تکیه بر ساختار جبری جمع-چرخش-XOR (موسوم به ARX) و مهار ریاضی کلید، بازدهی محاسباتی با زمان ثابت را در تمامی مدل‌های پردازنده ارائه می‌دهد.

چشم‌انداز رمزنگاری در غیاب شتاب‌دهنده سخت‌افزاری AES

برای پی بردن به دلایل چرخش پروتکل‌های مدرن از AES-GCM در تجهیزات مختلف، باید نحوه اجرای رمزهای بلوکی را ارزیابی کرد. الگوریتم AES بر شبکه جانشینی-جایگشت استوار است. مرحله غیرخطی جانشینی بایت‌ها (SubBytes) بایت‌های ورودی ۸ بیتی را از طریق جدول اس‌باکس ریندال پردازش می‌نماید.

در نرم‌افزارهایی که فاقد دستورات سخت‌افزاری هستند، این محاسبات در قالب چهار جدول یک کیلوبایتی در حافظه ذخیره می‌شوند:

// تابع دور AES نرم‌افزاری با مراجعه به جداول اس‌باکس
state[0] = Te0[(s0 >> 24)       ] ^ Te1[(s1 >> 16) & 0xff] ^ 
           Te2[(s2 >>  8) & 0xff] ^ Te3[(s3      ) & 0xff] ^ rk[0];

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

در نقطه مقابل، ChaCha20 هرگونه جدول حافظه را کنار می‌گذارد. این رمز جریانی منحصراً بر پایه سه عمل پایه‌ای واحد محاسبات و منطق (ALU) کار می‌کند: جمع به پیمانه $2^{32}$، چرخش بیتی با فواصل معین، و عملگر XOR. تمامی این دستورها در تعداد چرخه‌های کلاک کاملاً ثابت اجرا شده و ذاتاً در برابر حملات تحلیل زمانی حافظه پنهان نفوذناپذیرند.

فلسفه طراحی ARX و ماتریس وضعیت ۴ در ۴ در ChaCha20

الگوریتم ChaCha20 طراحی‌شده توسط دانیل برنشتاین بر روی یک وضعیت درونی ۵۱۲ بیتی عمل می‌کند که در قالب یک ماتریس ۴ در ۴ از شانزده کلمه ۳۲ بیتی سازمان‌دهی شده است:

+---------------+---------------+---------------+---------------+
|  Constant 0   |  Constant 1   |  Constant 2   |  Constant 3   |
|  0x61707865   |  0x3320646e   |  0x79622d32   |  0x6b206574   |
+---------------+---------------+---------------+---------------+
|  Key Word 0   |  Key Word 1   |  Key Word 2   |  Key Word 3   |
+---------------+---------------+---------------+---------------+
|  Key Word 4   |  Key Word 5   |  Key Word 6   |  Key Word 7   |
+---------------+---------------+---------------+---------------+
| Block Counter |    Nonce 0    |    Nonce 1    |    Nonce 2    |
+---------------+---------------+---------------+---------------+

ترتیب قرارگیری داده‌ها یکپارچگی رمزنگاری را حفظ می‌کند:

  • کلمه‌های 0 تا 3: عبارت متنی ثابت ۱۲۸ بیتی "expand 32-byte k" برای غیرصفر نگه‌داشتن وضعیت پایه.
  • کلمه‌های 4 تا 11: کلید متقارن ۲۵۶ بیتی نشست.
  • کلمه 12: شمارنده بلوک ۳۲ بیتی که پس از تولید هر ۶۴ بایت داده اضافه می‌شود.
  • کلمه‌های 13 تا 15: نشانه یک‌بارمصرف ۹۶ بیتی (Nonce).

تحول وضعیت درونی بر پایه تابع یک‌چهارم دور QR(a, b, c, d) صورت می‌پذیرد:

// تابع یک‌چهارم دور ChaCha20
#define ROTL32(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
#define QR(a, b, c, d) { \
    a += b; d ^= a; d = ROTL32(d, 16); \
    c += d; b ^= c; b = ROTL32(d, 12); \
    a += b; d ^= a; d = ROTL32(d,  8); \
    c += d; b ^= c; b = ROTL32(d,  7); \
}

یک مرحله کامل ChaCha20 شامل ۲۰ دور چرخش (۱۰ دور روی ستون‌ها و ۱۰ دور روی قطرها) است. در انتها، وضعیت حاصل با ماتریس اولیه جمع شده و با ۶۴ بایت داده خام XOR می‌شود. از آنجا که محاسبات تنها در ثبات‌های پردازنده انجام می‌پذیرد، هیچ انشعاب شرطی یا نوسان زمانی رخ نمی‌دهد.

احراز اصالت با Poly1305 و مهار ریاضی کلید

تنها پنهان‌سازی اطلاعات کافی نیست؛ بدون بررسی صحت داده، بسته‌های رمزشده در مسیر دستکاری می‌شوند. ترکیب ChaCha20 با کد اصالت‌سنجی Poly1305 ساختار کامل AEAD را به وجود می‌آورد.

الگوریتم Poly1305 یک سیستم ارزیابی چندجمله‌ای کارتر-وگمن بر روی میدان اول $\mathbb{F}_{2^{130}-5}$ است. پیام رمزشده به قطعات ۱۶ بایتی بخش‌بندی شده و هر بخش به عنوان ضریب چندجمله‌ای قرار می‌گیرد:

$$A(r) = \left( \sum_{i=1}^{L} c_i \cdot r^{L-i+1} \right) \pmod{2^{130}-5} + s \pmod{2^{128}}$$

کلید احراز اصالت ۲۵۶ بیتی $(r, s)$ به شکل مستقیم از بلوک شماره صفر تولیدشده توسط ChaCha20 برای همان بسته مشخص استخراج می‌شود:

  • کلمه‌های 0 تا 3 کلید ارزیابی چندجمله‌ای $r$ را می‌سازند.
  • کلمه‌های 4 تا 7 کلید ماسک محرمانه $s$ را تأمین می‌کنند.

برای ممانعت از سرریز ارقام نقلی در ضرب‌های چندبخشی، کلید $r$ پیش از محاسبه تحت مهار بیتی (clamping) قرار می‌گیرد:

// مهار بیتی کلید Poly1305 طبق سند RFC 8439
r[3] &= 15;  r[7] &= 15;  r[11] &= 15; r[15] &= 15;
r[4] &= 252; r[8] &= 252; r[12] &= 252;

این مهار ۲۲ بیت مشخص را در کلید $r$ پاک می‌کند. این محدودیت تضمین می‌کند که مقدار $r < 2^{124}$ بماند و پردازنده‌های ۳۲ و ۶۴ بیتی بتوانند ضرب و کاهش پیمانه‌ای را با جابه‌جایی و جمع سریع بدون سرریز ارقام میانی به سرانجام برسانند.

ساختار بسته‌های WireGuard در مقایسه با استاندارد RFC 8439

اگرچه RFC 8439 ساختاری کلی برای اینترنت ارائه می‌کند، WireGuard این چارچوب را برای بسته‌های شبکه بهینه‌سازی نموده است:

ساختار استاندارد RFC 8439: [ شمارنده ۳۲ بیتی ] [ نشانه تصادفی ۹۶ بیتی ] -> احراز اصالت AAD و داده
ساختار بهینه‌شده WireGuard:  [ ۳۲ بیت صفر ] [ شمارنده ۶۴ بیتی بسته ]    -> ارسال شفاف شمارنده در سربرگ

در طراحی WireGuard:

  1. شمارنده ۶۴ بیتی: سربرگ هر بسته داده حاوی یک شمارنده ۶۴ بیتی آشکار است که با برقراری نشست روی صفر تنظیم شده و با هر بسته ارسالی افزایش می‌یابد.
  2. ساخت نشانه ۹۶ بیتی: نشانه مورد نیاز ChaCha20 از اتصال ۳۲ بیت صفر با مقدار ۶۴ بیتی شمارنده حاصل می‌شود.
  3. بازتولید دوره‌ای کلید: در صورتی که یک کلید با یک نشانه تکراری دو بار استفاده شود، امنیت Poly1305 دچار آسیب جدی می‌شود. پروتکل WireGuard پس از ارسال $2^{60}$ بسته یا گذشت ۱۲۰ ثانیه، تغییر کلید را اجباری می‌سازد.

به دلیل آن که شناسه Poly1305 اصالت داده‌ها را تضمین می‌کند و مشخصات گیرنده از طریق جدول Cryptokey Routing چک می‌شود، بسته‌های عادی نیازی به فیلدهای اضافه AAD ندارند.

شتاب‌بخشی پردازش موازی SIMD با AVX2 و ARM NEON

یک ویژگی برجسته ChaCha20 امکان‌پذیری ذاتی پردازش موازی است. بر خلاف رمزهای زنجیره‌ای، تولید جریان کلید در بلوک‌های ChaCha20 کاملاً مستقل از یکدیگر است.

این ویژگی استفاده از دستورات برداری را ممکن می‌سازد:

  • معماری ARM NEON: در تراشه‌های تلفن همراه، ثبات‌های ۱۲۸ بیتی دو تابع یک‌چهارم دور را هم‌زمان به انجام می‌رسانند.
  • معماری x86_64 AVX2: ثبات‌های ۲۵۶ بیتی چهار بلوک ۶۴ بایتی کامل را به طور موازی پردازش کرده و در هر مرحله ۲۵۶ بایت داده تولید می‌کنند.
  • معماری x86_64 AVX-512: ثبات‌های ۵۱۲ بیتی هشت بلوک را به طور هم‌زمان پیش برده و بازدهی را به ۵۱۲ بایت در هر دور می‌رسانند.

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

تدابیر ایمنی حافظه و پردازش چند‌هسته‌ای در RiceGuard

در دروازه‌های شبکه پرظرفیت، ساختار RiceGuard کارایی ChaCha20-Poly1305 را ارتقا می‌دهد:

  1. توزیع موازی ترافیک: با بهره‌گیری از بستر هسته لینوکس (padata)، بسته‌های ورودی پیش از بازگشایی میان تمام هسته‌های فعال پردازنده پخش می‌شوند.
  2. اعتبارسنجی در زمان ثابت: شناسه Poly1305 با توابع مقایسه با زمان ثابت (crypto_memneq) ارزیابی می‌شود و در صورت هرگونه عدم انطباق، بسته پیش از رمزگشایی حذف می‌گردد.
  3. امحای بلادرنگ حافظه کلید: پس از اتمام احراز اصالت، مقادیر موقت کلید ($r, s$) با دستور memzero_explicit از حافظه موقت پاک می‌شوند.

هماهنگی میان ساختار ARX، محاسبات بدون انشعاب و کنترل دقیق حافظه، سامانه‌ای سریع، مطمئن و محفوظ در برابر حملات کانال جانبی پدید می‌آورد.

دانلود VPNRice