https://milestone-of-se.nesuke.com/nw-basic/tls/rsa-summary/
# cat rsa.pl
use Math::BigInt;
#data
my $data = Math::BigInt->new("508");
print "data: ".$data."\n";
# encrypt
# koukaikagi 223, 1357
my $pubkey1 = 223;
my $pubkey2 = 1357;
my $crypt = ($data ** $pubkey1) % $pubkey2;
print "crypted data: ".$crypt."\n";
#decrypt
#himitukagi 103
my $privkey = 103;
$decrypt = ($crypt ** $privkey) % $pubkey2;
print "decrypted data: ".$decrypt."\n";
実行結果
# perl rsa.pl data: 508 crypted data: 1319 decrypted data: 508元のデータは 508
公開鍵となる数字は2つのペアで 223と1357である。
暗号化されたデータは、元のデータを223乗して、それを1357で割った余りとして作成し
この例ではその値は 1319である。
秘密鍵の値は103である。
復号は、1319を103乗して1357で割った余りとして求め、
その値は508であり、元のデータと一致する。
結果だけ見ると3~4桁の数字であるが、
計算途中で「508の223乗」というとんでもない計算があり、
280桁くらいになるので BigIntを使っている。
しかし実際の暗号化においては、508などという数値どころではない
文字列や画像、音声などを暗号化しているのだから
とてつもない量の計算がされている。
そのために暗号化専用のチップなどが使われたりしているのだ。
注目すべきは下記の記述である。
「メッセージ m を e 乗 (公開鍵で暗号化) したものに対しては d 乗 (秘密鍵で復号) することで元の m に戻りますし、
メッセージ m を d 乗 (秘密鍵で暗号化) したものに対しては e 乗 (公開鍵で復号) することで元の m に戻るのです。」
これがよく話題になる、「電子署名のことを秘密鍵で暗号化するというのは間違い」
のことである。
この人は、「別に署名を秘密鍵で暗号化するといってもいいじゃないか。」
という旨のことを言っている。
私もそう思う。
では、署名と検証もやってみよう。
# cat sign.pl
use Math::BigInt;
#data
my $data = Math::BigInt->new("508");
print "data: ".$data."\n";
# encrypt
# koukaikagi 223, 1357
#himitukagi 103
my $pubkey1 = 223;
my $pubkey2 = 1357;
my $privkey = 103;
my $sign = ($data ** $privkey) % $pubkey2;
print "signed data: ".$sign."\n";
#verify
$verified = ($sign ** $pubkey1) % $pubkey2;
print "verified data: ".$verified."\n";
さっきの暗号化の計算と同じことを、暗号化時(署名時)に103乗し、復号時(検証時)に223乗、つまり逆にしている。
逆にしても、元の値に戻る。
# perl sign.pl data: 508 signed data: 315 verified data: 508当然、公開鍵と秘密鍵というのはどんな数字でもいいわけではなく、
上記のような計算が成り立つような数字を選ぶわけであるが、
「署名を秘密鍵で暗号化すると言ってはいけない」と怒ることはないんだなと、
ようやく安心できた。
python版
# cat rsa.py
data=508
pub1=223
pub2=1357
priv=103
print("data:"+str(data))
crypted=(data ** pub1) % pub2
print("crypted:"+str(crypted))
decrypted=(crypted ** priv) % pub2
print("decrypted:"+str(decrypted))
signed=(data ** priv) % pub2
print("signed:"+str(signed))
verified=(signed ** pub1) % pub2
print("verified:"+str(verified))
# python rsa.py
data:508
crypted:1319
decrypted:508
signed:315
verified:508
BigIntとかいらない。