سالسا۲۰
گونهٔ ChaCha

| 0 | 1 |
| --- | --- |
تابع ربع دور ChaCha. چهار نسخه کپی موازی تشکیل یک دور می‌دهند.: تابع ربع دور ChaCha. چهار نسخه کپی موازی تشکیل یک دور می‌دهند.
عمومی: عمومی
طراحان: Daniel J. Bernstein
تاریخ اولین انتشار: 2008
مشتق‌شده از: Salsa20
مرتبط با: Rumba20
در سال 2008، برنشتاین خانواده رمزهای نزدیک "ChaCha" را منتشر کرد، که هدف آنها افزایش نسبت پراکنش بر هر دور در عین رسیدن به کارایی یکسان یا کمی بهتر است. مقالهٔ Aumasson و همکاران، همچنین به ChaCha حمله می‌کند و به یک دور کمتر می‌رسد: برای ChaCha6 با ۲۵۶ بیت با پیچیدگی2139 و ChaCha7 با پیچیدگی 2248. ChaCha6 با ۱۲۸ بیت در محدوده ی2107 اما ادعا می‌کند که این حمله نمی‌تواند ChaCha7 با ۱۲۸ بیت را بشکند.
مانند Salsa20، جالت اولیه ChaCha شامل یک ثابت ۱۲۸ بیتی، یک کلید ۲۵۶ بیتی، یک شمارنده ۶۴ بیتی و یک نانس ۶۴ بیتی می‌شود که به صورت یک ماتریس ۴ × ۴ از کلمه‌های ۳۲ بیتی تنظیم شده‌است اما ChaCha بعضی از کلمات را در حالت اولیه دوباره مرتب می‌کند:
| 0 | 1 | 2 | 3 |
| --- | --- | --- | --- |
| "te k" | "2-by" | "nd 3" | "expa" |
کلید: کلید
کلید: کلید
| نانس | نانس | موقعیت | موقعیت |
ثابت همانند Salsa20است ("expand 32-byte k"). ChaCha ربع دور در Salsa20 یعنی QR(a, b, c, d) را با تابع زیر جایگزین می‌کند:
a += b; d ^= a; d <<<= 16;
c += d; b ^= c; b <<<= 12;
a += b; d ^= a; d <<<= 8;
c += d; b ^= c; b <<<= 7;
توجه کنید که این نسخه هر کلمه را دو بار به روز می‌کند، در حالی که ربع دور Salsa20 هر کلمه را فقط یک بار به روز می‌کند. علاوه بر این، ربع دور ChaCha تغییرات را با سرعت بیشتری پراکنده می‌کند. به‌طور متوسط، پس از تغییر ۱ بیت از ورودی، ربع دور Salsa20، تعداد ۸ بیت خروجی را تغییر خواهد داد در حالی که ChaCha تعداد ۱۲٫۵ بیت خروجی را تغییر می‌دهد.
تعداد جمع‌ها، xorها و چرخش‌های بیتی در ربع دور ChaCha با ربع دور Salsa20 یکسان است ولی این واقعیت که دوتا از چرخش‌ها از مضارب ۸ هستند، باعث می‌شود که بهینه‌سازی کوچکی در برخی از معماری‌ها از جمله x86 انجام شود. علاوه بر این، قالب بندی ورودی به گونه ای دوباره تنظیم شده‌است تا از یک بهینه‌سازی اجرای کارآمد از SSE که برای Salsa20 کشف شده، پشتیبانی کند. به جای اینکه دورها بین ستون‌ها و ردیف‌ها متناوب باشد، بین ستون‌ها و در امتداد قطرهای مورب اجرا می‌شوند. ChaCha همانند Salsa20 شانزده کلمه ۳۲ بیتی را در یک ماتریس ۴ × ۴ مرتب می‌کند. اگر به عناصر ماتریس اندیسهای از ۰ تا ۱۵ نسبت دهیم:
| 0 | 1 | 2 | 3 |
| --- | --- | --- | --- |
| ۳ | ۲ | ۱ | ۰ |
| ۷ | ۶ | ۵ | ۴ |
| ۱۱ | ۱۰ | ۹ | ۸ |
| ۱۵ | ۱۴ | ۱۳ | ۱۲ |
در ادامه ربع دور در ChaCha بصورت زیر خواهد بود:
// دور فرد
QR(0, 4,  8, 12) // ستون اول
QR(1, 5,  9, 13) // ستون دوم
QR(2, 6, 10, 14) // ستون سوم
QR(3, 7, 11, 15) // ستون چهارم
// دور زوج
QR(0, 5, 10, 15) // قطر 1 (قطر اصلی)
QR(1, 6, 11, 12) // قطر 2
QR(2, 7,  8, 13) // قطر 3
QR(3, 4,  9, 14) // قطر 4
ChaCha20 از ۱۰ تکرار دور دوتایی استفاده می‌کند. یک پیاده‌سازی از این رمز در زبان C/C++ در کد قابل مشاهده است.
#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
#define QR(a, b, c, d) (   \
a += b,  d ^= a,  d = ROTL(d,16), \
c += d,  b ^= c,  b = ROTL(b,12), \
a += b,  d ^= a,  d = ROTL(d, 8), \
c += d,  b ^= c,  b = ROTL(b, 7))
#define ROUNDS 20

void chacha_block(uint32_t out[16], uint32_t const in[16])
{
int i;
uint32_t x[16];

for (i = 0; i < 16; ++i)
x[i] = in[i];
// 10 loops × 2 rounds/loop = 20 rounds
for (i = 0; i < ROUNDS; i += 2) {
// Odd round
QR(x[0], x[4], x[8], x[12]); // column 0
QR(x[1], x[5], x[9], x[13]); // column 1
QR(x[2], x[6], x[10], x[14]); // column 2
QR(x[3], x[7], x[11], x[15]); // column 3
// Even round
QR(x[0], x[5], x[10], x[15]); // diagonal 1 (main diagonal)
QR(x[1], x[6], x[11], x[12]); // diagonal 2
QR(x[2], x[7], x[8], x[13]); // diagonal 3
QR(x[3], x[4], x[9], x[14]); // diagonal 4
}
for (i = 0; i < 16; ++i)
out[i] = x[i] + in[i];
}
ChaCha اساس کار تابع هش بلیک است، یک فینالیست در رقابت تابع هش NIST و جانشین BLAKE2 که برای سرعت حتی بالاتر تنظیم شده‌است. این رمز همچنین با استفاده از شانزده کلمه ۶۴ بیتی (۱۰۲۴ بیت حالت)، گونه ای را با ثابت‌های چرخش تنظیم شدهی مطابق تعریف می‌کند.