end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

perl による文字列の可逆暗号化

なんとなく、以下のような感じでしょうか

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my $SEED_BASE =
    '(3hvKT1w0!W5xA}_/9^eDpR{Gt4S[coPNMnkHiL'
    'jUmY27r).Xz]lZFyECs=qgBaOVbId8~-J6Qfu';
my $PCP_TABLE = {};
my $FIXED_NUM = 383;

main();

sub main {
    my $encoded = pcp_encode('end0tknr','crt');
    print "$encoded\n";
    my $decoded = pcp_decode($encoded,'crt');
    print "$decoded\n";
}

sub pcp_encode {
    my($comment,$key_str) = @_;
    
    $comment .="\0" if length($comment) % 2;
    my @key = split(//,$key_str);
    my $j = pcp_make_table(@key);
    my $i = 0;
    $comment =~
        s/./sprintf("%03o",ord($&)^(ord($key[$i++ % @key])+($j++ % $FIXED_NUM)))/ges;
    $comment=~ s/../$PCP_TABLE->{$&}/g;
    
    return $comment;
}

sub pcp_decode {
    my($comment,$key_str) = @_;

    $comment = $_[0];
    my @key = split(//,$key_str);
    my $j = pcp_make_table(@key);
    $comment=~ s/./$PCP_TABLE->{$&}/g;
    my $i = 0;
    $comment =~
        s/.../sprintf("%c",oct($&)^(ord($key[$i++ % @key]) +($j++ % $FIXED_NUM)))/ges;
    $comment=~s/\0$//;
    return $comment;
}

sub pcp_make_table{
    my(@key) = @_;
    
    my @list;
    my @seed = split(//,$SEED_BASE);
    my $k = scalar(@key);
    my $init_j=0;
    for(my $i=0;$i<64;$i++){
        my $j=ord($key[$i % $k]);
        $init_j +=$j;
        $list[$i]=splice(@seed,(($j+$k) % (64-$i)),1);
    }
    $k=0;
    for(my $i=0;$i<8;$i++){
        for(my $j=0;$j<8;$j++,$k++){
            $PCP_TABLE->{"$i$j"}=$list[$k];
            $PCP_TABLE->{$list[$k]}="$i$j";
        }
    }
    return ($init_j % $FIXED_NUM);
}