الگوریتم SHA-256

SHA256 یک تابع و الگوریتم هشینگ است که در صنایع مختلفی از جمله ارتباطات، مجوزهای امنیتی نظیر SSL و IPsec، بلاک چین و رمز ارزها و موارد بسیار دیگر کاربرد دارد. در این مطلب، ابتدا تاریخچه ساخت و توسعه الگوریتم SHA-256 را بررسی کرده و سپس به کاربردهای مختلف، نحوه کار و استفاده از آن برای رمزنگاری در فضای بلاک چین و استخراج ارز دیجیتال از جمله بیت کوین می‌پردازیم.

الگوریتم SHA 256 چیست؟

SHA که عموما «شا» خوانده می‌شود، مخفف عبارت “Secure Hash Algorithm” به‌معنای «الگویتم هش امن» است که برای رمزنگاری داده‌ها به‌کار می‌رود. SHA یک خانواده بزرگ از توابع هش مختلف شامل دو خانواده SHA-1 و SHA-2 است که هر کدام ورودی‌های دارای طول‌های متغیر را گرفته و آن‌ها را به یک خروجی با طول ثابت تبدیل می‌کنند.

الگوریتم هشینگ SHA-256 زیرمجموعه خانواده SHA-2 محسوب می‌شود که به‌خاطر قدرت و امنیت بسیار بالای خود، در صنایع مختلف از جمله بلاک چین و معتبرسازی یکپارچگی اطلاعات ذخیره‌شده در بلاک‌ها هنگام استخراج ارزهای دیجیتالی از جمله بیت کوین کاربرد دارد.

تاریخچه ساخت تابع SHA-256

مشابه اکثر مفاهیم حوزه کریپتوگرافی، الگوریتم SHA نیز طی دوران جنگ توسعه داده شد. این الگوریتم رمزنگاری حاصل همکاری و تلاش‌های آژانس امنیت ملی ایالت متحده (NSA) و موسسه ملی فناوری و استاندارد (NIST) است.

در سال 1993، اولین پروتکل SHA به‌نام SHA-0 معرفی شد. با این حال، سازندگان طی مدت کوتاهی پس از انتشار، این الگوریتم را به‌خاطر یک «نقص فاحش» کنار گذاشته و ورژن بهبودیافته آن به‌نام SHA-1 (بخوانید شا وان) را منتشر کردند. در سال 2001، الگوریتم SHA-2 (بخوانید شا تو) معرفی شد که ابتدا دارای چهار نسخه بود و بعدا دو نسخه دیگر تکامل‌یافته نیز به آن اضافه شدند.

بنابراین در حالت کلی، خانواده SHA را به دو زیرخانواده SHA-1 و SHA-2. تقسیم می‌کنند:

  • SHA-1
  • SHA-2
    • SHA-224
    • SHA-256
    • SHA-384
    • SHA-512
    • SHA-512/224
    • SHA-512/256

تفاوت خانواده توابع هش SHA-1 و SHA-2 در طول خروجی آن‌هاست. SHA-1 دارای خروجی 160 بیتی و SHA-2 بسته به پسوند پس از آن، دارای خروجی‌های 224، 256، 238 و 512 بیتی هستند.

امنیت الگوریتم هش SHA-256 چقدر است؟

بر خلاف SHA-1، تابع هشینگ SHA-2 به امنیت و سرعت بالای خود شناخته می‌شود. بنابراین، SHA256 که زیرگروه خانواده بزرگ SHA-2 است نیز امنیت بسیار بالایی دارد. در مواردی نظیر مکانیزم اثبات کار (PoW) استخراج بیت کوین که در آن کلیدها تولید نمی‌شوند، یک تابع هشینگ پرسرعت نظیر SHA-256 کارایی بالایی دارد.

همانطور که گفتیم، این الگوریتم توسط NSA و NIST توسعه داده شده است که با مراجعه به سند FIPS 180-4 موسسه ملی استانداردها و فناوری می‌توانید جزئیات بیشتر آن را مطالعه نمایید.

الگوریتم هشینگ SHA256 چگونه کار می‌کند؟

برای درک نحوه کار تابع SHA-256 (که شا-تو فیفتی سیکس خوانده می‌شود)، ابتدا باید با مفهوم تابع هش آشنا شویم. در ادامه این قسمت، ابتدا نحوه کار هش فانکشن را بررسی کرده و سپس با بررسی جزئیات یک تابع SHA256، یک نمونه مثال عملی را با هم بررسی می‌کنیم.

تابع هش چیست؟

برای درک نحوه کار الگوریتم SHA-256، اول باید به این سوال پاسخ دهیم که تابع هش (Hash Function) چیست و چگونه کار می‌کند؟ هش فانکشن یک تابع است که یک مقدار ورودی (عموما قابل خوانش برای انسان) را گرفته و آن را به یک خروجی از رشته حروف و اعداد با طول مشخص تبدیل می‌کند. به این کار، هش کردن یا هشینگ می‌گویند. به خود مقدار هش خروجی و نهایی نیز گاهی اوقات «دایجست (Digest)» گفته می‌شود.

مثالی از تابع هش

مثلا فرض کنید می‌خواهیم مجموعه «ارباب حلقه‌ها (Lord of The Rings)» نوشته «جان رونالد ریول تالکین (John Ronald Reuel Tolkien)» را به‌عنوان ورودی گرفته و با استفاده از الگوریتم SHA256، به یک هش تبدیل کنیم. با این کار، خروجی ما یک رشته منحصربه‌فرد 256 بیتی (32 بایت) خواهد بود که گاهی اوقات به آن “FingerPrint” یا «اثر انگشت» نیز می‌گویند. این خروجی برای عبارت “Lord of The Rings” همیشه یکسان خواهد بود. حالا در صورتی که حتی یک حرف در عبارت “Lord of The Rings” را تغییر دهیم، یک هش منحصربه‌فرد کاملا جدید و متفاوت خواهیم داشت.

البته از آنجایی که طول رشته خروجی یک تابع هش محدود است، این خروجی را «تقریبا منحصربه‌فرد» می‌نامند. مثلا به‌خاطر 256 بیتی بودن طول رشته خروجی‌های تابع هش SHA-256، همیشه یک خروجی تقریبا منحصربه‌فرد با طول ثابت 256 بیتی خواهیم داشت. با این وجود، طول ورودی یک تابع هش نامحدود است که می‌تواند در برخی موارد نارد به یک خروجی یکسان منجر شود. به این اتفاق بسیار نادر، «تصادم» یا “Collision” می‌گویند. البته از آنجایی که در یک تابع SHA 256 تعداد خروجی‌ها برابر 256^2 است، احتمال رخداد این اتفاق بسیار بعید و معادل رقم زیر خواهد بود:

115,792,089,237,316,195,423,570,985,008,687,907,853,269,984,665,640,564,039,457,584,007,913,129,639,936

