模冪 (英語:modular exponentiation )是一種對模 進行的冪 運算,在電腦科學 ,尤其是公開金鑰加密 方面有一定用途。
模冪運算是指求整數
b
{\displaystyle b}
的
e
{\displaystyle e}
次方
b
e
{\displaystyle b^{e}}
被正整數
m
{\displaystyle m}
所除得到的餘數
c
{\displaystyle c}
的過程,可用數學符號表示為
c
=
b
e
mod
m
{\displaystyle c=b^{e}{\bmod {m}}}
。由
c
{\displaystyle c}
的定義可得
0
≤
c
<
m
{\displaystyle 0\leq c<m}
。
例如,給定
b
=
5
{\displaystyle b=5}
,
e
=
3
{\displaystyle e=3}
和
m
=
13
{\displaystyle m=13}
,
5
3
=
125
{\displaystyle 5^{3}=125}
被13除得的餘數
c
=
8
{\displaystyle c=8}
。
指數
e
{\displaystyle e}
為負數時可使用擴充歐幾里得演算法 找到
b
{\displaystyle b}
模除
m
{\displaystyle m}
的模反元素
d
{\displaystyle d}
來執行模冪運算,即:
c
=
b
e
mod
m
=
d
−
e
mod
m
{\displaystyle c=b^{e}{\bmod {m}}=d^{-e}{\bmod {m}}}
,其中
e
<
0
{\displaystyle e<0}
且
b
⋅
d
≡
1
(
mod
m
)
{\displaystyle b\cdot d\equiv 1{\pmod {m}}}
。
即使在整數很大的情況下,上述模冪運算其實也是易於執行的。然而,計算模的離散對數 (即在已知
b
{\displaystyle b}
,
c
{\displaystyle c}
和
m
{\displaystyle m}
時求出指數
e
{\displaystyle e}
)則較為困難。這種類似單向函式 的表現使模冪運算可用於加密演算法。
直接演算法
計算模冪的最直接方法是直接算出
b
e
{\displaystyle b^{e}}
,再把結果模除
m
{\displaystyle m}
。假設已知
b
=
4
{\displaystyle b=4}
,
e
=
13
{\displaystyle e=13}
,以及
m
=
497
{\displaystyle m=497}
,要求
c
{\displaystyle c}
:
c
≡
4
13
(
mod
497
)
{\displaystyle c\equiv 4^{13}{\pmod {497}}}
可用計算機算得413 結果為67,108,864,模除497,可得c 等於445。
注意到
b
{\displaystyle b}
只有一位,
e
{\displaystyle e}
也只有兩位,但
b
e
{\displaystyle b^{e}}
的值卻有8位元。
強加密時
b
{\displaystyle b}
通常至少有1024位元[ 1] 。考慮
b
=
5
×
10
76
{\displaystyle b=5\times 10^{76}}
和
e
=
17
{\displaystyle e=17}
的情況,
b
{\displaystyle b}
的長度為77位,
e
{\displaystyle e}
的長度為2位,但是
b
e
{\displaystyle b^{e}}
的值以十進制 表示卻已經有1304位元。現代電腦雖然可以進行這種計算,但計算速度卻大大降低。
用這種演算法求模冪所需的時間取決於操作環境和處理器,時間複雜度為
O
(
e
)
{\displaystyle \mathrm {O} (e)}
。
空間最佳化
這種方法比第一種所需要的步驟更多,但所需主記憶體空間和時間均大為減少,其原理為:
給定兩個整數
a
{\displaystyle a}
和
b
{\displaystyle b}
,以下兩個等式是等價的 [錨點失效 ] :
c
mod
m
=
(
a
⋅
b
)
mod
m
{\displaystyle c{\bmod {m}}=(a\cdot b){\bmod {m}}}
c
mod
m
=
[
(
a
mod
m
)
⋅
(
b
mod
m
)
]
mod
m
{\displaystyle c{\bmod {m}}=[(a{\bmod {m}})\cdot (b{\bmod {m}})]{\bmod {m}}}
演算法如下:
令
c
=
1
{\displaystyle c=1}
,
e
′
=
0
{\displaystyle e'=0}
。
e
′
{\displaystyle e'}
自增1。
令
c
=
(
b
⋅
c
)
mod
m
{\displaystyle c=(b\cdot c){\bmod {m}}}
.
若
e
′
<
e
{\displaystyle e'<e}
,則返回第二步;否則,
c
{\displaystyle c}
即為
c
≡
b
e
(
mod
m
)
{\displaystyle c\equiv b^{e}{\pmod {m}}}
。
再以
b
=
4
{\displaystyle b=4}
,
e
=
13
{\displaystyle e=13}
,
m
=
497
{\displaystyle m=497}
為例說明,演算法第三步需要執行13次:
e
′
=
1
⋅
c
=
(
1
⋅
4
)
mod
4
97
=
4
mod
4
97
=
4
{\displaystyle e'=1\cdot c=(1\cdot 4){\bmod {4}}97=4{\bmod {4}}97=4}
e
′
=
2
⋅
c
=
(
4
⋅
4
)
mod
4
97
=
16
mod
4
97
=
16
{\displaystyle e'=2\cdot c=(4\cdot 4){\bmod {4}}97=16{\bmod {4}}97=16}
e
′
=
3
⋅
c
=
(
16
⋅
4
)
mod
4
97
=
64
mod
4
97
=
64
{\displaystyle e'=3\cdot c=(16\cdot 4){\bmod {4}}97=64{\bmod {4}}97=64}
e
′
=
4
⋅
c
=
(
64
⋅
4
)
mod
4
97
=
256
mod
4
97
=
256
{\displaystyle e'=4\cdot c=(64\cdot 4){\bmod {4}}97=256{\bmod {4}}97=256}
e
′
=
5
⋅
c
=
(
256
⋅
4
)
mod
4
97
=
1024
mod
4
97
=
30
{\displaystyle e'=5\cdot c=(256\cdot 4){\bmod {4}}97=1024{\bmod {4}}97=30}
e
′
=
6
⋅
c
=
(
30
⋅
4
)
mod
4
97
=
120
mod
4
97
=
120
{\displaystyle e'=6\cdot c=(30\cdot 4){\bmod {4}}97=120{\bmod {4}}97=120}
e
′
=
7
⋅
c
=
(
120
⋅
4
)
mod
4
97
=
480
mod
4
97
=
480
{\displaystyle e'=7\cdot c=(120\cdot 4){\bmod {4}}97=480{\bmod {4}}97=480}
e
′
=
8
⋅
c
=
(
480
⋅
4
)
mod
4
97
=
1920
mod
4
97
=
429
{\displaystyle e'=8\cdot c=(480\cdot 4){\bmod {4}}97=1920{\bmod {4}}97=429}
e
′
=
9
⋅
c
=
(
429
⋅
4
)
mod
4
97
=
1716
mod
4
97
=
225
{\displaystyle e'=9\cdot c=(429\cdot 4){\bmod {4}}97=1716{\bmod {4}}97=225}
e
′
=
10
⋅
c
=
(
225
⋅
4
)
mod
4
97
=
900
mod
4
97
=
403
{\displaystyle e'=10\cdot c=(225\cdot 4){\bmod {4}}97=900{\bmod {4}}97=403}
e
′
=
11
⋅
c
=
(
403
⋅
4
)
mod
4
97
=
1612
mod
4
97
=
121
{\displaystyle e'=11\cdot c=(403\cdot 4){\bmod {4}}97=1612{\bmod {4}}97=121}
e
′
=
12
⋅
c
=
(
121
⋅
4
)
mod
4
97
=
484
mod
4
97
=
484
{\displaystyle e'=12\cdot c=(121\cdot 4){\bmod {4}}97=484{\bmod {4}}97=484}
e
′
=
13
⋅
c
=
(
484
⋅
4
)
mod
4
97
=
1936
mod
4
97
=
445
{\displaystyle e'=13\cdot c=(484\cdot 4){\bmod {4}}97=1936{\bmod {4}}97=445}
因此最終結果
c
{\displaystyle c}
為445,與第一種方法所求結果相等。
與第一種方法相同,這種演算法需要
O
(
e
)
{\displaystyle \mathrm {O} (e)}
的時間才能完成。但是,由於在計算過程中處理的數字比第一種演算法小得多,因此計算時間至少減少了
O
(
e
)
{\displaystyle \mathrm {O} (e)}
倍。
演算法虛擬碼如下:
function modular_pow(b, e, m)
if m = 1
then return 0
c := 1
for e' = 0 to e-1
c := (c * b) mod m
return c
從右到左二位演算法
第三種方法結合了第二種演算法和平方求冪 原理,使所需步驟大大減少,同時也與第二種方法一樣減少了主記憶體占用量。
首先把
e
{\displaystyle e}
表示成二進制 ,即:
e
=
∑
i
=
0
n
−
1
a
i
2
i
{\displaystyle e=\sum _{i=0}^{n-1}a_{i}2^{i}}
此時
e
{\displaystyle e}
的長度為
n
{\displaystyle n}
位。對任意
i
{\displaystyle i}
(
0
≤
i
<
n
{\displaystyle 0\leq i<n}
),
a
i
{\displaystyle a_{i}}
可取0或1任一值。由定義有
a
n
−
1
=
1
{\displaystyle a_{n-1}=1}
。
b
e
{\displaystyle b^{e}}
的值可寫作:
b
e
=
b
(
∑
i
=
0
n
−
1
a
i
2
i
)
=
∏
i
=
0
n
−
1
(
b
2
i
)
a
i
{\displaystyle b^{e}=b^{\left(\sum _{i=0}^{n-1}a_{i}2^{i}\right)}=\prod _{i=0}^{n-1}\left(b^{2^{i}}\right)^{a_{i}}}
因此答案
c
{\displaystyle c}
即為:
c
≡
∏
i
=
0
n
−
1
(
b
2
i
)
a
i
(
mod
m
)
{\displaystyle c\equiv \prod _{i=0}^{n-1}\left(b^{2^{i}}\right)^{a_{i}}\ ({\mbox{mod}}\ m)}
虛擬碼
下述虛擬碼基於布魯斯·施奈爾 所著《應用密碼學》[ 2] 。其中base ,exponent 和modulus 分別對應上式中的
b
{\displaystyle b}
,
e
{\displaystyle e}
和
m
{\displaystyle m}
。
function modular_pow(base, exponent, modulus)
if modulus = 1 then return 0
Assert :: (modulus - 1) * (modulus - 1) does not overflow base
result := 1
base := base mod modulus
while exponent > 0
if (exponent mod 2 == 1):
result := (result * base) mod modulus
exponent := exponent >> 1
base := (base * base) mod modulus
return result
注意到在首次進入迴圈時,變數base 等於
b
{\displaystyle b}
。在第三行代碼中重複執行平方運算,會確保在每次迴圈結束時,變數base 等於
b
2
i
mod
m
{\displaystyle b^{2^{i}}{\bmod {m}}}
,其中
i
{\displaystyle i}
是迴圈執行次數。
本例中,底數
b
{\displaystyle b}
的指數為
e
=
13
{\displaystyle e=13}
。
指數用二進制表示為1101,有4位元,故迴圈執行4次。
4位元數字從右到左依次為1,0,1,1。
首先,初始化結果
R
{\displaystyle R}
為1,並將b 的值儲存在變數
x
{\displaystyle x}
中:
R
←
1
(
=
b
0
)
且
x
←
b
{\displaystyle R\leftarrow 1\,(=b^{0}){\text{且 }}x\leftarrow b}
.
第1步 第1位為1,故令
R
←
R
⋅
x
(
=
b
1
)
{\displaystyle R\leftarrow R\cdot x{\text{ }}(=b^{1})}
;
令
x
←
x
2
(
=
b
2
)
{\displaystyle x\leftarrow x^{2}{\text{ }}(=b^{2})}
。
第2步 第2位為0,故不給R 賦值;
令
x
←
x
2
(
=
b
4
)
{\displaystyle x\leftarrow x^{2}{\text{ }}(=b^{4})}
。
第3步 第3位為1,故令
R
←
R
⋅
x
(
=
b
5
)
{\displaystyle R\leftarrow R\cdot x{\text{ }}(=b^{5})}
;
令
x
←
x
2
(
=
b
8
)
{\displaystyle x\leftarrow x^{2}{\text{ }}(=b^{8})}
。
第4步 第4位元為1,故令
R
←
R
⋅
x
(
=
b
13
)
{\displaystyle R\leftarrow R\cdot x{\text{ }}(=b^{13})}
;
這是最後一步,所以不需要對x 求平方。
綜上,
R
{\displaystyle R}
為
b
13
{\displaystyle b^{13}}
。
以下計算
b
=
4
{\displaystyle b=4}
的
e
=
13
{\displaystyle e=13}
次方對497求模的結果。
初始化:
R
←
1
(
=
b
0
)
{\displaystyle R\leftarrow 1\,(=b^{0})}
且
x
←
b
=
4
{\displaystyle x\leftarrow b=4}
。
第1步 第1位為1,故令
R
←
R
⋅
4
(
mod
497
)
≡
4
(
mod
497
)
{\displaystyle R\leftarrow R\cdot 4{\pmod {497}}\equiv 4{\pmod {497}}}
;
令
x
←
x
2
(
=
b
2
)
≡
4
2
≡
16
(
mod
497
)
{\displaystyle x\leftarrow x^{2}{\text{ }}(=b^{2})\equiv 4^{2}\equiv 16{\pmod {497}}}
。
第2步 第2位為0,故不給R 賦值;
令
x
←
x
2
(
=
b
4
)
≡
16
2
(
mod
497
)
≡
256
(
mod
497
)
{\displaystyle x\leftarrow x^{2}{\text{ }}(=b^{4})\equiv 16^{2}{\pmod {497}}\equiv 256{\pmod {497}}}
。
第3步 第3位為1,故令
R
←
R
⋅
x
(
=
b
5
)
≡
4
⋅
256
(
mod
497
)
≡
30
(
mod
497
)
{\displaystyle R\leftarrow R\cdot x{\text{ }}(=b^{5})\equiv 4\cdot 256{\pmod {497}}\equiv 30{\pmod {497}}}
;
令
x
←
x
2
(
=
b
8
)
≡
256
2
(
mod
497
)
≡
429
(
mod
497
)
{\displaystyle x\leftarrow x^{2}{\text{ }}(=b^{8})\equiv 256^{2}{\pmod {497}}\equiv 429{\pmod {497}}}
。
第4步 第4位元為1,故令
R
←
R
⋅
x
(
=
b
13
)
≡
30
⋅
429
(
mod
497
)
≡
445
(
mod
497
)
{\displaystyle R\leftarrow R\cdot x{\text{ }}(=b^{13})\equiv 30\cdot 429{\pmod {497}}\equiv 445{\pmod {497}}}
;
綜上,
R
{\displaystyle R}
為
4
13
(
mod
497
)
≡
445
(
mod
497
)
{\displaystyle 4^{13}{\pmod {497}}\equiv 445{\pmod {497}}}
,與先前演算法中所得結果相同。
該演算法時間複雜度為O(log exponent ) 。指數exponent 值較大時,這種演算法與前兩種O( exponent ) 演算法相比具有明顯的速度優勢。例如,如果指數為220 = 1048576,此演算法只需執行20步,而非1,048,576步。
function modPow(b,e,m)
if m == 1 then
return 0
else
local r = 1
b = b % m
while e > 0 do
if e % 2 == 1 then
r = (r*b) % m
end
e = e >> 1 --Lua 5.2或更早版本使用e = math.floor(e / 2)
b = (b^2) % m
end
return r
end
end
軟體實現
鑑於模冪運算是電腦科學中的重要操作,並且已有高效演算法,所以許多程式語言和高精度整數庫都有執行模冪運算的函式:
另見
參考資料
外部連結