[僕] DBIC の Component を書いてみる。

僕ト云フ事

たろマークはてなブックマーク

2007年05月13日

[dbic][perl][pgp] DBIC の Component を書いてみる。

WEB+DB PRESS の id:naoya さんの連載(Vol35, Vol36)を読んだり YAPC::ASIA 2007 での id:nekokak さん(資料)、id:tokuhirom さん(資料)の講演を拝聴したりして、最近はちょこちょこと DBIx::Class を使い始めてます。

んで、理解を進めるために自分で Component を書いてみました。Crypt::OpenPGP を使って、DB に突っ込むときに暗号化、取り出すときに復号化する Component です。

package DBIx::Class::OpenPGPColumns;
use strict;
use warnings;
use base 'DBIx::Class';
use Crypt::OpenPGP;
 
__PACKAGE__->mk_classdata( '_openpgp_columns' );
__PACKAGE__->mk_classdata( 'recipients' );
__PACKAGE__->mk_classdata( armour => 1 );
__PACKAGE__->mk_classdata( 'passphrase' );
 
=head2 openpgp
 
=cut
 
sub openpgp {
    my $self = shift;
    $self->{_openpgp} ||= Crypt::OpenPGP->new;
    $self->{_openpgp};
}
 
sub openpgp_columns {
    my $self = shift;
 
    if (@_) {
        foreach my $col (@_) {
            $self->throw_exception("column $col doesn't exist")
                unless $self->has_column($col);
        }
        return $self->_openpgp_columns({ map { $_ => 1 } @_ });
    }
    else {
        return $self->_openpgp_columns;
    }
}
 
sub get_column {
    my ( $self, $column ) = @_;
    my $value = $self->next::method($column);
 
    my $cols = $self->_openpgp_columns;
 
    if ( $cols and defined $value and $cols->{$column}) {
        $value = $self->openpgp->decrypt(
            Data       => $value,
            Passphrase => $self->passphrase,
        );
    }
 
    $value;
}
 
sub store_column {
    my ( $self, $column, $value ) = @_;
 
    my $cols = $self->_openpgp_columns;
 
    if ( $cols and defined $value and $cols->{$column}) {
        $value = $self->openpgp->encrypt(
            Data       => $value,
            Recipients => $self->recipients,
            Armour     => $self->armour,
        );
    }
 
    $self->next::method( $column, $value );
}
 
1;

使うときは他の Component と同じように呼び出します。

package MyApp::Schema;
 
use strict;
use warnings;
 
use base qw/DBIx::Class::Schema::Loader/;
 
__PACKAGE__->loader_options(
    debug => 0,
    components => [qw(
        OpenPGPColumns
    )],
);
 
1;

んで、各テーブルクラスで recipient, passphrase, openpgp_columns をセットします。

package MyApp::Schema::User;
 
use strict;
use warnings;
 
__PACKAGE__->recipients('key id');
__PACKAGE__->passphrase('pass phrase');
__PACKAGE__->openpgp_columns(qw/secret/);
 
1;

これで create / update するときは暗号化されて、取り出すときは復号化されるようになりました。

参考にしたモジュール

トラックバック

このエントリーのトラックバックURL:
http://vkgtaro.jp/cgi-bin/mt/mt-tb.cgi/607

コメント

# びるず (2007年05月14日 00:23)

複合化→復号化?

# 海賊たろ [TypeKey Profile Page] (2007年05月14日 22:29)

ツッコミありがとうございます。修正しました。

# AzureStone (2007年05月18日 09:49)

LinuxだとOpenPGPじゃなくてGnuPGだと思うよ。

http://search.cpan.org/~frajulac/GnuPG-0.09/GnuPG.pm

# 海賊たろ [TypeKey Profile Page] (2007年05月19日 00:55)

コメントありがとうございます。
(perl module の方の)GnuPG は、一旦ファイルを書き出さないといけないっぽいので、ちょっと今回の目的には使いづらいかなぁ、と思って外しました。

Crypt::GPG っていうのもあるね。
http://search.cpan.org/~agul/Crypt-GPG-1.63/GPG.pm

# AzureStone [TypeKey Profile Page] (2007年09月10日 14:48)

> Crypt::GPG っていうのもあるね。
> http://search.cpan.org/~agul/Crypt-GPG-1.63/GPG.pm
PurePerlで動くね。
すごいね。これしかも
ちゃんとメンテされているし。

僕が間違っていたよ。
情報ありがとうございます!

# 海賊たろ [TypeKey Profile Page] (2007年09月10日 23:15)

> AzureStone さん
間違ってはいないでしょ。
IRC でも話したけど、GnuPG::Interface ってのもあるね。
http://search.cpan.org/dist/GnuPG-Interface/

# AzureStone [TypeKey Profile Page] (2007年09月11日 09:39)

> 間違ってはいないでしょ。
!!!Σ(゚Д゚;)

> IRC でも話したけど、GnuPG::Interface ってのもあるね。
> http://search.cpan.org/dist/GnuPG-Interface/
あれ?そんな話したっけ?

コメントを投稿