3 هدف یک تابع هش شامل موارد زیر است:

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

گام‌های الگوریتم هشینگ SHA-256

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

  1. مرحله Padding – گرفتن ورودی و تبدیل آن به مضربی از 512 بیت دارای 64 بیت کمتر.
  2. گرفتن پیام و شکستن آن به N بلاک 512 بیتی
  3. تکرار مرحله 2 روی تمام بلاک‌ها:
    1. مقداردهی به Message Schedule؛ دنباله‌ای از 64 کلمه 32 بیتی (هر بلاک دارای 8 کلمه)
    2. مقداردهی به هشت متغیر a … h با مقادیر هش H0 … H7 حاصل از تکرار قبل (برای تکرار اول، H0 … H7 با یک عدد ثابت مقداردهی می‌شوند).
    3. انجام 64 تکرار که در آن‌ها متغیرهای a … h به‌روش خاصی چرخانده (Rotate) می‌شوند. این فرآیند، قلب تابع هشینگ ماست. در این مرحله، پیام با استفاده از تعداد بالایی ترکیب بیتی وارد تابع هش می‌شود.
    4. محاسبه مقادیر میانی هش جدید H0 … H7 به‌صورت H0 = H0 + a و H1 = H1 + b و به همین ترتیب تا آخر.
  4. الحاق H0 … H7 به‌عنوان دایجست (نتیجه) پیام و بازگردانی آن.

الگوریتم هش SHA-256 شامل 64 دور عملیات در هر بلاک است. هر بلاک نیز 512 بیت ورودی دارد که هر کدام به هشت کلمه 32 بیتی شکسته می‌شوند. حالا Message Schedule به حرکت این کلمات داخل الگوریتم اتلاق می‌شود.

چرخش یا Rotation هم فرآیندی مشابه شیفت دادن است، با این تفاوت که اعداد بیرون افتاده از یک انتها، از یک انتهای دیگر وارد می‌شوند. مثلا فرض کنید یک کلمه 8 بیتی به‌صورت 11100101 ذخیره شده است. 3 چرخش از چپ یعنی 3 باینری سمت چپ (111) را گرفته و آن را به انتهای دیگر از سمت راست اضافه می‌کنیم: 00101111. در حالت دیگر، 3 چرخش از راست یعنی 3 باینری راست (101) را گرفته و آن را به سمت چپ اضافه می‌کنیم: 10111100

1. پدینگ (Padding)

از نظر واژه شناسی، “Padding” یعنی «پر کردن». این فعالیت در زمینه‌های مختلفی نظیر تولید البسه و مبلمان (مثلا پر کردن کوسن با موارد نرم)، نویسندگی (اضافه کردن کلمات غالبا زائد جهت افزایش طول محتوا) و موارد دیگر به‌کار می‌رود. اما پدینگ در دنیای برنامه‌نویسی نظیر CSS و HTML معنی دیگری دارد.

در الگوریتم هشینگ SHA 256، مرحله پدینگ شامل اضافه کردن بیت‌های بیشتر به یک پیام است تا اندازه آن به دقیقا 64 بیت کمتر از 512 یا مضربی از آن تبدیل شود. در مرحله اضافه کردن بیت‌ها، باید اولین بیت اضافی 1 و بقیه 0 باشند.

مرحله اول الگوریتم sha-256 - پدینگ

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

2. مقداردهی اولیه مقادیر هش

حالا باید 8 مقدار هش بسازیم تا در دورهای الگوریتم هشینگ SHA-256 استفاده شوند. همانطور که پیشتر گفتیم، برای دور اول، مقادیر هش ثابت و هاردکد شده هستند و از 32 بیت اول کسر حاصل از ریشه درجه دو 8 عدد ابتدیی مجموعه اعداد اول، شامل 2، 3، 5، 7، 11، 13، 17 و 19 به‌دست می‌آیند. این هش‌ها به‌صورت زیر هستند:

h0 := 0x6a09e667
h1 := 0xbb67ae85
h2 := 0x3c6ef372
h3 := 0xa54ff53a
h4 := 0x510e527f
h5 := 0x9b05688c
h6 := 0x1f83d9ab
h7 := 0x5be0cd19

3. مقداردهی اولیه ثابت دورها

مشابه مرحله 2، باید یک سری مقدار ثابت بسازیم. این بار، این مقادیر ثابت شامل 64 مقدار و به‌صورت K[0] تا K[63] هستند. هر مقدار نیز برابر 32 بیت اول کسر ریشه سوم 64 عدد ابتدایی مجموعه اعداد اول شامل 2 تا 311 است.

0x428a2f98 0x71374491 0xb5c0fbcf 0xe9b5dba5 0x3956c25b 0x59f111f1 0x923f82a4 0xab1c5ed5
0xd807aa98 0x12835b01 0x243185be 0x550c7dc3 0x72be5d74 0x80deb1fe 0x9bdc06a7 0xc19bf174
0xe49b69c1 0xefbe4786 0x0fc19dc6 0x240ca1cc 0x2de92c6f 0x4a7484aa 0x5cb0a9dc 0x76f988da
0x983e5152 0xa831c66d 0xb00327c8 0xbf597fc7 0xc6e00bf3 0xd5a79147 0x06ca6351 0x14292967
0x27b70a85 0x2e1b2138 0x4d2c6dfc 0x53380d13 0x650a7354 0x766a0abb 0x81c2c92e 0x92722c85
0xa2bfe8a1 0xa81a664b 0xc24b8b70 0xc76c51a3 0xd192e819 0xd6990624 0xf40e3585 0x106aa070
0x19a4c116 0x1e376c08 0x2748774c 0x34b0bcb5 0x391c0cb3 0x4ed8aa4a 0x5b9cca4f 0x682e6ff3
0x748f82ee 0x78a5636f 0x84c87814 0x8cc70208 0x90befffa 0xa4506ceb 0xbef9a3f7 0xc67178f2

4. توابع فشرده‌سازی در حلقه چانک (Chunk)

حالا این مرحله از الگوریتم هش SHA256، برای هر 512 بیت «چانک (تکه)» داده حاصل از ورودی ما تکرار می‌شود. به عبارت دیگر، کل پیام به چندین بلاک 512 بیتی شکسته می‌شود. در واقع این گام، هر بلاک را وارد 64 دور عملیات می‌کند که خروجی هر بلاک، ورودی بلاک بعدی خواهد بود. کل این فرآیند به‌شکل زیر است:

گام 4 الگوریتم sha256

با اینکه مقدار K[i] در تمام این دورها از پیش‌مقداردهی شده است، اما W[i] ورودی دیگری است که بسته به تعداد تکرارهای در حال انجام در لحظه، برای هر بلاک به‌صورت جداگانه محاسبه می‌شود.

5. خروجی

