Reputation: 406
Can someone explain what is PHP doing here and if it is possible to get predictable result?
Could this be used for hiding messages?
echo '1' | 'z';
Upvotes: 0
Views: 232
Reputation: 197554
If you do a bitwise operation between two strings, each character within a string represents an octet of 8 bits. The bitwise operation is then done character per character. That is converting a character into an integer first like with the ord
function and then turning the result as a string (comparable to chr
).
echo '1' | 'z';
Is the same as
echo chr(ord('1') | ord('z'));
Taken from the PHP manual:
<?php
echo 12 ^ 9; // Outputs '5'
echo "12" ^ "9"; // Outputs the Backspace character (ascii 8)
// ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8
echo "hallo" ^ "hello"; // Outputs the ascii values #0 #4 #0 #0 #0
// 'a' ^ 'e' = #4
echo 2 ^ "3"; // Outputs 1
// 2 ^ ((int)"3") == 1
echo "2" ^ 3; // Outputs 1
// ((int)"2") ^ 3 == 1
?>
The same conversion logic applies to the OR |
operator:
<?php
echo 12 | 9; // Outputs '13'
echo "12" | "9"; // Outputs the 9 character (ascii 57)
// ('1' (ascii 49)) | ('9' (ascii 57)) = #57
echo "hallo" | "hello"; // Outputs the ascii values #104 #101 #108 #108 #111
// 'a' | 'e' = #101
echo 2 | "3"; // Outputs 3
// 2 | ((int)"3") == 3
echo "2" | 3; // Outputs 3
// ((int)"2") | 3 == 3
?>
If you do a bitwise operation between a string and an integer, strings are converted to integer first.
Upvotes: 2
Reputation: 212402
It's using a bitwise OR operator
'1' = ASCII 0x31 = Binary 00110001
'z' = ASCII 0x7A = Binary 01111010
ORing the two gives
00110001 1
| 01111010 z
= 01111011 {
which is 0x7B which is ASCII character {
And as has been pointed out, to make this reversible, XOR should be used rather than OR
XORing the two gives
00110001 1
^ 01111010 z
= 01001011 K
which is 0x4B which is ASCII character K
Reversing:
01001011 K
^ 01111010 z
= 00110001 1
EDIT
It's not a particularly strong code, but:
$plainTextMessage = "My secret message";
$secretCharacter = 'z';
$codedMessage = '';
for($i = 0; $i < strlen($plainTextMessage); $i++) {
$codedMessage .= $plainTextMessage[$i] ^ $secretCharacter;
}
echo 'Coded Message is: '.$codedMessage.PHP_EOL;
$decodedMessage = '';
for($i = 0; $i < strlen($codedMessage); $i++) {
$decodedMessage .= $codedMessage[$i] ^ $secretCharacter;
}
echo 'Decoded Message is: '.$decodedMessage.PHP_EOL;
Upvotes: 2
Reputation: 137290
This is bit-wise "or" operator. It returns a result made of bits that were set to 1
in at least one of the elements ('1'
or 'z'
).
All of the following give the same results:
$r1 = '1' | 'z';
$r2 = chr(49) | chr(122); // chr(49) is '1', chr(122) is 'z'
$r3 = chr(49 | 122); // result is chr(123), which is '{'
and all of them are equal to '{'
. See proof here: http://ideone.com/YC048
Upvotes: 0
Reputation: 72975
|
is a bitwise operator - instead of operating on a string, or object, it operates on the bits (i.e. the 0s and 1s). In this case, |
is OR. That is, bits that are in the first or second argument are set.
When you represent both as bits, take the bits that are in common, then echo it as a string, it happens to be '{' in this case.
Yes, you could use this to encode things - a similar but better way to do this is using XOR instead of OR. Have a look at http://en.wikipedia.org/wiki/XOR_cipher.
Upvotes: 1