#!/usr/bin/perl -w package Gost; sub new { my $argument = shift; my $class = ref ($argument) || $argument; my $self = {}; $self->{KEY} = []; $self->{SBOX} = []; bless $self, $class; return $self; } sub generate_sbox { my $self = shift; my $passphrase = shift; if (ref ($passphrase)) { @{$self->{SBOX}} = @$passphrase; } else { my ($i, $x, $y, $random, @tmp) = 0; my @temp = (0..15); for ($i=0; $i <= (length $passphrase); $i+=4) { $random = $random ^ (unpack L, pack a4, substr ($passphrase, $i, $i+4)) }; srand $random; for ($i=0; $i < 8; $i++) { @tmp = @temp; grep { $x = _rand (15); $y = $tmp[$x]; $tmp[$x] = $tmp[$_]; $tmp[$_] = $y; } (0..15); grep {@{$self->{SBOX}}->[$i][$_] = $tmp[$_] } (0..15); } } } sub generate_keys { my ($self, $passphrase) = @_; if (ref ($passphrase)) { @{$self->{KEY}} = @$passphrase; } else { my ($i, $random) = 0; for ($i=0; $i <= (length $passphrase); $i+=4) { $random = $random ^ (unpack L, pack a4, substr ($passphrase, $i, $i+4))}; srand $random; grep { @{$self->{KEY}}[$_] = _rand (2**32) } (0..7); } } sub crypt { my ($self, $data, $decrypt) = @_; my ($i, $j, $d1, $d2) = 0; my $return = ''; for ($i=0; $i < length $data; $i += 8) { $d1 = unpack L, pack a4, substr ($data, $i, $i + 4); $d2 = unpack L, pack a4, substr ($data, $i + 4, $i + 8); $j = 0; grep { $j = ($_ % 8) - 1; $j = 7 if $j == -1; $decrypt ? ($_ >= 9) && ($j = (32 - $_) % 8) : ($_ >= 25) && ($j = 32 - $_); ($_ % 2) == 1 ? ($d2 ^= $self->_substitute ($d1 + @{$self->{KEY}}[$j])) : ($d1 ^= $self->_substitute ($d2 + @{$self->{KEY}}[$j])) ; } (1..32); $return = $return . (pack L, $d2) . (pack L, $d1); } return $return; } sub _substitute { my ($self, $d) = @_; my $return = 0; grep { $return = $return | @{$self->{SBOX}}->[$_][$d >> ($_ * 4) & 15] << ($_ * 4) } reverse (0..7); return $return << 11 | $return >> 21; } sub _rand { return int (((shift) / 100) * ((rand) * 100)); } 1;