Convert::PEM

ASN.1 PEMファイルを読み書きする

use Convert::PEM;
パッケージをロードする。

my $pem = Convert::PEM->new(Name => $name, ASN => $module);
インスタンスを生成する。
$name : PEMファイルのヘッダ文字列(---- BEGIN の後ろの文字列)
$module : ASN.1モジュール定義

my $obj = $pem->decode(Content => $asn1, Password => $pwd);
PEMをデコードしてハッシュ参照を返す。
$asn1 : PEMファイルの内容
$pwd : PEMファイルのパスワード(暗号化されている場合)

my $asn1 = $pem->encode(Content => $obj, Password => $pwd);
ハッシュ参照をPEMにエンコードする。
$obj : PEMファイルにエンコードするデータ
$pwd : PEMファイルのパスワード(暗号化したい場合)

my $obj = $pem->read(Filename => $name, Password => $pwd);
PEMファイルをデコードしてハッシュ参照を返す。
$name : PEMファイル名
$pwd : PEMファイルのパスワード(暗号化されている場合)

my $asn1 = $pem->write(Filename => $name, Password => $pwd);
ハッシュ参照をエンコードしてPEMファイルに書き込む。
$name : PEMファイル名
$pwd : PEMファイルのパスワード(暗号化したい場合)


ASN.1モジュールの記述方法
RFCなどに定義されているモジュール記述を、ほぼそのまま書けばよい。

ECDSA秘密鍵の例:(RFC5915)

   ECPrivateKey ::= SEQUENCE {
     version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
     privateKey     OCTET STRING,
     parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
     publicKey  [1] BIT STRING OPTIONAL
   }

    my $pvKeyASN1 = qq(
        SEQUENCE {
            version       INTEGER,
            privateKey    OCTET STRING,
            parameters [0]   EXPLICIT OBJECT IDENTIFIER OPTIONAL,
            publicKey [1]    EXPLICIT BIT STRING OPTIONAL
        }
    );

[0]などのタグがある場合、EXPLICIT属性の指定は必須。デフォルトがIMPLICIT属性なので、内側のタグが省略される。

上記の例だと、下記の様なハッシュ参照で読み書きする。
エンコード時は、SEQUENCEのネスト深さに関わらず、名前で参照してエンコードしてくれる。
デコード時は、BIT STRINGは長さ1の配列に保存されるなど、若干の違いがある様だ。

$obj = {
    version => 1,
    privateKey => $dStr,
    parameter => $curveID,
    publicKey => $qStr
};

OIDは、'1.2.840.10045.3.1.7'の様なOID表記の文字列
OCTET STRINGやBIT STRINGは、perlの文字列リテラルで表現される