3.2 KiB
id, title, challengeType, forumTopicId, dashedName
id | title | challengeType | forumTopicId | dashedName |
---|---|---|---|---|
5900f4231000cf542c50ff35 | 問題 182: RSA 暗号化 | 5 | 301818 | problem-182-rsa-encryption |
--description--
RSA 暗号化は次の手順で行われます。
2 つの相異なる素数 p
と q
を生成します。 n=p*q
と φ=(p-1)(q-1)
を計算します。 1 < e < φ
に対して、gcd(e,φ) = 1
となる整数 e
を見つけます。
この方式におけるメッセージは、区間 [0,n-1]
の中の数です。 次に、暗号化される文は何らかの形でメッセージ (区間 [0,n-1]
の中の数) に変換されます。 文を暗号化するために、メッセージごとに m
, c=me mod n が計算されます。
文を復号するには、ed=1 mod φ
となるような d
を計算し、暗号化されたメッセージ c
ごとに、m=cd mod n を計算するという手順が必要です。
me mod n = m となるような e
と m
の値が存在します。 me mod n = m となるメッセージ m
を非隠蔽メッセージと呼びます。
e
を選択する際の問題は、非隠蔽メッセージが多すぎてはいけないという点です。 例えば、p=19
, q=37
とします。 このとき、n=19*37=703
, φ=18*36=648
となります。 e=181
を選択した場合、gcd(181,648)=1
ですが、me mod n の計算時に、考えられるすべてのメッセージ m (0≤m≤n-1)
が非隠蔽メッセージとなります。 e
についてどのような有効な選択を行っても、非隠蔽メッセージがいくつか存在します。 非隠蔽メッセージの数が最小限であることが重要です。
1 < e < φ(p,q)
かつ gcd(e,φ)=1
のとき、与えられた任意の p
と q
について、e
値に対する非隠蔽メッセージの数が最小になるような e
値の総和を求めなさい。
--hints--
RSAEncryption
は関数でなければなりません。
assert(typeof RSAEncryption === 'function')
RSAEncryption
は数値を返す必要があります。
assert.strictEqual(typeof RSAEncryption(19, 37), 'number');
RSAEncryption(19, 37)
は 17766
を返す必要があります。
assert.strictEqual(RSAEncryption(19, 37), 17766);
RSAEncryption(283, 409)
は 466196580
を返す必要があります。
assert.strictEqual(RSAEncryption(283, 409), 466196580);
RSAEncryption(1009, 3643)
は 399788195976
を返す必要があります。
assert.strictEqual(RSAEncryption(19, 37), 17766);
--seed--
--seed-contents--
function RSAEncryption(p, q) {
return true;
}
RSAEncryption(19, 37);
--solutions--
function gcd(a, b) {
if (b)
return gcd(b, a % b);
else
return a;
}
function RSAEncryption(p, q) {
let phi = (p - 1) * (q - 1);
let best = Number.MAX_SAFE_INTEGER;
let sum = 0;
for (let e = 0; e < phi; ++e) {
if (!(gcd(e, phi) == 1))
continue;
let msg = (gcd(p - 1, e - 1) + 1) * (gcd(q - 1, e - 1) + 1);
if (best == msg) {
sum += e;
} else if (best > msg) {
best = msg;
sum = e;
}
}
return sum;
}