یک رمز عبور قوی بسازید
رمز عبور را نویسهبهنویسه از مولد اعداد تصادفی رمزنگاری مرورگر برمیدارد و بهجای حدس زدن قدرت رشته، آنتروپی مولدی را گزارش میکند که آن را تولید کرده است. رمز عبور هرگز در نوار آدرس نوشته نمیشود، هرگز ذخیره نمیشود و هرگز به جایی فرستاده نمیشود.
نتیجهها بدون تضمین درستی ارائه میشوند. روش و منابع در پایین صفحه منتشر شدهاند تا بتوانید محاسبه را بررسی کنید.
چگونگی کار
این ابزار چه میکند
رمز عبور را نویسهبهنویسه از مولد اعداد تصادفی رمزنگاری مرورگر برمیدارد و سپس میگوید واقعاً چقدر تصادفی بودن در آن هست. نیمهٔ دوم همان بخشی است که بیشتر مولدها اشتباه انجام میدهند، و تنها بخشی است که ارزش اعتماد دارد.
قدرت رمز عبور ویژگی رشته نیست؛ ویژگی فرایندی است که آن را تولید کرده: چند رمز عبور هماحتمال دیگر میتوانستند بهجای آن درآیند. Tr0ub4dor&3 قوی به نظر میرسد و نیست، چون فرایند تولیدش شخصی بوده که در یک واژهٔ فرهنگ لغت، رقم را جای حرف گذاشته است. بیست نویسه که بهطور یکنواخت و تصادفی برداشته شدهاند قویاند، حتی اگر یکی از آنها تصادفاً واژهای را هجی کند، چون مهاجم راهی ندارد که این را بداند.
روش
هر بایت از crypto.getRandomValues میآید که در مشخصات Web Cryptography تعریف شده و به مولد رمزنگاری سیستمعامل متکی است. Math.random هیچجا استفاده نمیشود و آزمونی هست که اگر روزی استفاده شود شکست میخورد. Math.random الگوریتمی سریع و غیررمزنگاری است که کل وضعیت درونیاش را میتوان از چند خروجی خودش بازیابی کرد، یعنی یک رمز عبور از آن میتواند برای پیشبینی رمز بعدی کافی باشد.
تبدیل یک بایت تصادفی به یک نویسهٔ تصادفی جایی است که اشتباه دوم معمولاً رخ میدهد. یک بایت از ۰ تا ۲۵۵ است و الفبای اینجا ۹۰ نویسه دارد، و ۲۵۶ مضرب ۹۰ نیست، پس گرفتن مستقیم باقیمانده ۷۶ نویسهٔ اول الفبا را در هر ۲۵۶ بایت سه بار و ۱۴ نویسهٔ باقیمانده را فقط دو بار برمیگرداند — سوگیری ۵۰٪ به سمت ابتدای الفبا. در عوض هر بایت برابر یا بزرگتر از ۱۸۰، بزرگترین مضرب صحیح ۹۰، دور انداخته میشود و بایت دیگری برداشته میشود. هزینه بسیار کمتر از یک بایت اضافی در هر نویسه است؛ فایده این است که هر نویسه دقیقاً به اندازهٔ هر نویسهٔ دیگری محتمل است.
«دستکم یکی از هر نوع» با رد کردن انجام میشود، نه با تعمیر. میانبر رایج این است که یک نویسه از هر کلاس لازم را در جایگاه ثابتی بگذارند و باقی را بر بزنند، که توزیعی میسازد که یکنواخت نیست و هیچکس نمیتواند آنتروپیاش را بیان کند. این ابزار یک نامزد کامل برمیدارد، آن را بررسی میکند و اگر کلاسی کم باشد نامزد را دور میاندازد و دیگری برمیدارد. این کار مجموعهٔ رمزهای معتبر را یکنواخت نمونهبرداری میکند، یعنی آنتروپی نتیجه دقیقاً لگاریتم پایهٔ ۲ تعداد رمزهای معتبر موجود است.
شمردن آنها با اصل شمول و طرد روی کلاسهاست:
valid = SUM over subsets S of the classes of (-1)^|S| x (A - size(S))^L
A = alphabet size, L = length, size(S) = characters in the classes in S
bits = log2(valid)
= L x log2(A) + log2( SUM (-1)^|S| ((A - size(S)) / A)^L )
خط دوم همانی است که کد اجرا میکند. اگر خط اول مستقیم محاسبه شود، تفاضل عددهایی در حدود ده به توان دویستوپنجاه است که هیچ عدد ممیز شناوری گنجایشش را ندارد؛ تقسیم اولیه بر A^L هر جمله را نسبتی بین صفر و یک میکند و مجموع در هر طولی دقیق میماند.
پیش از ادامهٔ مطلب
بیست نویسه از الفبای ۹۰ نویسهای ۱۲۹٫۸۳۷۱ بیت است. سپس «دستکم یکی از هر نوع» را تیک میزنید. این الزام چقدر هزینه دارد؟
۰٫۱۴۸ بیت، که ۱۲۹٫۸۳۷۱ را به ۱۲۹٫۶۸۹۱ میرساند. اینقدر کم است چون ۹۰٫۲۵٪ رشتههای بیستنویسهای از قبل بهطور تصادفی هر چهار نوع را دارند، پس قاعده کمتر از یکدهم احتمالات را کنار میگذارد. آن را کنار چیزی بگذارید که یک نویسهٔ اضافی میخرد — ۶٫۴۹ بیت، چهل برابر — تا معلوم شود سیاست پیچیدگیای که بانک شما بر آن اصرار دارد یک خطای گرد کردن است، و محدودیت طولی که همان بانک اعمال میکند چیزی است که واقعاً به شما هزینه تحمیل میکند. این ابزار این رقم را صادقانه به دست میآورد: نامزدهای کامل را برمیدارد و نامعتبرها را کنار میگذارد، پس نتیجه نمونهای یکنواخت از مجموعهٔ معتبر است و آنتروپیاش دقیقاً لگاریتم دودویی تعداد رمزهای معتبر است.
byte = 0 to 255, alphabet = 90هر بایت از crypto.getRandomValues میآید. Math.random هیچجا استفاده نمیشود و اگر روزی استفاده شود آزمونی شکست میخورد.
character = byte % 90 <- wrong۲۵۶ مضرب ۹۰ نیست، پس این کار ۷۶ نویسهٔ اول را در هر ۲۵۶ بایت سه بار و ۱۴ نویسهٔ دیگر را فقط دو بار برمیگرداند. سوگیری ۵۰٪ به سمت ابتدای الفبا.
if (byte >= 180) draw another۱۸۰ بزرگترین مضرب صحیح ۹۰ زیر ۲۵۶ است. دور انداختن باقیمانده همان چیزی است که بقیه را یکنواخت میکند.
character = byte % 90حالا هر نویسه دقیقاً به اندازهٔ هر نویسهٔ دیگری محتمل است. هزینه بسیار کمتر از یک بایت اضافی در هر نویسه است.
یک نمونهٔ کارشده
بیست نویسه، هر چهار نوع روشن، نویسههای شبیه به هم مجاز، دستکم یکی از هر نوع الزامی.
| الفبا | ۲۶ + ۲۶ + ۱۰ + ۲۸ = ۹۰ |
| آنتروپی بدون قید | ۲۰ × لگاریتم دودویی ۹۰ = ۱۲۹٫۸۳۷۱ بیت |
| سهم رشتههایی که هر چهار نوع را دارند | ۹۰٫۲۵٪ |
| آنتروپی بهصورت تولیدشده | ۱۲۹٫۶۸۹۱ بیت، نمایشدادهشده بهصورت ۱۲۹٫۷ |
| میانگین حدسهای لازم | ۲ به توان ۱۲۸٫۶۸۹۱ |
| با ۱۰۰ میلیارد حدس در ثانیه | ۱۷۴ کوئینتیلیون سال |
پس قاعدهای که سیاست پیچیدگی یک وبسایت را برآورده میکند ۰٫۱۴۸ بیت هزینه دارد، که در کنار آنچه اغلب گمان میرود و در کنار آنچه یک نویسهٔ اضافی میخرد — ۶٫۴۹ بیت — یک خطای گرد کردن است.
همان تنظیمات در طولهای دیگر:
| طول | آنتروپی | میانگین زمان حدس زدن |
|---|---|---|
| ۸ | ۵۰٫۹ بیت | ۳ ساعت |
| ۱۲ | ۷۷٫۴ بیت | ۳۲٫۱ هزار سال |
| ۱۶ | ۱۰۳٫۶ بیت | ۲٫۴۶ تریلیون سال |
| ۲۰ | ۱۲۹٫۷ بیت | ۱۷۴ کوئینتیلیون سال |
| ۱۲۸ | ۸۳۱٫۰ بیت | ۲٫۲ × ۱۰^۲۳۱ سال |
اینها همان اعدادی هستند که در فایل آزمون این ابزار تأیید میشوند، پس اگر فرمول بدون تغییر این صفحه تغییر کند، ساخت شکست میخورد.
کاری که انجام نمیدهد
رمز عبور را با پیکرهای از نشتها مقایسه نمیکند و نیازی هم ندارد: رمز عبوری که بهطور تصادفی از ۹۰ نویسه برداشته شده هرگز در هیچ نشتی ظاهر نشده است. چیزی ذخیره نمیکند، پس سابقهای نیست و راهی برای بازیابی رمزی که تب را روی آن بستهاید وجود ندارد — اول آن را در مدیر رمز عبور کپی کنید. نمیداند سمت دیگر آنچه را میدهید چگونه ذخیره میکند، و این همان فرضی است که رقم زمان حدس زدن را بیش از همه جابهجا میکند: ۱۰۰ میلیارد حدس در ثانیه برای یک هش سریع بدون salt درست و برای Argon۲ بهشدت بدبینانه است.
و به دو راهی که رمزهای عبور واقعاً شکست میخورند کمکی نمیکند. استفادهٔ دوباره یک نشت را به چندین نشت تبدیل میکند و فیشینگ یک راز ۱۲۸ بیتی را به همان آسانی یک راز چهاررقمی تحویل میدهد. آنتروپی حد پایینی برای زحمت حدس زدن است، نه معیاری برای امن بودن یک حساب.
مراحل انجام کار
- الفبا را از بههمپیوستن کلاسهای نویسهٔ روشن بسازید — ۲۶ حرف کوچک، ۲۶ حرف بزرگ، ۱۰ رقم و ۲۸ علامت نگارشی ASCII که دو نویسهٔ نقلقول، بکتیک و بکاسلش از آن کنار گذاشته شدهاند.
- اگر نویسههای شبیه به هم کنار گذاشته شدهاند، پیش از هر کار دیگری I بزرگ، l کوچک، یک، خط عمودی (|)، صفر و O بزرگ را از آن الفبا حذف کنید.
- حد رد را حساب کنید — بزرگترین مضرب صحیح اندازهٔ الفبا که از ۲۵۶ بزرگتر نباشد. برای الفبای ۹۰تایی این حد ۱۸۰ است.
- یک بایت از crypto.getRandomValues بردارید. اگر برابر یا بزرگتر از حد است دورش بیندازید، چون تا کردن آن با باقیمانده، چند نویسهٔ اول الفبا را محتملتر از بقیه میکند. در غیر این صورت نویسهٔ متناظر با باقیماندهٔ آن بایت را بردارید.
- تا رسیدن نامزد به طول درخواستی تکرار کنید.
- اگر دستکم یکی از هر نوع لازم است و نامزد یک نوع را ندارد، کل نامزد را دور بیندازید و نامزد تازهای بردارید. آن را با جایگزین کردن یک نویسه تعمیر نکنید، چون توزیعی میسازد که هیچکس نمیتواند آنتروپیاش را بیان کند.
- رمزهای عبوری را که این تنظیمات میتوانند تولید کنند با اصل شمول و طرد روی کلاسها بشمارید و لگاریتم پایهٔ ۲ آن شمار را بهعنوان آنتروپی بر حسب بیت گزارش کنید.
فرضها
- رقم آنتروپی مولد را توصیف میکند، نه رشته را. رشتهای از ۲۰ حرف کوچک دقیقاً به اندازهٔ هر برداشت دیگری با همان تنظیمات قوی است، چون مهاجم راهی ندارد بداند که چنین درآمده است.
- الزام دستکم یکی از هر نوع، تعداد رمزهایی را که مولد میتواند تولید کند کم میکند، پس آنتروپی را کاهش میدهد. این ابزار رقم کاهشیافته را گزارش میکند؛ بیشتر مولدها رقم بزرگتر را.
- زمان حدس زدن ۱۰۰ میلیارد حدس در ثانیه را فرض میکند، که یک حملهٔ آفلاین با سختافزار گرافیکی معمولی در برابر یک هش سریع و بدون salt است. رمز عبوری که با bcrypt یا Argon۲ ذخیره شده باشد چندین مرتبهٔ بزرگی کندتر حمله میشود و ورودِ با نرخ محدود باز هم کندتر است.
- زمان نشاندادهشده میانگین است، نه بدترین حالت — نیمی از فضای جستوجو، یعنی دو به توان یک واحد کمتر از آنتروپی.
- دو نویسهٔ نقلقول، بکتیک و بکاسلش از مجموعهٔ نمادها کنار گذاشته شدهاند، چون وقتی رمز عبور در یک دستور پوسته یا فایل JSON جایگذاری شود مشکلساز میشوند. این حدود ۰٫۰۶ بیت در هر نویسه هزینه دارد.
- آنتروپی چیزی دربارهٔ استفادهٔ دوباره، فیشینگ یا نشت داده در سمت دیگر نمیگوید. یک رمز عبور بینقص که در دو جا استفاده شود، یک رمز عبور است.
پرسشهای رایج
آیا رمز عبور به جایی فرستاده یا ذخیره میشود؟
خیر. مرورگر شما آن را تولید میکند و فقط در صفحهٔ روبهروی شما وجود دارد. سروری برای فرستادنش نیست — کل سایت فایلهای ایستاست. تنظیمات در نوار آدرس منتقل میشوند تا یک پیوند همان گزینهها را بازتولید کند، اما خود رمز عبور عمداً از آن بیرون نگه داشته میشود؛ بنابراین کپی کردن پیوند، دستور پخت را به اشتراک میگذارد نه راز را.
چرا آنتروپی اینجا کمتر از سایتهای رمز عبور دیگر است؟
چون «دستکم یکی از هر نوع» روشن است و این قاعده مجموعهٔ رمزهایی را که مولد میتواند تولید کند کوچک میکند. در ۲۰ نویسه تقریباً یک رشته از هر ده رشته را رد میکند، که ۰٫۱۵ بیت هزینه دارد. بیشتر مولدها این قاعده را اعمال میکنند و بعد رقم برداشت بدون قید را گزارش میکنند، که اندکی زیادی بالاست. قاعده را خاموش کنید تا دو رقم یکی شوند.
آیا هشت نویسه کافی است؟
خیر. هشت نویسه از الفبای ۹۰تایی ۵۰٫۹ بیت میدهد که با ۱۰۰ میلیارد تلاش در ثانیه حدود سه ساعت حدس زدن است. دوازده نویسه ۷۷٫۴ بیت و با همان نرخ حدود ۳۲٬۰۰۰ سال است؛ شانزده نویسه ۱۰۳٫۶ بیت. طول تنها تنظیمی است که پاسخ را چند مرتبهٔ بزرگی تغییر میدهد.
آیا این ابزار از Math.random استفاده میکند؟
هرگز. هر بایت از crypto.getRandomValues میآید که مولد رمزنگاری پلتفرم است. Math.random یک الگوریتم سریع و غیررمزنگاری با وضعیت درونی کوچکی است که از چند خروجی خودش بازیابی میشود، پس رمز عبوری که از آن ساخته شود را هر کسی که رمز دیگری را ببیند میتواند بازتولید کند. در فایل آزمون این ابزار آزمونی هست که اگر Math.random فراخوانی شود شکست میخورد.
آیا باید «نویسههای شبیه به هم کنار گذاشته شوند» را روشن کنم؟
فقط برای رمز عبوری که کسی باید بخواند و دوباره تایپ کند — عبارت عبور وایفای روی برچسب روتر، یا رمز موقتی که پشت تلفن خوانده میشود. حرف I، حرف کوچک l، رقم یک، خط عمودی، رقم صفر و حرف O را حذف میکند که الفبا را از ۹۰ به ۸۴ کوچک میکند و حدود ۰٫۱ بیت در هر نویسه هزینه دارد. برای هر چیزی که مستقیم به مدیر رمز عبور میرود، اتلافی بیفایده است.
رمز عبور واقعاً چقدر باید بلند باشد؟
آنقدر که آنتروپی برای حسابی که مهم است از ۸۰ بیت بگذرد، که با این تنظیمات ۱۳ نویسه است، و برای رمز عبور اصلی یا کلید رمزنگاری از ۱۲۸ بیت بگذرد، که ۲۰ نویسه است. هر دو آستانه در فایل آزمون این ابزار تأیید میشوند. فراتر از آن، رمز عبور با فاصلهٔ زیاد دیگر ضعیفترین بخش سامانه نیست.
منابع
روش را Tessalor در ۸ مرداد ۱۴۰۵ نوشته و بررسی کرده است.