A simple perl function needed

I have a very simple function that takes a string and scrambles itwith a password and a given password length:

void scramble(char*trg,char*src,int len,char*pwd,int pwdlen)
   {
   for (int x = 0 ; x < len ; x ++)
      {
      trg[x] = src[x] + pwd[x % pwdlen];
      }
   }

I tried to do that in perl, without success.

my @trg;
my @rkey = "The Key";
my $ll = length(@rkey);
my @unt = $source_buffer;

for($x = 0 ; $x < $ll ; $x++) {
  $cot[$x] = $unt[$x] + $rkey[$x % $ll];
 }
and then im trying to write @trg to a file, and only 2 bytes are written, where the length of _source_buffer (1000 bytes) should have been written.

Please help.
LVL 6
WxWAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

fantasy1001Commented:
try to change this:
my @rkey = split / /, "The key";
my @unt = split / /, $source_buffer;
my $len = @unt;   # should return the length
$trg[$_] = map { $unt[$_] + $rkey[$_ % $len] } 1..@unt;

OR
my @rkey = split / /, "The key";
my @unt = split / /, $source_buffer;
foreach (1..$#unt){
   $trg[$_] = $unt[$_] + $rkey[$_ % $#unt];
}

NOTE: I am not sure whether $_ % $#unt will return the remaining or not.

Try first. Thanks & cheers.
ultimatemikeCommented:
Change the lines to:


my @rkey = split //, "The Key";

and

my @unt = split //, $source_buffer;



What this will do is split the strings and store each character as an element of an array. Perhaps not the most efficient way of doing it, but it should make operating on the individual characters easy.  Then when you want to print out the result,

print join('', @trg);



Also I noticed that in your method you set $cot[$x].  Should that be $trg[$x]?

WxWAuthor Commented:
I have now this one.
# -----------------------------
my @trg;
my @rkey = split //,$uidkey;
my @unt = split //,$untouch;
my $ll = length($untouch);

for($x = 0 ; $x < $ll ; $x++) {
  $trg[$x] = $unt[$x] + $rkey[$x % $ll];
  }

my $result = join('',@trg);

# -------------------------------
This fails. It stores in the @trg array a string that is mostly filled in with zeros. I think that the
  $trg[$x] = $unt[$x] + $rkey[$x % $ll];

line , fails to add 8-bit chars correctly . i.e. if the original char is 255 and the add value is 10 , the dest char should be 9 (265 - 256).

It also fails when I use / /, instead of //.
OWASP: Avoiding Hacker Tricks

Learn to build secure applications from the mindset of the hacker and avoid being exploited.

ultimatemikeCommented:
 $trg[$x] = $unt[$x] + $rkey[$x % $ll];



Correct me if I'm wrong - but this can place values > 255 in @trg.  Try changing it to:


$trg[$x] = ($unt[$x] + $rkey[$x % $ll] ) % 256;
BioICommented:
if you want to split a string in different charachters, you can *not* do this by:
my @rkey = split //,$uidkey;
my @unt = split //,$untouch;

the way I usually do it, is splitting the string by adding different charachters between the different charachters, end then split them bases on this charachter e.g. "-"

#### script ###
my @trg;
$rkey =~ s/(?<=.)(?=.)/$1-/g; # inserting "-"
print "rkey -> $rkey\n";
@rkey = split /-/, $rkey;  # split into different charachters based on "-"
foreach $number (@rkey) {
    print "$number\n";
}
my $ll = @rkey;
print "length -> ", $ll, "\n";

$source_buffer =~ s/(?<=.)(?=.)/$1-/g; # inserting "-"
print "source_buffer -> $source_buffer\n";
@unt = split /-/, $source_buffer;  # split into different charachters based on "-"
foreach $number (@unt) {
    print "$number\n";
}

for($x = 0 ; $x < $ll ; $x++) {
    $trg[$x] = $unt[$x] + $rkey[$x % $ll];
}

my $result = join('', @trg);
WxWAuthor Commented:
I have this one now.
# -------------------------
my $tlen = 925; # length of source_buffer
my $rkey = $uidkey;
$rkey =~ s/(?<=.)(?=.)/$1-/g; # inserting "-"
@rkey = split /-/, $rkey;  # split into different charachters based on "-"
my $ll = @rkey;

$source_buffer =~ s/(?<=.)(?=.)/$1-/g; # inserting "-"
# print "source_buffer -> $source_buffer\n";
@unt = split /-/, $source_buffer;  # split into different charachters based on "-"

print "\r\n\r\n";

for($x = 0 ; $x < $tlen ; $x++) {
    $c = @rkey[$x % $ll];
    $o = @unt[$x];
    $v = $c + $o; <<< THIS LINE FAILS
   
    print "$v";

------------
$unt has the original data, with len $tlen.
@rkey has the key OK .
$v = ($c + $o) % 256;
This line generates always a number in $v, and not a byte.
How can I add two bytes and convert them to a byte?

jmcgOwnerCommented:
$v = chr( (ord($c) + ord($o)) %256);

This manipulation is starting to look expensive.
ozoCommented:
my @trg;
my @rkey = unpack"C*","The Key";
my $ll = @rkey;
my @unt = unpack"C*",$source_buffer;

for $x( 0 .. $#unt ) {
  $trg[$x] = $unt[$x] + $rkey[$x % $ll];
 }
return pack"C*",@trg;

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
WxWAuthor Commented:
Jmcg: That nearly worked, except that ord($o) returns 0 if $o = space (0x20). I haven't yet tested what ord returns if $o == 0.
How to fix that ?

ozo: It doesn't work at all, it returns names instead of characters.
jmcgOwnerCommented:
That's strange. If I do:

$o = " ";
print ord($o), "\n";

my version of Perl prints

32

=========

As usual, Ozo is on exactly the right track. He does not even need to do modulo 256 if both input strings contain only characters less than 128. I wonder why his solution did not work for you. (Your original C routined did not need to do module 256 because the variables were declared 'char'.)

=========

BioI's claim about not using split with a null pattern to divide a string into an array of characters contradicts my experience. I believe 'unpack' with 'C*' is better, but splitting with a null string ought to work: it's even appears as an example in the Camel book;


WxWAuthor Commented:
Edit: Yes, ord() works. But the buffer is binary, it can contain any value from 0 to 255. Therefore, if there is a '-' inside the buffer, it kills it (using the split pattern with '-') , and that is where ord() returns 0, because the buffer has a 0 as well , instead of the original '-'


Ozo's method sends me results with numbers, e.g. the @trg[0] has the number "193" instead of the char with ascii value 193. Any option on how to fix that ?




WxWAuthor Commented:
Also, the C++ routine works the same way with both unsigned and signed variables.
jmcgOwnerCommented:
Well, that's just another argument against using BioI's method.

To turn the @trg array back into an ordinary scalar string, you need to do the operation Ozo indicated:

  $result = pack 'C*', @trg;

If you want to keep it as a split up array, but of one-character strings, I guess you'd need to do something like:

  @trg = map { chr } @trg;
WxWAuthor Commented:
LoL,  I needed to save back the array

 $result = pack "C*",@trg;

it only had  pack "C*",@trg;

Splitting the points, all helped.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Perl

From novice to tech pro — start learning today.