Encrypt/decrypt with XOR in PHP - php

I am studying encryption. And I got a problem like this:
After I XOR plaintext with a key, I get a crypt, "010e010c15061b4117030f54060e54040e0642181b17", as hex type. If I want to get plaintext from this crypt, what should I do in PHP?
I tried convert it to string/int and after that take them to XOR with the key (three letters). But it doesn't work.
This is the code:
function xor_this($string) {
// Let's define our key here
$key = 'fpt';
// Our plaintext/ciphertext
$text = $string;
// Our output text
$outText = '';
// Iterate through each character
for($i=0; $i<strlen($text); )
{
for($j=0; $j<strlen($key); $j++,$i++)
{
$outText .= ($text[$i] ^ $key[$j]);
//echo 'i=' . $i . ', ' . 'j=' . $j . ', ' . $outText{$i} . '<br />'; // For debugging
}
}
return $outText;
}
function strToHex($string)
{
$hex = '';
for ($i=0; $i < strlen($string); $i++)
{
$hex .= dechex(ord($string[$i]));
}
return $hex;
}
function hexToStr($hex)
{
$string = '';
for ($i=0; $i < strlen($hex)-1; $i+=2)
{
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
return $string;
}
$a = "This is the test";
$b = xor_this($a);
echo xor_this($b), '-------------';
//
$c = strToHex($b);
$e = xor_this($c);
echo $e, '++++++++';
//
$d = hexToStr($c);
$f = xor_this($d);
echo $f, '=================';
And this is the result:
This is the test-------------
PHP Notice: Uninitialized string offset: 29 in C:\
Users\Administrator\Desktop\test.php on line 210 PHP Stack trace: PHP
1. {main}() C:\Users\Administrator\Desktop\test.php:0 PHP 2. xor_this() C:\Users\Administrator\Desktop\test.php:239
Notice: Uninitialized string offset: 29 in
C:\Users\Administrator\Desktop\test.p hp on line 210
Call Stack:
0.0005 674280 1. {main}() C:\Users\Administrator\Desktop\test.php:0
0.0022 674848 2. xor_this() C:\Users\Administrator\Desktop\test.php:23 9
UBE^A►WEAVA►WEAV#◄WEARAFWECWB++++++++
This is zs$fs☺=================
Why? The "UBE^A►WEAVA►WEAV#◄WEARAFWECWB++++++++" is the result, which I got trouble in my real work.

Try this:
function xor_this($string) {
// Let's define our key here
$key = ('magic_key');
// Our plaintext/ciphertext
$text = $string;
// Our output text
$outText = '';
// Iterate through each character
for($i=0; $i<strlen($text); )
{
for($j=0; ($j<strlen($key) && $i<strlen($text)); $j++,$i++)
{
$outText .= $text{$i} ^ $key{$j};
//echo 'i=' . $i . ', ' . 'j=' . $j . ', ' . $outText{$i} . '<br />'; // For debugging
}
}
return $outText;
}
Basically to revert text back (even numbers are in) you can use the same function:
$textToObfuscate = "Some Text 12345";
$obfuscatedText = xor_this($textToObfuscate);
$restoredText = xor_this($obfuscatedText);

Even easier:
function xor_string($string, $key) {
for($i = 0; $i < strlen($string); $i++)
$string[$i] = ($string[$i] ^ $key[$i % strlen($key)]);
return $string;
}

Based on the code above i created 2 functions to xor encode a JSON string using javascript and then decode it on server side using PHP.
!!! Important: If you will have characters different from ASCII(like Chinese, Cyrillic, Symbols...) in your JSON string, you
must either write some code in PHP or JS to fix how these
characters are encoded/decoded (ord/chr in PHP produce different
results in comparison with JS charCodeAt/String.fromCharCode) or
just base64_encode the JSON string and after that xor encode it.
Personally i use xor_string(base64_encode(JSON.stringify(object)), 'xor_key') in JS and on PHP side:
$json = json_decode(base64_decode(
xor_string(file_get_contents("php://input"), 'xor_key')
),
true);
PHP:
function xor_string($string, $key) {
$str_len = strlen($string);
$key_len = strlen($key);
for($i = 0; $i < $str_len; $i++) {
$string[$i] = $string[$i] ^ $key[$i % $key_len];
}
return $string;
}
Javascript:
function xor_string(string, key) {
string = string.split('');
key = key.split('');
var str_len = string.length;
var key_len = key.length;
var String_fromCharCode = String.fromCharCode;
for(var i = 0; i < str_len; i++) {
string[i] = String_fromCharCode(string[i].charCodeAt(0) ^ key[i % key_len].charCodeAt(0));
}
return string.join('');
}

Related

PHP problem with Bulgarian-MIK character set, cant get one letter

I know that Bulgarian-MIK character set can be converted with the ord function and adding 64, and the bulgarian-MIK characters are from 127 to 191 but i cant get the letter "а"(ord - 127).I tried a lot of ways but it seems that php is processing "а" with a blank symbol and i cant get it.
define("PHP_NL", "<br>");
$string = '-------------- 1 --------------'.PHP_NL;
$string .= '413 …±Ї°Ґ±® €¶® X1.000'.PHP_NL;
$string .= '358 ЊЁ­ ‚®¤  0.5 X1.000'.PHP_NL;
$string .= '--------------------------------'.PHP_NL;
$string .= '1 -Ђ¤°Ё ­  - ЊЂ‘Ђ: 1 - 6'.PHP_NL;
$string .= '17-08-2018 09:05:32'.PHP_NL;
$string .= '--------------------------------';
That is my string with Bulgarian-MIK encoding.I tried to convert it and i every letter is converted fine, but only "а" i cant get.
My function
function ConvertDosToWin($string) {
$chr = null;
for ($i = 1;$i<strlen($string);$i++) {
$chr = mb_convert_encoding($string[$i],'utf-8','windows-1251');
if((ord($chr) >= 127) && (ord($chr)<=(127+64)) ) {
echo 'inside if';
$string[$i] = chr(ord($chr)+64);
}
}
return $string;
}
I fixed the problem using iconv.
function ConvertWinToDos($string) {
$chr = null;
for ($i = 1;$i<strlen($string);$i++) {
$string = iconv(mb_detect_encoding($string,mb_detect_order(),true),'windows-1251',$string);
$chr = $string[$i];
if ((ord($chr) >= 192) && (ord($chr) <= 255)) {
$string[$i] = chr(ord($chr) - 64);
}
}
return $string;
}
I think that this approach may help. I used this in an old project and next is working example. PHP file is Windows-1251 encoded. If your text is in different encoding, you need to convert text using mb_convert_encoding() or iconv(), because ord() returns the binary value of the first byte of text as an unsigned integer between 0 and 255.
Test.php:
<?php
// Functions
function ConvertDosToWin($string) {
$chr = null;
for ($i = 0; $i<strlen($string); $i++) {
if ((ord($chr) >= 128) && (ord($chr) <= 191)) {
$string[$i] = chr(ord($chr) + 64);
}
}
return $string;
}
function ConvertWinToDos($string) {
$chr = null;
for ($i = 0; $i<strlen($string); $i++) {
$chr = $string[$i];
if ((ord($chr) >= 192) && (ord($chr) <= 255)) {
$string[$i] = chr(ord($chr) - 64);
}
}
return $string;
}
// Output
$text = 'АБВГДЕЖЗИЙ';
$text = ConvertWinToDos($text);
file_put_contents('dos.txt', $text);
?>

XOR string in PHP with key

I need to XOR a string/text in PHP the base64 encode it, but something goes wrong:
<?php
$mustget = 'Kw4SCQ==';
$string = 'Josh';
echo("Must get: " . $mustget . "\n");
echo("We got: " . base64_encode(xor_this($string)) . "\n");
function xor_this($text) {
$key = 'frtkj';
$i = 0;
$encrypted = '';
foreach (str_split($text) as $char) {
$encrypted .= chr(ord($char) ^ ord($key{$i++ % strlen($key)}));
}
return $encrypted;
}
?>
I get the following result, but I need to get the "$mustget" one:
Must get: Kw4SCQ==
We got: LB0HAw==
What do I do wrong?
$mustget = 'Kw4SCQ==';
$key = 'frtkj';
$key_length = strlen($key);
$encoded_data = base64_decode($mustget);
$result = '';
$length = strlen($encoded_data);
for ($i = 0; $i < $length; $i++) {
$tmp = $encoded_data[$i];
for ($j = 0; $j < $key_length; $j++) {
$tmp = chr(ord($tmp) ^ ord($key[$j]));
}
$result .= $tmp;
}
echo $result; // Josh
http://ideone.com/NSIe7K
I'm sure you can reverse it and create a function, that "crypts" the data ;-)

Encoding/decoding string in hexadecimal and back

Given a string that may contain any character (including a unicode characters), how can I convert this string into hexadecimal representation, and then reverse and obtain from hexadecimal this string?
Use pack() and unpack():
function hex2str( $hex ) {
return pack('H*', $hex);
}
function str2hex( $str ) {
return array_shift( unpack('H*', $str) );
}
$txt = 'This is test';
$hex = str2hex( $txt );
$str = hex2str( $hex );
echo "{$txt} => {$hex} => {$str}\n";
would produce
This is test => 546869732069732074657374 => This is test
Use a function like this:
<?php
function bin2hex($str) {
$hex = "";
$i = 0;
do {
$hex .= dechex(ord($str{$i}));
$i++;
} while ($i < strlen($str));
return $hex;
}
// Look what happens when ord($str{$i}) is 0...15
// you get a single digit hexadecimal value 0...F
// bin2hex($str) could return something like 4a3,
// decimals(74, 3), whatever the binary value is of those.
function hex2bin($str) {
$bin = "";
$i = 0;
do {
$bin .= chr(hexdec($str{$i}.$str{($i + 1)}));
$i += 2;
} while ($i < strlen($str));
return $bin;
}
// hex2bin("4a3") just broke. Now what?
// Using sprintf() to get it right.
function bin2hex($str) {
$hex = "";
$i = 0;
do {
$hex .= sprintf("%02x", ord($str{$i}));
$i++;
} while ($i < strlen($str));
return $hex;
}
// now using whatever the binary value of decimals(74, 3)
// and this bin2hex() you get a hexadecimal value you can
// then run the hex2bin function on. 4a03 instead of 4a3.
?>
Source: http://php.net/manual/en/function.bin2hex.php

Reverse letters in each word of a string without using native splitting or reversing functions [duplicate]

This question already has answers here:
Reverse the letters in each word of a string
(6 answers)
Closed 1 year ago.
This task has already been asked/answered, but I recently had a job interview that imposed some additional challenges to demonstrate my ability to manipulate strings.
Problem: How to reverse words in a string? You can use strpos(), strlen() and substr(), but not other very useful functions such as explode(), strrev(), etc.
Example:
$string = "I am a boy"
Answer:
I ma a yob
Below is my working coding attempt that took me 2 days [sigh], but there must be a more elegant and concise solution.
Intention:
1. get number of words
2. based on word count, grab each word and store into array
3. loop through array and output each word in reverse order
Code:
$str = "I am a boy";
echo reverse_word($str) . "\n";
function reverse_word($input) {
//first find how many words in the string based on whitespace
$num_ws = 0;
$p = 0;
while(strpos($input, " ", $p) !== false) {
$num_ws ++;
$p = strpos($input, ' ', $p) + 1;
}
echo "num ws is $num_ws\n";
//now start grabbing word and store into array
$p = 0;
for($i=0; $i<$num_ws + 1; $i++) {
$ws_index = strpos($input, " ", $p);
//if no more ws, grab the rest
if($ws_index === false) {
$word = substr($input, $p);
}
else {
$length = $ws_index - $p;
$word = substr($input, $p, $length);
}
$result[] = $word;
$p = $ws_index + 1; //move onto first char of next word
}
print_r($result);
//append reversed words
$str = '';
for($i=0; $i<count($result); $i++) {
$str .= reverse($result[$i]) . " ";
}
return $str;
}
function reverse($str) {
$a = 0;
$b = strlen($str)-1;
while($a < $b) {
swap($str, $a, $b);
$a ++;
$b --;
}
return $str;
}
function swap(&$str, $i1, $i2) {
$tmp = $str[$i1];
$str[$i1] = $str[$i2];
$str[$i2] = $tmp;
}
$string = "I am a boy";
$reversed = "";
$tmp = "";
for($i = 0; $i < strlen($string); $i++) {
if($string[$i] == " ") {
$reversed .= $tmp . " ";
$tmp = "";
continue;
}
$tmp = $string[$i] . $tmp;
}
$reversed .= $tmp;
print $reversed . PHP_EOL;
>> I ma a yob
Whoops! Mis-read the question. Here you go (Note that this will split on all non-letter boundaries, not just space. If you want a character not to be split upon, just add it to $wordChars):
function revWords($string) {
//We need to find word boundries
$wordChars = 'abcdefghijklmnopqrstuvwxyz';
$buffer = '';
$return = '';
$len = strlen($string);
$i = 0;
while ($i < $len) {
$chr = $string[$i];
if (($chr & 0xC0) == 0xC0) {
//UTF8 Characer!
if (($chr & 0xF0) == 0xF0) {
//4 Byte Sequence
$chr .= substr($string, $i + 1, 3);
$i += 3;
} elseif (($chr & 0xE0) == 0xE0) {
//3 Byte Sequence
$chr .= substr($string, $i + 1, 2);
$i += 2;
} else {
//2 Byte Sequence
$i++;
$chr .= $string[$i];
}
}
if (stripos($wordChars, $chr) !== false) {
$buffer = $chr . $buffer;
} else {
$return .= $buffer . $chr;
$buffer = '';
}
$i++;
}
return $return . $buffer;
}
Edit: Now it's a single function, and stores the buffer naively in reversed notation.
Edit2: Now handles UTF8 characters (just add "word" characters to the $wordChars string)...
My answer is to count the string length, split the letters into an array and then, loop it backwards. This is also a good way to check if a word is a palindrome. This can only be used for regular string and numbers.
preg_split can be changed to explode() as well.
/**
* Code snippet to reverse a string (LM)
*/
$words = array('one', 'only', 'apple', 'jobs');
foreach ($words as $d) {
$strlen = strlen($d);
$splits = preg_split('//', $d, -1, PREG_SPLIT_NO_EMPTY);
for ($i = $strlen; $i >= 0; $i=$i-1) {
#$reverse .= $splits[$i];
}
echo "Regular: {$d}".PHP_EOL;
echo "Reverse: {$reverse}".PHP_EOL;
echo "-----".PHP_EOL;
unset($reverse);
}
Without using any function.
$string = 'I am a boy';
$newString = '';
$temp = '';
$i = 0;
while(#$string[$i] != '')
{
if($string[$i] == ' ') {
$newString .= $temp . ' ';
$temp = '';
}
else {
$temp = $string[$i] . $temp;
}
$i++;
}
$newString .= $temp . ' ';
echo $newString;
Output: I ma a yob

How to remove characters from a string?

(my first post was not clear and confusing so I've edited the question)
I was studying string manipulation.
You can use strlen() or substr() but cannot rely on other functions that are predefined in libraries.
Given string $string = "This is a pen", remove "is" so that
return value is "Th a pen" (including 3 whitespaces).
Remove 'is' means if a string is "Tsih", we don't remove it. Only "is" is removed.
I've tried (shown below) but returned value is not correct. I've run test test and
I'm still capturing the delimiter.
Thanks in advance!
function remove_delimiter_from_string(&$string, $del) {
for($i=0; $i<strlen($string); $i++) {
for($j=0; $j<strlen($del); $j++) {
if($string[$i] == $del[$j]) {
$string[$i] = $string[$i+$j]; //this grabs delimiter :(
}
}
}
echo $string . "\n";
}
Clarifying, the original quiestion is not Implement a str_replace, It's remove 'is' from 'this is a pen' without any functions and no extra white spaces between words. The easiest way would be $string[2] = $string[3] = $string[5] = $string[6] = '' but that would leave an extra white space between Th and a (Th[ ][ ]a).
There you go, no functions at all
$string = 'This is a pen';
$word = 'is';
$i = $z = 0;
while($string[$i] != null) $i++;
while($word[$z] != null) $z++;
for($x = 0; $x < $i; $x++)
for($y = 0; $y < $z; $y++)
if($string[$x] === $word[$y])
$string[$x] = '';
If you were allowed to use substr() it'd be so much easier. Then you could just loop it and check for the matched value, why can't you use substr() but you can strlen() ?
But without, this works at least:
echo remove_delimiter_from_string("This is a pen","is");
function remove_delimiter_from_string($input, $del) {
$result = "";
for($i=0; $i<strlen($input); $i++) {
$temp = "";
if($i < (strlen($input)-strlen($del))) {
for($j=0; $j<strlen($del); $j++) {
$temp .= $input[$i+$j];
}
}
if($temp == $del) {
$i += strlen($del) - 1;
} else {
$result .= $input[$i];
}
}
return $result;
}
The following code can also used to replace the sub string:
$restring = replace_delimiter_from_string("This is a pen","is", "");
var_dump($restring);
$restring = replace_delimiter_from_string($restring," ", " ");
var_dump($restring);
function replace_delimiter_from_string($input, $old, $new) {
$input_len = strlen($input);
$old_len = strlen($old);
$check_len = $input_len-$old_len;
$result = "";
for($i=0; $i<=$check_len;) {
$sub_str = substr($input, $i, $old_len);
if($sub_str === $old) {
$i += $old_len;
$result .= $new;
}
else {
$result .= $input[$i];
if($i==$check_len) {
$result = $result . substr($input, $i+1);
}
$i++;
}
}
return $result;
}

Categories