SSLが使えない時などにWebブラウザーとバックエンド間で暗号化したデータをやり取りしたい場合はどうすればいいのでしょうか? 今回はWebブラウザー側としてflash、バックエンド側としてperlを用いることにして、flashで暗号したデータをperlで復号する場合を考えてみます。暗号アルゴリズムはBlowfishでモードはCBCで利用します。
flash用の暗号ライブラリはいくつかあるようですがAs3 Cryptoが良さそうです。データを暗号するAS3コードは以下のようになります。
private function encrypt():void {
var plainStr:String = "生文字列";
var keyStr:String = "e602f3c05b191eb50390c4d234b9feb0";
var key:ByteArray;
var data:ByteArray;
key = Hex.toArray(keyStr);
data = Hex.toArray(Hex.fromString(plainStr));
var pad:IPad = new PKCS5;
var cipher:ICipher = Crypto.getCipher("blowfish-cbc", key, pad);
pad.setBlockSize(cipher.getBlockSize());
cipher.encrypt(data);
var resultStr:String = Hex.fromArray(data);
var ivmode:IVMode = cipher as IVMode;
var ivStr:String = Hex.fromArray(ivmode.IV);
}
plainStrが暗号したい平文でkeyStrが128ビット長の鍵です。resultStrに暗号データ、ivStrにIV(Initialization Vector)が、それぞれ16進表記の文字列としてセットされるのでこれをバックエンドに送信します。
一方、バックエンドのperlでは送信された暗号文字列($encrypted)とIV($iv_str)を受け取ったら以下のように復号します。
use Crypt::CBC;
my $key = pack("H*", 'e602f3c05b191eb50390c4d234b9feb0');
my $iv = pack("H*", $iv_str);
my $encoded = pack("H*", $encrypted);
my $cipher = Crypt::CBC->new( -key => $key,
-keysize => 16,
-literal_key => 1,
-cipher => "Blowfish",
-header => 'none',
-iv => $iv,
);
my $plain = $cipher->decrypt(pack("H*", $encrypted));
鍵は以下のように長さ(上の場合は16バイト==128ビット)を決め適当なものを用意すればよいのですが、perl 側のCrypt::CBCのコンストラクターに渡すkeysizeをその鍵の長さ(バイト数)にしておかないとうまく復号できません。
例えば自分の好きな文字列「this is a pen」を用いてunpack("H*", "this is a pen")(perlの場合)して得られた7468697320697320612070656eだと13バイトなので0を6つ付けて7468697320697320612070656e000000として16バイトの鍵とするなどします。
当然のことながら鍵は大切にしまっておきましょう。
コメントする