حالا در هر تکرار، خروجی نهایی هر بلاک به‌عنوان ورودی بلاک بعدی عمل می‌کند. کل این چرخه نیز تا زمانی که به آخرین بلاک 512 بیتی برسیم تکرار می‌شود و هش به‌دست‌آمده، به‌عنوان هش نهایی (دایجست) محاسبه خواهد شد.

مثالی از هش کردن یک کلمه با الگوریتم SHA256

برای درک بهتر نحوه کار الگوریتم هشینگ SHA-256 به‌صورت عملی، اجازه دهید مثالی بزنیم. فرض کنید ورودی ما برای الگوریتم هشینگ SHA 256، عبارت “hello world” باشد. با توجه به مراحل قبل، گام‌های هش کردن این عبارت به‌صورت زیر است:

1. پیش‌پردازش و پدینگ:

در مرحله اول، ابتدا باید “hello world” را به باینری تبدیل کنیم:

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100

سپس باید عدد “1” را به انتهای این باینری اضافه کنیم:

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 1

برای تبدیل داده به مضربی از 512 بیت، به آن “0” اضافه می‌کنیم تا جایی که 64 بیت کمتر داشته باشد (در این حالت، 448 بیت):

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 10000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

سپس 64 بیت باقی مانده را به انتهای داده‌های قبل اضافه می‌کنیم. این 64 بیت، یک عدد صحیح اندیان بزرگ (Big-endian) است که طول ورودی اصلی ما یعنی “hello world” را در حالت باینری نشان می‌دهد. طول این باینری 88 (11 داده 8 بیتی) است که خود به‌صورت باینری معادل “1011000” خواهد بود:

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 10000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 01011000

اکنون ورودی الگوریتم هشینگ SHA-256 را به‌دست آورده‌ایم که به 512 بخش‌پذیر است.

2. مقداردهی اولیه مقادیر هش:

همانطور که در گام 2 بخش قبل گفتیم، باید هشت مقدار هش اولیه به‌صورت h0 تا h7 داشته باشیم که 32 بیت اولیه کسر ریشه دوم 8 عدد نخستین مجموعه اعداد اول شامل 2 تا 19 و دارای مقادیر ثابت زیر هستند:

h0 := 0x6a09e667
h1 := 0xbb67ae85
h2 := 0x3c6ef372
h3 := 0xa54ff53a
h4 := 0x510e527f
h5 := 0x9b05688c
h6 := 0x1f83d9ab
h7 := 0x5be0cd19

3. مقداردهی اولیه ثابت دورها:

مشابه گام 3 در بخش قبل، به 64 مقدار ثابت نیاز داریم که هر مقدار، 32 بیت اولیه کسر ریشه سوم 64 عدد اول شامل 2 تا 311 است:

0x428a2f98 0x71374491 0xb5c0fbcf 0xe9b5dba5 0x3956c25b 0x59f111f1 0x923f82a4 0xab1c5ed5
0xd807aa98 0x12835b01 0x243185be 0x550c7dc3 0x72be5d74 0x80deb1fe 0x9bdc06a7 0xc19bf174
0xe49b69c1 0xefbe4786 0x0fc19dc6 0x240ca1cc 0x2de92c6f 0x4a7484aa 0x5cb0a9dc 0x76f988da
0x983e5152 0xa831c66d 0xb00327c8 0xbf597fc7 0xc6e00bf3 0xd5a79147 0x06ca6351 0x14292967
0x27b70a85 0x2e1b2138 0x4d2c6dfc 0x53380d13 0x650a7354 0x766a0abb 0x81c2c92e 0x92722c85
0xa2bfe8a1 0xa81a664b 0xc24b8b70 0xc76c51a3 0xd192e819 0xd6990624 0xf40e3585 0x106aa070
0x19a4c116 0x1e376c08 0x2748774c 0x34b0bcb5 0x391c0cb3 0x4ed8aa4a 0x5b9cca4f 0x682e6ff3
0x748f82ee 0x78a5636f 0x84c87814 0x8cc70208 0x90befffa 0xa4506ceb 0xbef9a3f7 0xc67178f2

4. حلقه چانک:

این مرحله برای هر 512 بیت «چانک» داده حاصل از ورودی ما تکرار می‌شود. حالا از آنجایی که “hello world” بسیار کوتاه است، ما تنها یک چانک داریم. بنابراین در هر دور این حلقه، مقادیر هش h0 تا h7 را جهش می‌دهیم تا خروجی نهایی به‌دست آید.

5. ساخت Message Schedule:

برای ساخت Message Schedule، داده نهایی مرحله 1 را در یک آرایه جدید که هر ورودی یک کلمه 32 بیتی است، کپی می‌کنیم:

01101000011001010110110001101100 01101111001000000111011101101111
01110010011011000110010010000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000001011000

اکنون 48 کلمه دیگر که با صفر مقداردهی شده‌اند را اضافه می‌کنیم تا یک آرایه w[0…63] داشته باشیم:

01101000011001010110110001101100 01101111001000000111011101101111
01110010011011000110010010000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000001011000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
...
...
00000000000000000000000000000000 00000000000000000000000000000000

برای اصلاح ایندکس‌های صفر انتهای آرایه، از الگوریتم زیر استفاده می‌کنیم:

  • For i from w[16…63]:
    • s0 = (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3)
    • s1 = (w[i- 2] rightrotate 17) xor (w[i- 2] rightrotate 19) xor (w[i- 2] rightshift 10)
    • w[i] = w[i-16] + s0 + w[i-7] + s1

مثلا برای w[16]، این الگوریتم به‌صورت زیر کار می‌کند:

w[1] rightrotate 7:
01101111001000000111011101101111 -> 11011110110111100100000011101110
w[1] rightrotate 18:
01101111001000000111011101101111 -> 00011101110110111101101111001000
w[1] rightshift 3:
01101111001000000111011101101111 -> 00001101111001000000111011101101
s0 = 11011110110111100100000011101110 XOR 00011101110110111101101111001000 XOR 00001101111001000000111011101101
s0 = 11001110111000011001010111001011
w[14] rightrotate 17:
00000000000000000000000000000000 -> 00000000000000000000000000000000
w[14] rightrotate19:
00000000000000000000000000000000 -> 00000000000000000000000000000000
w[14] rightshift 10:
00000000000000000000000000000000 -> 00000000000000000000000000000000
s1 = 00000000000000000000000000000000 XOR 00000000000000000000000000000000 XOR 00000000000000000000000000000000
s1 = 00000000000000000000000000000000
w[16] = w[0] + s0 + w[9] + s1
w[16] = 01101000011001010110110001101100 + 11001110111000011001010111001011 + 00000000000000000000000000000000 + 00000000000000000000000000000000
// addition is calculated modulo 2^32
w[16] = 00110111010001110000001000110111

