sub createRoundKeys { my $key = $_[0]; if(length $key != 8) { die "#ERROR: DES key is not 64 bit#\n";} my ($i, $j); # to hold references to sub-keys for each round according to array index. # the function returns a reference of this array to be farther used. my @subKeys = (); # unpack returns the key string as a corresponding bit string # 64 bit where B indicates highest first my @tempArr = unpack("B64", $key); # split bit string to corresponding bits array my @keyBitsArr = map { $_+0 } split("", $tempArr[0]); #------------------------------------------------------------ # permuted choice one(@PC_1) # each index in the keyBitsArr56_PC1 gets some bit from the 64-bit original key according to some mapping, PC-1 my @keyBitsArr56_PC1 = map { $keyBitsArr[$PC_1[$_]-1] } 0 .. $#PC_1; my @leftBitsArr = @keyBitsArr56_PC1[0..27]; my @rightBitsArr = @keyBitsArr56_PC1[28..55]; # create sub-keys for each round @tempArr = (); for($i=0; $i<16; $i++) { # shift each part individually for (0 .. $ScheduleOfLeftShifts[$i]-1) { # shift left part according to round push(@leftBitsArr, shift(@leftBitsArr)); # shift right part according to round push(@rightBitsArr, shift(@rightBitsArr)); } # PC_2, get 48 bit round sub key @tempArr = (@leftBitsArr, @rightBitsArr); # permuted choice two @{$subKeys[$i]} = map { $tempArr[$PC_2[$_]-1] } 0 .. $#PC_2; } return \@subKeys; } sub des { my ($i, $j, $k, $tempVar, @tempArr); # iterate over input file in chunks of 64 bit, DES ECB-mode of operation for($i=0; $i<=$#FileArray; $i++) { # convert block read from file to its binary rep $tempVar = unpack("B64", $FileArray[$i]); #---------------------------------------- # DEBUG/PoC my $hex = join("", map { sprintf "%02X", $_ } unpack("C*",$FileArray[$i])); print("($i): $hex <$FileArray[$i]>\n"); #---------------------------------------- # an array of bits as numeric values, the block rep as numeric binary numbers my @bitsArray = map { $_+0 } split("", $tempVar); # initial permutation (IP) for each block/64 bit chunk before the 16 rounds my @bitsArray_ip = map { $bitsArray[$IP[$_]-1] } 0 .. $#IP; my @leftBitsArr = @bitsArray_ip[0 .. 31]; my @rightBitsArr = @bitsArray_ip[32 .. 63]; # 16 DES rounds per 64 bit chunk treated as two 32 bit chunks for($j=0; $j<16; $j++) { my @nextLeftBitsArr = @rightBitsArr; # curr right bits chunk expansion/permutation (E) @rightBitsArr = map { $rightBitsArr[$E[$_]-1] } 0 .. $#E; # XOR with round sub-key: check function bool param for encryption/decryption action my $ref; if($action eq "e") { $ref = $SubKeys[$j];# j - index of curr round } elsif($action eq "d") { $ref = $SubKeys[15-$j];# j - index of curr round reversed } @rightBitsArr = map { $rightBitsArr[$_] ^ $ref->[$_] } 0 .. $#rightBitsArr; # S-box my $sBoxResult = 0; for($k=0; $k<8; $k++) { my $sBoxRow = $rightBitsArr[$k*6]*2 + $rightBitsArr[$k*6+5]; my $sBoxCol = $rightBitsArr[$k*6+1]*8 + $rightBitsArr[$k*6+2]*4 + $rightBitsArr[$k*6+3]*2 + $rightBitsArr[$k*6+4]; $sBoxResult = ($sBoxResult<<4) + $SBOXES[$k][$sBoxRow][$sBoxCol]; } my $sBoxResStr = unpack("B32", pack("N", $sBoxResult)); @rightBitsArr = map { $_+0 } split("", $sBoxResStr);# now 32 bits, $sBoxResStr was loop concat. # Permute the bits, then xor the resulting bit with leftBitsArr @rightBitsArr = map { $rightBitsArr[$P[$_]-1] ^ $leftBitsArr[$_] } 0 .. $#P; # assign next values @leftBitsArr = @nextLeftBitsArr; } # swap two sides { my @temp = @leftBitsArr; @leftBitsArr = @rightBitsArr; @rightBitsArr = @temp; } # merge the left and right halves, invert the permutation, then convert back to binary # and store the result @bitsArray = (@leftBitsArr, @rightBitsArr); my @bitsArray_ip_inverse = map { $bitsArray[$IP_INVERSE[$_]-1] } 0 .. $#IP_INVERSE; $FileArray[$i] = pack("B64", join("", @bitsArray_ip_inverse)); #$tempVar); } }