前に、お手軽にシリアルナンバが作りたいけどでスクリプト書いたのはいいけど、あまりに手抜き過ぎてシリアルになってなかった。
簡単に暗号化してチェックサムを付加してちょっとシリアル番号風にしてみた。
use strict;
use warnings;
my $dicstr1 = join('', '*', 'A'..'Z', 'a'..'z', 0..9);
my $dicstr2 = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
# a1X12345
my $text = 'a1X';
my $num = 12345;
print $text, '-', $num, "\n";
my $len = 4;
my $salt = int(rand(length($dicstr2) ** $len));
my $salt_s = int2str($salt, $len, $dicstr2);
my $dicstr3= strshuffle($dicstr2, $salt);
my $text_i = str2int($text, $dicstr1);
my $text_i_s = int2str($text_i, $len, $dicstr3);
my $num_s = int2str($num, $len, $dicstr3);
my $checksum = fletcher($salt_s . $text_i_s . $num_s);
my $checksum_s = int2str($checksum, $len, $dicstr2);
print $salt_s, '-', $text_i_s, '-', $num_s, '-', $checksum_s, "\n";
my $salt_s_i = str2int($salt_s, $dicstr2);
my $dicstr4 = strshuffle($dicstr2, $salt_s_i);
my $text_i_s_i = str2int($text_i_s, $dicstr4);
my $text_i_s_i_s = int2str($text_i_s_i, $len, $dicstr1);
my $num_s_i = str2int($num_s, $dicstr4);
print $text_i_s_i_s, '-', $num_s_i, "\n";
exit;
sub fletcher
{
my $data = shift;
my $sum1 = 0;
my $sum2 = 0;
my $len = length($data);
for(my $i = 0; $i < $len; $i++) {
$sum1 += ord(substr($data, $i, 1));
$sum2 += $sum1;
}
$sum1 = ($sum1 & 0x3ff) + ($sum1 >> 10);
$sum2 = ($sum2 & 0x3ff) + ($sum2 >> 10);
return $sum2 << 10 | $sum1;
}
our $myrand_next;
sub myrand
{
my $x = shift || 1;
$myrand_next = ($myrand_next * 1664525 + 1013904223) % 4294967296;
return ((int($myrand_next / 65536) % 32768) / 32767) * $x;
}
sub mysrand
{
$myrand_next = shift || 1;
myrand();
}
sub strshuffle
{
my $str = shift;
my $seed = shift || 1;
mysrand($seed);
my @arr_str = split('', $str);
fisher_yates_shuffle(\@arr_str);
return join('', @arr_str);
}
# fisher_yates_shuffle( \@array ) : generate a random permutation
# of @array in place
sub fisher_yates_shuffle {
my $array = shift;
my $i;
for ($i = @$array; --$i; ) {
my $j = int myrand($i+1);
next if $i == $j;
@$array[$i,$j] = @$array[$j,$i];
}
}
sub str2int
{
my $instr = shift || 'A';
my $dicstr = shift || join('', '*', 'A'..'Z', 'a'..'z', 0..9);
my $reint = 0;
for(my $i = 0; $i < length($instr); $i++)
{
$reint += index($dicstr, substr($instr, length($instr) - $i - 1, 1))
* (length($dicstr) ** $i);
}
return $reint;
}
sub int2str
{
my $instr = shift || 0;
my $length = shift || 8;
my $dicstr = shift || '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
my $restr ='';
do
{
$restr = substr($dicstr, $instr % length($dicstr), 1) . $restr;
$instr = int($instr / length($dicstr));
}
while($instr);
return substr(substr($dicstr, 0, 1) x $length . $restr, length($restr));
}
こんなの。
コメントする