M.C.P.C.

―むり・くり―プラスコミュニケーション(更新終了)


| トップページ |

2010年5月22日 17:33

Perlで0~536870911までの数字を62進数文字列最大5文字に変換したり逆変換したり

このエントリーをはてなブックマークに追加 mixiチェック

0からの連番(シリアル値)を62進数文字列(最大5文字)として暗号化しておいて、使う時に復号してシリアル値に戻すっていうの。普通にやると、文字が順番に代わっていくだけなのでなんだかいたたまれない気持ちになるので、数値を2進数に見立てて、左右ビット反転することで、それっぽくなる。

Filename: crypt62.pl

use strict;
use warnings;
use Math::BaseCalc;
my $calc = Math::BaseCalc->new(digits => 'bin' ); # 2進数
for (my $i = 0; $i < 16; $i++ ){
  my $b = $calc->to_base( $i );
  my $h = $calc->to_base( _bit_hanten($i) );
  my $c = crypt62  ( $i );
  my $d = decrypt62( $c );
  printf "%2d %4s %32s %5s %2d\n" ,$i, $b, $h, $c, $d;
}
exit;
 
sub crypt62 {
  my $n = shift;
  my $calc = Math::BaseCalc->new( digits => 62 ); # 62進数
  #$n ^= 12345678; # XORする場合
  $n = _bit_hanten( $n ) >> 3; # ビット左右反転ご3ビット右シフト
  my $s = $calc->to_base( $n ); # 数値を62進数文字列へ
  return $s;
  #return substr "0000$s", -5; # ゼロパディングする場合
}
sub decrypt62 {
  my $s = shift;
  my $calc = new Math::BaseCalc( digits => 62 ); # 62進数
  my $n = $calc->from_base( $s ); # 62進数文字列を数値へ
  $n = _bit_hanten( $n << 3 ); # 3ビット左シフト後ビット左右反転
  #$n ^= 12345678; # XORする場合
  return $n;
}
sub _bit_hanten { # 32ビット左右反転
  my $n = shift;
  $n = ( $n << 16) | ( $n >> 16 );
  $n = ( ($n & 0x00ff00ff) << 8 ) | ( ($n & 0xff00ff00) >> 8 );
  $n = ( ($n & 0x0f0f0f0f) << 4 ) | ( ($n & 0xf0f0f0f0) >> 4 );
  $n = ( ($n & 0x33333333) << 2 ) | ( ($n & 0xcccccccc) >> 2 );
  $n = ( ($n & 0x55555555) << 1 ) | ( ($n & 0xaaaaaaaa) >> 1 );
  return $n;
}
 
__END__
$ perl crypt62.pl
 0    0                                0     0  0
 1    1 10000000000000000000000000000000 iakk8  1
 2   10  1000000000000000000000000000000 95aa4  2
 3   11 11000000000000000000000000000000 rfuuc  3
 4  100   100000000000000000000000000000 4xA52  4
 5  101 10100000000000000000000000000000 mHUpa  5
 6  110  1100000000000000000000000000000 dCKf6  6
 7  111 11100000000000000000000000000000 vN4ze  7
 8 1000    10000000000000000000000000000 2gN2w  8
 9 1001 10010000000000000000000000000000 kr7mE  9
10 1010  1010000000000000000000000000000 blXcA 10
11 1011 11010000000000000000000000000000 twhwI 11
12 1100   110000000000000000000000000000 6On7y 12
13 1101 10110000000000000000000000000000 oYHrG 13
14 1110  1110000000000000000000000000000 fTxhC 14
15 1111 11110000000000000000000000000000 y3RBK 15
$ 

変換後の文字列を5文字に抑えるためには、3ビット削らなくてはならなかった。ということで、表現できる数値は、0~536870911(2^29-1)までとなります。

最初のゼロが0という文字列になるのが嫌な人は、0埋めするか(0→00000、1→00001にすること。ゼロパディングって言います)、0から使わないか(どうせDBから出てくるIDなんて1が起点だろ)、暗号化と復号のルーチンの要所に ^ (XOR)を仕込んどくといいよ。あと、これ暗号にはなりません。idを1増やして簡単に情報をたどられるのが嫌だ、程度の難読化ですよね。

一番怖いのはPerlのモジュールでこういうのを専門でやるモジュールが用意されていたりしそうだってことだ。

投稿 大野 義貴 [Perl] | |

トラックバック(0)

トラックバックURL: http://blog.dtpwiki.jp/MTOS/mt-tb.cgi/3229

コメントする