توان پیمانهای (مربعسازی پیاپی)
aᵇ mod n را با حدود log b ضرب حساب میکند: پایه را پشت سر هم مربع میکند و برای هر بیت ۱ توان، آن را در جواب ضرب میکند.
حساب کردن aᵇ با b − 1 ضرب برای b بزرگ (مثلاً در RSA) ناممکن است. ولی اگر b را در مبنای ۲ بنویسیم:
- زمان:
O(log b) - حافظه:
O(1) - CLRS، بخش ۳۱.۶
- جانسونباو، فصل ۵
۷⁵⁶⁰ mod ۵۶۱ = ۱؛ ۵۶۰ ده بیت دارد، پس بهجای ۵۵۹ ضرب، ۱۳ ضرب (۱۰ مربع و ۳ ضرب در جواب) کافی است.
def mod_pow(a, b, n):# a to the power b, mod n, reading the bits of b from the right.result = 1 % nbase = a % nrows = []while b > 0:bit = b % 2if bit == 1:result = result * base % nrows.append((bit, base, result))base = base * base % nb = b // 2return result
شروع اجرا
b560
base—
result—
جدول هنوز خالی است.
متغیرهای محلی
a7
b560
n561
نارنجی = در همین گام عوض شد
Call stack
- mod_pow()خط 1
گام ۱ از ۶۹
توضیح
ایده
حساب کردن aᵇ با b − 1 ضرب برای b بزرگ (مثلاً در RSA) ناممکن است. ولی اگر b را در مبنای ۲ بنویسیم:
b = 560 = 1000110000₂ ⇒ a⁵⁶⁰ = a⁵¹² · a³² · a¹⁶
توانهای a¹, a², a⁴, a⁸, … با مربع کردن پیاپی به دست میآیند و فقط آنهایی که بیتشان ۱ است در جواب ضرب میشوند. بعد از هر ضرب mod n میگیریم تا عددها کوچک بمانند.
هزینه
حداکثر 2 log b ضرب. پایهی RSA، آزمون میلر–رابین و دیفی–هلمن.
در trace به چه چیزی نگاه کنی
- هر سطر جدول یک بیت از
bاست (از راست): بیت، پایهی آن دور و جواب تا آن لحظه.