Crypt::OpenSSL::RSA

RSA暗号・電子署名アルゴリズムを実行するOpenSSLラッパモジュール。

use Crypt::OpenSSL::RSA;
パッケージをロードする。

my $rsa = Crypt::OpenSSL::RSA->generate_key($size);
鍵のbitサイズを指定して鍵を生成し、インスタンスを作成する。

my $rsa = Crypt::OpenSSL::RSA->new_public_key($key_string);
Base64/DERエンコードされたPKCS#1またはX.509表記の公開鍵を入力してインスタンスを生成する。

my $rsa = Crypt::OpenSSL::RSA->new_private_key($key_string);
Base64/DERエンコードされたPKCS#1表記の秘密鍵を入力してインスタンスを生成する。

my $rsa = Crypt::OpenSSL::RSA->new_key_from_parameters($n, $e, $d, $p, $q);
鍵パラメタの実値を入力してインスタンスを生成する。各鍵パラメタは、Crypt::OpenSSL::Bignum オブジェクトを入力すること。暗号化・署名検証しか実行しないのであれば、秘密鍵パラメタ d, p, q は省略可。

my $encrypted = $rsa->encrypt($plain);
暗号化を実行する。平文サイズの制限は下記の通り。
PKCS#1 padding:鍵長-11バイト以下
OAEP padding:鍵長-42バイト以下
paddingなし:鍵長と同じ(「以下」ではない)

my $plain = $rsa->decrypt($encrypted);
復号を実行する。暗号文サイズは鍵長と一致していなければならない。

my $signature = $rsa->sign($text);
入力データに対する電子署名を生成する。デフォルトのハッシュ関数はSHA-1。use_sha256_hash() メソッドなどを使って変更することも出来る。

my $result = $rsa->verify($text, $signature);
署名検証を行なう。

$rsa->use_pkcs1_padding();
PKCS#1 v1.5 paddingを指定する。デフォルト。

$rsa->use_oaep_padding();
PKCS#1 v2.0 で追加されたOAEP paddingを指定する。padding

$rsa->use_no_padding();
paddingを実行しない。モジュール外部で適切なpaddingを行なって入力する場合に使用する。

my $public = $rsa->get_public_key_string();
DER/Base64エンコードして公開鍵を出力する。

my $public = $rsa->get_public_key_x509_string();
X.509/Base64エンコードして公開鍵を出力する。

my $private = $rsa->get_private_key_string();
DER/Base64エンコードして秘密鍵を出力する。

my ($n, $e, $d, $p, $q) = $rsa->get_key_parameters();
鍵パラメタの実値を取得する。各鍵パラメタは、Crypt::OpenSSL::Bignum オブジェクトで出力される。

my $size = $rsa->size();
保持されている鍵のバイト長を返す。


Crypt::RSAなるモジュールもあるが、このモジュールには色々バクがあるので、Crypt::OpenSSL::RSA を使うこと。確認済みのバグは以下の通り。Active Perl では Crypt::OpenSSL::RSAはサポートされていないので、下記の箇所を修正してCrypt::RSAを使うしかない。

Crypt::RSA::Key::Private::check()
暗号化と署名検証は、公開鍵だけで実行できる(できないと困る)が、秘密鍵の整合性までチェックしてしまっているため、秘密鍵を持っていない状態だとエラーが発生して暗号化・署名検証を実行できない。

Crypt::RSA::Key::msg1()
MGF1関数の仕様が間違っている。
ループカウンタが +4 づつされていて、且つ、ループ回数が違う 。下記のソースが正解。
sub mgf1 {
     my ($seed, $l) = @_; 
     my $hlen = 20;  my ($T, $i) = ("",0);
     for (0 .. ($l/$hlen)) {
         my $C = i2osp (int($i), 4);
         $T .= sha1("$seed$C");
         ++$i;
     }
     my ($output) = unpack "a$l", $T;
     return $output;
}