این کار، 64 کلمه در Message Schedule (w) ما می‌سازد:

01101000011001010110110001101100 01101111001000000111011101101111
01110010011011000110010010000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000001011000
00110111010001110000001000110111 10000110110100001100000000110001
11010011101111010001000100001011 01111000001111110100011110000010
00101010100100000111110011101101 01001011001011110111110011001001
00110001111000011001010001011101 10001001001101100100100101100100
01111111011110100000011011011010 11000001011110011010100100111010
10111011111010001111011001010101 00001100000110101110001111100110
10110000111111100000110101111101 01011111011011100101010110010011
00000000100010011001101101010010 00000111111100011100101010010100
00111011010111111110010111010110 01101000011001010110001011100110
11001000010011100000101010011110 00000110101011111001101100100101
10010010111011110110010011010111 01100011111110010101111001011010
11100011000101100110011111010111 10000100001110111101111000010110
11101110111011001010100001011011 10100000010011111111001000100001
11111001000110001010110110111000 00010100101010001001001000011001
00010000100001000101001100011101 01100000100100111110000011001101
10000011000000110101111111101001 11010101101011100111100100111000
00111001001111110000010110101101 11111011010010110001101111101111
11101011011101011111111100101001 01101010001101101001010100110100
00100010111111001001110011011000 10101001011101000000110100101011
01100000110011110011100010000101 11000100101011001001100000111010
00010001010000101111110110101101 10110000101100000001110111011001
10011000111100001100001101101111 01110010000101111011100000011110
10100010110101000110011110011010 00000001000011111001100101111011
11111100000101110100111100001010 11000010110000101110101100010110

6. فشرده‌سازی:

ابتدا متغیرهای a, b, c, d, e, f, g, h را مقداردهی کرده و آن‌ها را به‌ترتیب معادل مقادیر هش فعلی h0, h1, h2, h3, h4, h5, h6, h7 قرار می‌دهیم. سپس حلقه فشرده‌سازی را اجرا می‌کنیم که باعث جهش مقادیر a تا h می‌شود. این حلقه به‌صورت زیر است:

  • for i from 0 to 63
    • S1 = (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)
    • ch = (e and f) xor ((not e) and g)
    • temp1 = h + S1 + ch + k[i] + w[i]
    • S0 = (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
    • maj = (a and b) xor (a and c) xor (b and c)
    • temp2 := S0 + maj
    • h = g
    • g = f
    • f = e
    • e = d + temp1
    • d = c
    • c = b
    • b = a
    • a = temp1 + temp2

اولین تکرار در الگوریتم SHA256 به‌صورت زیر است و تمام جمع‌ها به‌صورت Modulo (عملیات پیمانه) 32^2 محاسبه شده‌اند:

a = 0x6a09e667 = 01101010000010011110011001100111
b = 0xbb67ae85 = 10111011011001111010111010000101
c = 0x3c6ef372 = 00111100011011101111001101110010
d = 0xa54ff53a = 10100101010011111111010100111010
e = 0x510e527f = 01010001000011100101001001111111
f = 0x9b05688c = 10011011000001010110100010001100
g = 0x1f83d9ab = 00011111100000111101100110101011
h = 0x5be0cd19 = 01011011111000001100110100011001
e rightrotate 6:
01010001000011100101001001111111 -> 11111101010001000011100101001001
e rightrotate 11:
01010001000011100101001001111111 -> 01001111111010100010000111001010
e rightrotate 25:
01010001000011100101001001111111 -> 10000111001010010011111110101000
S1 = 11111101010001000011100101001001 XOR 01001111111010100010000111001010 XOR 10000111001010010011111110101000
S1 = 00110101100001110010011100101011
e and f:
01010001000011100101001001111111
& 10011011000001010110100010001100 =
00010001000001000100000000001100
not e:
01010001000011100101001001111111 -> 10101110111100011010110110000000
(not e) and g:
10101110111100011010110110000000
& 00011111100000111101100110101011 =
00001110100000011000100110000000
ch = (e and f) xor ((not e) and g)
= 00010001000001000100000000001100 xor 00001110100000011000100110000000
= 00011111100001011100100110001100
// k[i] is the round constant
// w[i] is the batch
temp1 = h + S1 + ch + k[i] + w[i]
temp1 = 01011011111000001100110100011001 + 00110101100001110010011100101011 + 00011111100001011100100110001100 + 01000010100010100010111110011000 + 01101000011001010110110001101100
temp1 = 01011011110111010101100111010100
a rightrotate 2:
01101010000010011110011001100111 -> 11011010100000100111100110011001
a rightrotate 13:
01101010000010011110011001100111 -> 00110011001110110101000001001111
a rightrotate 22:
01101010000010011110011001100111 -> 00100111100110011001110110101000
S0 = 11011010100000100111100110011001 XOR 00110011001110110101000001001111 XOR 00100111100110011001110110101000
S0 = 11001110001000001011010001111110
a and b:
01101010000010011110011001100111
& 10111011011001111010111010000101 =
00101010000000011010011000000101
a and c:
01101010000010011110011001100111
& 00111100011011101111001101110010 =
00101000000010001110001001100010
b and c:
10111011011001111010111010000101
& 00111100011011101111001101110010 =
00111000011001101010001000000000
maj = (a and b) xor (a and c) xor (b and c)
= 00101010000000011010011000000101 xor 00101000000010001110001001100010 xor 00111000011001101010001000000000
= 00111010011011111110011001100111
temp2 = S0 + maj
= 11001110001000001011010001111110 + 00111010011011111110011001100111
= 00001000100100001001101011100101
h = 00011111100000111101100110101011
g = 10011011000001010110100010001100
f = 01010001000011100101001001111111
e = 10100101010011111111010100111010 + 01011011110111010101100111010100
= 00000001001011010100111100001110
d = 00111100011011101111001101110010
c = 10111011011001111010111010000101
b = 01101010000010011110011001100111
a = 01011011110111010101100111010100 + 00001000100100001001101011100101
= 01100100011011011111010010111001

حال کل این محاسبات 63 بار دیگر تکرار شده و متغیرهای a تا h را طی تکرارها اصلاح می‌کند. آخرین نتیجه به‌صورت زیر است:

h0 = 6A09E667 = 01101010000010011110011001100111
h1 = BB67AE85 = 10111011011001111010111010000101
h2 = 3C6EF372 = 00111100011011101111001101110010
h3 = A54FF53A = 10100101010011111111010100111010
h4 = 510E527F = 01010001000011100101001001111111
h5 = 9B05688C = 10011011000001010110100010001100
h6 = 1F83D9AB = 00011111100000111101100110101011
h7 = 5BE0CD19 = 01011011111000001100110100011001
a = 4F434152 = 01001111010000110100000101010010
b = D7E58F83 = 11010111111001011000111110000011
c = 68BF5F65 = 01101000101111110101111101100101
d = 352DB6C0 = 00110101001011011011011011000000
e = 73769D64 = 01110011011101101001110101100100
f = DF4E1862 = 11011111010011100001100001100010
g = 71051E01 = 01110001000001010001111000000001
h = 870F00D0 = 10000111000011110000000011010000

7. اصلاح مقادیر نهایی:

پس از پایان حلقه تکرار، البته در داخل خود حلقه چانک، مقادیر هش را با اضافه کردن متغیرهای a تا h مربوط به آن‌ها اصلاح می‌کنیم. مشابه قبل، تمام جمع‌ها به‌صورت عملیات پیمانه 32^2 هستند.

h0 = h0 + a = 10111001010011010010011110111001
h1 = h1 + b = 10010011010011010011111000001000
h2 = h2 + c = 10100101001011100101001011010111
h3 = h3 + d = 11011010011111011010101111111010
h4 = h4 + e = 11000100100001001110111111100011
h5 = h5 + f = 01111010010100111000000011101110
h6 = h6 + g = 10010000100010001111011110101100
h7 = h7 + h = 11100010111011111100110111101001

8. الحاق هش نهایی:

در آخر، با استفاده از یک الحاق رشته (String Contanation) ساده، تمام هش‌ها را به هم متصل و با یکدیگر جمع می‌کنیم:

digest = h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
= B94D27B9934D3E08A52E52D7DA7DABFAC484EFE37A5380EE9088F7ACE2EFCDE9

تمام. کار الگوریتم SHA 256 ما اینجا به پایان می‌رسد.

شبکه‌کدها

این مراحل به‌صورت «شبه‌کد» در ویکی‌پدیا به‌صورت زیر هستند:

Note 1: All variables are 32 bit unsigned integers and addition is calculated modulo 232
Note 2: For each round, there is one round constant k[i] and one entry in the message schedule array w[i], 0 ≤ i ≤ 63
Note 3: The compression function uses 8 working variables, a through h
Note 4: Big-endian convention is used when expressing the constants in this pseudocode,
and when parsing message block data from bytes to words, for example,
the first word of the input message "abc" after padding is 0x61626380
Initialize hash values:
(first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
h0 := 0x6a09e667
h1 := 0xbb67ae85
h2 := 0x3c6ef372
h3 := 0xa54ff53a
h4 := 0x510e527f
h5 := 0x9b05688c
h6 := 0x1f83d9ab
h7 := 0x5be0cd19
Initialize array of round constants:
(first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
k[0..63] :=
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
Pre-processing (Padding):
begin with the original message of length L bits
append a single '1' bit
append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512
append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits
Process the message in successive 512-bit chunks:
break message into 512-bit chunks
for each chunk
create a 64-entry message schedule array w[0..63] of 32-bit words
(The initial values in w[0..63] don't matter, so many implementations zero them here)
copy chunk into first 16 words w[0..15] of the message schedule array
Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
for i from 16 to 63
s0 := (w[i-15] rightrotate  7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift  3)
s1 := (w[i- 2] rightrotate 17) xor (w[i- 2] rightrotate 19) xor (w[i- 2] rightshift 10)
w[i] := w[i-16] + s0 + w[i-7] + s1
Initialize working variables to current hash value:
a := h0
b := h1
c := h2
d := h3
e := h4
f := h5
g := h6
h := h7
Compression function main loop:
for i from 0 to 63
S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)
ch := (e and f) xor ((not e) and g)
temp1 := h + S1 + ch + k[i] + w[i]
S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
maj := (a and b) xor (a and c) xor (b and c)
temp2 := S0 + maj
h := g
g := f
f := e
e := d + temp1
d := c
c := b
b := a
a := temp1 + temp2
Add the compressed chunk to the current hash value:
h0 := h0 + a
h1 := h1 + b
h2 := h2 + c
h3 := h3 + d
h4 := h4 + e
h5 := h5 + f
h6 := h6 + g
h7 := h7 + h
Produce the final hash value (big-endian):
digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7

کاربردهای الگوریتم SHA-256 کدامند؟

الگوریتم SHA256 به‌خاطر سرعت و امنیت خود، برای موارد مختلفی استفاده می‌شود از جمله:

  • ساخت طرح‌های احراز هویت وبسایت با استفاده از JWT و HMAC و MAC
  • ساخت امضاهای دیجیتال
  • تامین امنیت بلاک چین‌هایی نظیر بیت کوین
  • در پروتکل‌های امنیتی نظیر SSL
  • در آنتی ویروس‌ها برای مقایسه اثر انگشت فایل‌ها و برنامه‌ها
  • در سیستم کنترل ورژن نظیر Git جهت بررسی تغییرات داده
  • در سیستم عامل‌هایی نظیر Unix و ویندوز XP سرویس‌پک 3 به بالا

هشینگ رمز عبور

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

اما به عقیده برخی دیگر، نباید از الگوریتم هشینگ SHA 256 برای هش کردن پسوردها استفاده کرد. به باور این افراد، شا-256 سرعت بالایی دارد، به این معنا که در صورت حمله بروت فورس (Brute Force یا جستجوی فراگیر) به رمز عبورها، امنیت آن‌ها به‌خطر خواهد افتاد. به پیشنهاد این افراد، بهتر است از تابع مشتق کلید (KDF) که باعث کاهش سرعت فعالیت مهاجمان می‌شود برای هش کردن پسوردها استفاده کرد.

حفاظت از تمامیت داده‌ها

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

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

اعتبارسنجی درستی فایل‌ها

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

اعتبارسنجی امضاهای دیجیتال

امضای دیجیتال روشی برای امضا کردن اسناد دیجیتال، کد یا نرم افزاری است که امکان اعتبارسنجی آن توسط گیرنده یا کاربران وجود دارد. در این حالت، افراد از اینکه فایل یا سندی توسط شما ساخته یا امضا شده یا حتی آیتم مورد نظر توسط فرد دیگری ساخته یا دستکاری شده است، خبردار خواهند شد.

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

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

پروتکل‌های رمزگذاری و مجوزهای دیجیتال

از الگوریتم SHA256 برای ساخت مجوزهای دیجیتال SSL و TLS استفاده می‌شود. این مجوزهای دیجیتال ارتباطی رمزگذاری‌شده را بین سرورها و مرورگرهای وب ایجاد می‌کنند. برای محافظت از اطلاعات کاربران و تامین امنیت مبادلات آنلاین، به مجوزهای SSL نیاز است. از دیگر پروتکل‌های رمزگذاری و احراز هویت مختلف که الگوریتم SHA 256 در آن‌ها کاربرد دارد می‌توان موارد زیر را نام برد:

  • SSH: این پروتکل که مخفف Secure Shell است، کانالی امن بین دو دستگاه برای انتقال داده می‌سازد.
  • IPsec: مخفف Internet Protocol Security و مجموعه‌ای از پروتکل‌های طراحی‌شده جهت تامین امنیت انتقال داده در شبکه‌های آی‌پی مختلف است.
  • PGP: مخفف Pretty Good Privacy و یک الگوریتم رمزگذاری است که برای امضا، رمزگذاری و رمزگشایی ایمیل‌ها، فایل‌ها، دایرکتوری‌ها یا پارتیشن‌بندی دیسک (افرازش) کاربرد دارد.
  • S/MIME: مخفف Secure/Multipurpose Internet Mail Extension و الگوریتمی است که برای امن نگه داشتن تمامیت و محرمانگی ایمیل‌ها استفاده می‌شود.
  • Blockchain: در یک بلاک چین، مقادیر هش قبلی برای محاسبه هش بلاک فعلی به‌کار می‌روند.

مزایای استفاده از الگوریتم SHA-256 در بلاک چین

از جمله مهمترین کاربردهای SHA-256 در تامین امنیت یک بلاک چین است. در فناوری بلاک چین، از تابع هش برای تولید هش‌هایی استفاده می‌شود که به‌عنوان «اثر انگشت منحصربه‌فرد» هر بلاک جهت شناسایی آن‌ها عمل می‌کنند. در این حالت، هر بلاک دارای یک داده هش‌شده است و از مقدار هش بلاک قبلی برای محاسبه مقدار هش بلاک بعدی استفاده می‌شود که نهایتا یک ساختار زنجیرگونه را می‌سازد. حالا از آنجایی که این هش‌ها به هم متصل هستند، هر گونه تلاشی برای تغییر حتی یک کاراکتر از آن‌ها باعث ایجاد یک اثر زنجیره‌ای قابل مشاهده برای همگان خواهد شد. البته اولین بلاک هر شبکه که بلاک جنسیس (Genesis Block) نام دارد، دارای هش بلاک قبلی نیست.

تابع هش در بلاک چین

این هش‌ها با استفاده از داده‌های بلاک و یک مقدار نانس (Nonce) به‌عنوان ورودی تابع تولید می‌شوند. در واقع فرآیند تولید هش بلاک همان چیزی است که ماینرها هنگام استخراج بلاک‌ها انجام می‌دهند.

حالا بلاک چین‌هایی نظیر بیت کوین از تابع هش SHA-256 و شبکه‌هایی نظیر اتریوم اثبات کار (زنجیره اصلی پیش از مهاجرت به اثبات سهام) از تابع هش Keccak-256 استفاده می‌کنند. تابع هش Keccak اکنون با نام SHA-3 شناخته می‌شود و بخشی از مکانیزم اجماع اثبات کار اتریوم به‌نام ای تی هش (Ethash) است.

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

مقاومت پیش تصویر یا یک طرفگی

مقاومت پیش تصویر (Preimage Resistane) یا یک طرفگی (One-wayness) یعنی هش تولیدی توسط تابع هش را نمی‌توان برای دستیابی به مقدار ورودی اولیه مهندسی معکوس کرد. برای درک بهتر، تابع h(x) = y را در نظر بگیرید. در صورتی که h تابع هش، x داده ورودی و y خود مقدار هش باشد، تحت هیچ شرایطی نباید بتوانیم از روی y به x برسیم. این خاصیت، مقاومت یک طرفه یا یک طرفگی نام دارد.

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

مقاومت تصادم ضعیف یا پیش تصویر دوم

مقاومت تصادم ضعیف (Weak Collistion Resistance) که تحت عنوان مقاومت پیش تصویر دوم (Secon Preimage Resistance) نیز شناخته می‌شود، یعنی ساخت یک خروجی یکسان توسط دو ورودی متفاوت باید تقریبا غیر ممکن باشد. مشابه مثال قبل، تابع h(x) = y را در نظر بگیرید. همانطور که گفتیم، از ورودی x و تابع هش h، به مقدار هش خروجی y می‌رسیم. با توجه به ویژگی مقاومت تصادم ضعیف، در صورتی که ورودی z (برابر x نیست) را وارد کنیم، نباید دوباره به مقدار y برسیم (h(z) ≠ y).

در صورتی که بتوان از دو ورودی متفاوت یک هش یکسان تولید کرد، هکرها به‌راحتی قادر به حمله به بلاک چین‌ها و دستکاری داده‌ها بدون نگرانی در خصوص تغییر هش خروجی خواهند بود. چنین اتفاقی در الگوریتم SHA-256 بسیار بعید است و حتی در صورت رخداد، نمی‌توان گفت کدام دو ورودی متفاوت قادر به تولید یک خروجی یکسان هستند. بنابراین شانس حمله موفق به شبکه توسط این روش تقریبا 0 است.

قطعی

ویژگی قطعی و Deterministic بودن یعنی برای هر ورودی مشخص، تابع هش باید همیشه همان مقدار خروجی یکسان را تولید کند. در مثال h(x) = y، یعنی h(x) همیشه باید با ورودی x، خروجی y را تولید کند. در واقع صرف‌نظر از تعداد دفعات استفاده از h(x)، هیچ‌گاه نباید از ورودی x به خروجی متفاوتی از y، مثلا t برسیم.

محاسبات سریع

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

اثر بهمنی

اثر بهمنی یا Avalanche Effect یعنی تغییر حتی یک بیت در ورودی، بهمنی از تغییرات را در محاسبه هش‌ها ایجاد می‌کند. در نتیجه، کوچکترین تغییر در هش، تولید یک هش کاملا جدید را به‌دنبال دارد.

این ویژگی باعث می‌شود معادلات ریاضی پیدا کردن هش درست بلاک‌ها برای ماینرها که جهت رسیدن به هدف مورد نظر باید هر دقیقه نانس (Nonce) را تغییر دهند، قابل پیش‌بینی نباشد. در قسمت‌های بعدی، بیشتر راجع به نانس صحبت می‌کنیم.

هش و نانس در بلاک چین

برای مشاهده نحوه تغییر هش در الگوریتم SHA-256 با تغییر حتی یک بیت داده، می‌توانید از سایت demoblockchain.org/hash استفاده نمایید.

محدودیت‌های الگوریتم SHA256 در استخراج ارزهای دیجیتال

زمانی که شبکه بیت کوین در سال 2009 آغاز به‌کار کرد، SHA-256 امن‌ترین الگوریتم هشینگ در دسترس بود. از آن زمان تا کنون، محدودیت‌های این الگوریتم خود را نشان داده‌اند که در ادامه این قسمت آن‌ها را بررسی می‌کنیم.

تسلط اسیک ماینرها

مهمترین خصیصه SHA-256 این است که هیچ‌گاه قرار نبود در برابر دستگاه‌های قدرتمند مقاومت داشته باشد. اما گفتگوها پیرامون مقاومت اسیک ماینرها در شبکه‌های بلاک چینی پس از معرفی بیت کوین مطرح شد.

به استناد گزارشی از Michael Bedford Taylor از دانشگاه واشنگتون، سیر تکامل سخت افزارهای ماینینگ بیت کوین را می‌توان به شش نسل تقسیم کرد. با راه‌اندازی این شبکه در سال 2009، تنها CPUها پشتیبانی می‌شدند که سیستمی عادلانه را برای همه ماینرها ایجاد کرده بود. با این حال، این وضعیت با نسل‌های بعدی تجهیزات استخراج تغییر کرد. هر نسل جدید از ریگ‌های ماینینگ قادر به پردازش قدرت هش بیشتری نسبت به نسخه قبلی خود بود. نهایتا، شبکه بیت کوین با ظهور GPUها در سال 2010، FPGAها در سال 2011 و اسیک ماینرها در سال 2012 تا 2013 متحول شد. نتیجه این اتفاق، عدم کارآمدی دیگر گزینه‌ها نظیر CPUها و GPUها برای استخراج بیت کوین بود.

اسیک‌ها امروزه بازار را غبضه کرده و همچنان به افزایش قدرت خود ادامه می‌دهند. شواهد این امر را می‌توان با نگاه به هش ریت عمر 14 ساله بیت کوین تا به امروز مشاهده کرد.

سودآوری فعلی استخراج

امروزه، میزان سود استخراج بیت کوین و دیگر ارزهای الگوریتم SHA256 به دستگاه‌های اسیک قدرتمند متکی است. البته تمام استیک ماینرها توانایی تولید نتیجه یکسان را ندارند. برای نمونه، انت ماینر S19 پرو بیت‌مین محصول 2020 را با انت ماینر T15 بیت‌مین محصول سال 2018 مقایسه می‌کنیم. S19 پرو از نظر تئوری قدرت تولید هش بیشتری دارد، بنابراین در بازه زمانی یکسان، درآمد بیشتری تولید خواهد کرد. اما این را هم باید در نظر گرفت که قیمت اس19 پرو تقریبا 3 برابر تی15 است. با فرض اینکه دستگاه‌های بعدی حتی قدرت بیشتری هم از اس19 داشته باشند، تصور افزایش رقابت و نیازمندی به سرمایه هنگفت توسط آن‌ها دشوار نیست.

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

ظهور SHA-3 و دیگر الگوریتم‌های هشینگ

SHA-2 آخرین خانواده الگوریتم هش منتشر شده نیست. SHA-3 که پیشتر تحت عنوان Keccak شناخته می‌شد، سرعت و قدرت بیشتری نسبت به SHA-256 دارد. الگوریتم SHA-2 در بلاک چین‌هایی نظیر نکسوس (NXS)، اسمارت کش (SMART) و چندی دیگر استفاده می‌شود.

البته مشابه SHA256، الگوریتم SHA-3 اسیک‌دوست است که کار استخراج رمز ارزهای مبتنی بر آن را با استفاده از GPU و CPU دشوار می‌کند. بسیاری از پروژه‌های بلاک چینی، عدم مقاومت الگوریتم‌های هشینگ، خصوصا پیاده‌سازی شا-256 در بیت کوین را یکی از علل بزرگ توسعه الگوریتم‌های دیگری نظیر الگوریتم اسکریپت (Scrypt)، ایکوئی هش (Equihash)، کریپتو نایت (CryptoNight)، و لیرا2رو2 (Lyra2Rev2) می‌دانند.

ارزهای SHA-256

اهمیت استفاده از الگوریتم SHA256 در بلاک چین را نمی‌توان دست کم گرفت. امروزه ارزهای دیجیتال زیادی به‌خاطر سرعت و امنیت این الگوریتم از آن برای ساخت و استخراج بلاک‌های خود استفاده می‌کنند. در تصویر زیر، به استناد کوین مارکت کپ، برخی از این رمز ارزها از نظر برتری ارزش بازار را مشاهده می‌کنید:

ارزهای الگوریتم sha-256

در ادامه، نحوه کار بلاک چین‌های بیت کوین، بیت کوین کش و بیت کوین اس وی با استفاده از الگوریتم SHA-256 را بررسی می‌کنیم.

بیت کوین

بیت کوین از زمان آغاز به‌کار خود در سال 2009، همیشه از الگوریتم SHA 256 استفاده کرده که نتیجه آن، ظهور ریگ‌های ماینینگ قدرتمند طی گذر زمان بوده است. الگوریتم شا-256 در جنبه‌های مختلفی از پروتکل بیت کوین نظیر استخراج، درخت مرکل (Merkle Tree) و ساخت آدرس‌های بیت کوین به‌کار می‌رود که در ادامه، دو مورد استخراج و ساخت آدرس را بررسی می‌کنیم.

استخراج

ماینرها برای استخراج و افزدن بلاک به شبکه بیت کوین، ابتدا باید چیزی به‌نام نود ماینینگ (Mining Node) را اجرا کنند. پس از راه‌اندازی موفق یک نود، ماینرها به پیدا کردن هش بلاک می‌پردازند که در ادامه، این بلاک در شبکه معرفی می‌شود تا توسط دیگر نودها تحت اعتبارسنجی قرار بگیرد. در صورتی که این بلاک توسط دیگر نودها تایید شود، به زنجیره اضافه خواهد شد.

حالا هر بلاک در شبکه، از دو قسمت به‌نام هدر یا عنوان (Header) و بادی یا بدنه (Body) تشکیل می‌شود که هر کدام دارای المان و پارامترها مختص به خود هستند. در داخل بلاک هدر، 6 پارامتر وجود دارد که ماینرها باید آن را پر کنند از جمله:

  • نسخه (Version): عدد ورژن نرم افزار بیت کوین برای پیگیری آپگرید‌های پروتکل یا نرم افزار
  • هش بلاک قبلی: ارجاع به هش بلاک قبلی در بلاک جدید
  • ریشه مرکل (Merkle Root): نماینده هش تمام تراکنش‌های داخل بلاک
  • مهر زمان (Timestamp): زمان تقریبی ساخت بلاک
  • هدف سختی (Difficulty Target): سختی الگوریتم اثبات کار برای بلاک مورد نظر
  • نانس (Nonce): عدد متغیر مورد استفاده در فرآیند اثبات کار

هدر بلاک

همانطور که مشخص است، هش رمزنگاری‌شده هر بلاک به‌عنوان شناساگر آن عمل می‌کند که از طریق الگوریتم SHA-256 تولید می‌شود. با اینکه به این هش، «هش بلاک» می‌گویند، اما از آنجایی که تنها قسمت هدر بلوک برای تولید آن مورد استفاده قرار می‌گیرد، بهتر است آن را «هش هدر بلاک» بنامیم. پس در واقع شما با هش کردن هدر یک بلاک توسط تابع SHA256 می‌توانید هش آن را پیدا کنید.

حالا برای این کار، ماینرها ابتدا به محاسبه هش بلاک قبلی نیاز دارند. برای محاسبه هش بلاک قبلی، باید هدر بلاک قبلی را دو بار وارد الگوریتم SHA-256 کنند. به این کار، Double-SHA-256 یا SHA-256d می‌گویند:

SHA256(SHA256(Block Heade)) = هش بلاک قبلی

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

مثلا، اگر نانس فعلی ما “1234” باشد، آن را در کنار 5 پارامتر ثابت دیگر در هدر قرار می‌دهیم. سپس کل این هدر به‌عنوان ورودی داخل تابع SHA 256 قرار داده و آن را هش می‌کنیم. اگر مقدار خروجی بالای هدف سختی باشد، باید دوباره با تغییر نانس این فرآیند را تکرار کنیم. مثلا این بار نانس را “90872” گذاشته و با 5 پارامتر ثابت دیگر هش هدر را تولید می‌کنیم. اگر این بار هش خروجی زیر هدف سختی باشد، بلاک تولیدی در شبکه پخش شده و دیگر نودها به تایید یا رد آن می‌پردازند.

در تصویر زیر، یک نمونه بلاک موفق بیت کوین را مشاهده می‌کنید:

نمونه بلاک بیت کوین

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

آدرس بیت کوین

کاربرد دیگر الگوریتم SHA-256 در ساخت آدرس بیت کوین است که در کیف پول‌ها برای ارسال و دریافت رمز ارزها استفاده می‌شود. برای ساخت این آدرس، ابتدا یک کلید خصوصی که یک عدد تصادفی است را با استفاده از یک منحنی بیضوی به‌نام secp256k1، در یک نقطه از پیش مشخص‌شده به‌نام “Generator Point G” یا «نقطه تولیدکننده جی» ضرب می‌کنیم تا یک نقطه دیگر در فضای منحنی تولید شود. این نقطه، کلید عمومی ما خواهد بود.

سپس این کلید عمومی را در الگوریتم‌های هشینگ SHA-256 و RIPEMD160 وارد می‌کنیم تا یک عدد 160 بیتی (20 بایتی) تولید شود:

A = RIPEMD160(SHA-256(K))

K: کلید عمومی

A: آدرس بیت کوین

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

کاربرد الگوریتم sha256 در ساخت آدرس بیت کوین

از جمله مزایای استفاده از الگوریتم هشینگ SHA256 و RIPEMD160 برای ساخت آدرس بیت کوین، کوتاه شدن آدرس‌هاست. کلید عمومی بیت کوین یک رشته 256 بیتی است که نسخه هش‌شده آن یعنی آدرس، دارای 160 بیت طول است. این ویژگی باعث راحت‌تر شدن استفاده از آدرس‌های بیت کوین برای کاربران می‌شود.

بیت کوین کش

بیت کوین کش (BCH) یکی دیگر از بلاک چین‌های استفاده‌کننده از الگوریتم SHA 256 است که طی هارد فورکی از شبکه بیت کوین در جولای 2017 (تیر 96) ساخته شد. به باور برخی از اعضای جامعه بیت کوین نظیر راجر ور (Roger Ver) که مخالف پیاده‌سازی سگویت (SegWit) بود، BIP-91 باید باعث افزایش اندازه بلاک شبکه می‌شد. پس از این اختلاف نظر و فورک شدن شبکه Bitcoin، بیت کوین کش اندازه بلاک‌های خود را به 8 مگابایت افزایش داد و چندی بعد در می 2018 (اردیبهشت 97)، این مقدار را با افزایش سه برابری به 24 مگابایت رساند.

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

با اینکه شبکه بیت کوین کش دارای قدرت زیادی است، اما تا کنون چندین چالش را پشت‌سر گذاشته است. در می 2019 (اردیبهشت 98)، مهاجمی با هدف قرار دادن یکی از باگ‌های این بلاک چین باعث تقسیم شبکه و هدایت ماینرها به استخراج بلاک‌های خالی برای مدت کوتاهی شد. در آن زمان، دو استخر ماینینگ BCH به‌نام‌های BTC.com و BTC.top با همکاری یکدیگر یک حمله 51 درصدی را به شبکه ترتیب دادند تا قادر به بازگردانی تراکنش‌ها و جلوگیری از دسترسی مهاجم به کوین‌های BCH باشند.

در اکتبر 2019 (مهر 98) نیز گزارشی از خطر حمله 51 درصدی به‌خاطر کنترل بیش از 50 درصد از قدرت هش شبکه توسط یک ماینر ناشناس به مدت 24 ساعت خبر داد. با این حال، در ژانویه 2020 (دی 98)، استخر BTC.top حدود 50.2 درصد از هش ریت بیت کوین کش را در دست گرفت که نشان‌دهنده آسیب‌پذیری این شبکه بود.

بیت کوین اس وی

بیت کوین ساتوشی ویژن معروف به بی اس وی (BSV)، نتیجه هارد فورک شبکه بیت کوین کش در نوامبر 2018 (آبان 97) است. برخی از اعضای جامعه رمز ارز BCH مخالف آپگریدهای فنی روی این شبکه بودند که نتیجه آن، ساخت زنجیره BSV با اندازه بلاک 128 مگابایتی بود.

در آن زمان، BCH و BSV یک «جنگ هش» را راه انداختند که حدود 10 روز به درازا کشید. هدف مدافعان بیت کوین اس وی، انجام یک حمله 51 درصدی برای دلسرد کردن انجام ماینینگ BCH و وادار ساختن ماینرها به مهاجرت به زنجیره BSV بود. این برنامه نهایتا شکست خورد و این جنگ با جدایی کامل این دو شبکه به دو زنجیره مجزای مبتنی بر الگوریتم SHA256 خاتمه یافت.

در سال 2019 و پس از کنترل اکثریت هش پاور شبکه توسط یکی از ماینینگ پول‌های BSV، نگرانی‌هایی در خصوص احتمال حمله 51 درصدی به این شبکه نیز مطرح شد.

سخن پایانی

الگوریتم SHA-256 که به آن شا-256 می‌گویند، یکی از قوی‌ترین و سریع‌ترین الگوریتم‌های هشینگ است که در حوزه‌های مختلفی از جمله مجوزهای دیجیتال و پروتکل‌های امنیتی، امضاهای دیجیتال، حفظ تمامیت داده، بلاک چین و استخراج ارزهای دیجیتال و دیگر موارد کاربرد دارد. الگوریتم SHA256 یکی از اعضای خانواده بزرگ الگوریتم SHA-2 محسوب می‌شود که توسط آژانس امنیت ملی ایالت متحده (NSA) و موسسه ملی فناوری و استاندارد (NIST) طراحی شده است.

تهیه شده در بیت 24