This is not about security. It is also not to make it hard to break. I'm looking for a simple algorithm to change a string (a url) in a way it does not resemble the original. The encryption will be done with javascript. Then I want to feed the encrypted string to a PHP function to change it back to the original. Both ends could share a secret key, or the conversions could be key-less and rely on just logic.
The ideal solution
will be simple
will use available javascript functions for encryption
will use available php functions for decryption
will produce encrypted string in way not to resemble the plain text at all
will only use lower-case alphabet characters and numbers in the encrypted string
is not a method widely used like Base64-ing as encryption.
Edit: The last requirement was added after shamittomar's answer.
You can use bitwise XOR in javascript to encode the string and again in PHP to decode it again. I wrote a little Javascript example for you. It works the same in PHP. If you call enc() a second time with the already encoded string, you'll get the original string again.
<html>
<head><title></title></head>
<body>
<script type="text/javascript">
function enc(str) {
var encoded = "";
for (i=0; i<str.length;i++) {
var a = str.charCodeAt(i);
var b = a ^ 123; // bitwise XOR with any number, e.g. 123
encoded = encoded+String.fromCharCode(b);
}
return encoded;
}
var str = "hello world";
var encoded = enc(str);
alert(encoded); // shows encoded string
alert(enc(encoded)); // shows the original string again
</script>
</body>
</html>
In PHP do something like this (caution, this is not tested and it's been a long while since I did PHP):
$encoded = "..."; // <-- encoded string from the request
$decoded = "";
for( $i = 0; $i < strlen($encoded); $i++ ) {
$b = ord($encoded[$i]);
$a = $b ^ 123; // <-- must be same number used to encode the character
$decoded .= chr($a)
}
echo $decoded;
If that's what you want, you can Base64 encode and decode that.
[EDIT]: After OP clarification:
As you do not want widely used methods, here is one rarely used method and that can do it for you by giving output only in LOWERCASE letters and NUMBERS. It is Base32 Encode/Decode. Use the following libraries:
Javascript Base32 Encoder: http://www.tumuski.com/2010/04/nibbler/
PHP Base32 Decoder: https://www.phpclasses.org/package/3484-PHP-Encode-and-decode-data-with-MIME-base-32-encoding.html
If it's not about security, and not about making it hard to break, then how about ROT-13?
//+ Jonas Raoni Soares Silva
//# http://jsfromhell.com/string/rot13 [rev. #1]
String.prototype.rot13 = function(){
return this.replace(/[a-zA-Z]/g, function(c){
return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
});
};
...
var s = "My String";
var enc = s.rot13(); // encrypted value in enc
PHP has a native function, str_rot13: http://php.net/manual/en/function.str-rot13.php
$decrypted = str_rot13($_GET['whatever']);
Well I found this page and found Redcully's program not work for me so I thought It happens with all others. finally I got reason and fixed it. Here new code is...
Thanks to Redcully :)
JS function:
function encode(str) {
var encoded = "";
for (i=0; i<str.length;i++) {
var a = str.charCodeAt(i);
var b = a ^ 51; // bitwise XOR with any number, e.g. 123
encoded = encoded+String.fromCharCode(b);
}
return encoded;
}
PHP function:
function decode($encoded) {
$decoded = "";
for( $i = 0; $i < strlen($encoded); $i++ ) {
$b = ord($encoded[$i]);
$a = $b ^ 51; // <-- must be same number used to encode the character
$decoded .= chr($a);
}
return $decoded;
}
How are you planning to implement (hide) the secret in Javascript? IMHO it's not possible.
Edit: OK - not about security.. then just use any baseXX or rot encoding mechanism. But you can't really say one of these algorythms would not be well known...
Related
I'm trying to decrypt a string in PHP, I can do it in JS, but I can't do it via PHP.
New in cryptography, I try to recover my original string, but it can't find a solution.
So I have this code below in JS :
const p1 = ['abc', 1, 'def', 'hij'].join('a');
let p2 = crypto.createHash('md5').update(p1, 'ascii').digest('hex') + 'a' + p1 + 'a';
while (p2.length % 16 > 0) p2 += ' ';
let result = crypto.createCipheriv('aes-128-ecb', 'aeda94ad8azd', '').update(p2, 'ascii', 'hex');
this code in PHP :
$p1 = implode('a', ['abc', 1, 'def', 'hij']);
$p2 = hash('md5', $p1, false) . 'a' . $p1 . 'a';
dd($p2);
while (strlen($p2) % 16 > 0) $p2 .= ' ';
$result = openssl_encrypt($p2, 'aes-128-ecb', 'aeda94ad8azd', 0);
JS Result :
let p2 result = 7fbe3256bd8e9ac3e9b2e2ac9c1c812aaabca1adefahija
p2 result after while = same as P2 with one space at the end
let result = a7222dbd06b1ae0ea421ac968eba780f0e0e23317c25bab0ecf423b6ff95f1e25ede0432af1a8b17c56e682193c55516
PHP Result :
$p2 result = 7fbe3256bd8e9ac3e9b2e2ac9c1c812aaabca1adefahija
$p2 result after while = same as p2 with one space at the end
$result = wE5FpEuPuWdL8D06y/jiqRB7kehRcLcBmI16AncqsKWeeqWm8Tj08anFBrnD0JWCP5/ihLo0AUZr0/+MBDjQvw==
I do something wrong in openssl_decrypt ? I don't use the right function ?
Waiting for your help thank you all.
Have a nice day
I gave it a try, but you're using Javascript in Node.js which I don't use. Still, it could be useful to give an answer because I got somewhat closer to the result you want.
First of all I noticed that your JS result is in hexadecimal whereas the PHP result is probably in Base64. Some conversion is required. I had to use the raw result, and remove the padding to get a hexadecimal string that's as long as yours. The PHP code is:
$raw = openssl_encrypt($p2,
'aes-128-ecb',
'aeda94ad8azd',
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
$result = bin2hex($raw);
Now the result is:
c04e45a44b8fb9674bf03d3acbf8e2a9107b91e85170b701988d7a02772ab0a59e7aa5a6f138f4f1a9c506b9c3d09582
Same type (hexadecimal) and length of string, but not the same. There are two things that could cause the difference:
The character encoding of the file. I can't check the node.js one.
The keys might be treated differently. In node.js it has to be in UTF-8 and I think it is binary in PHP.
Anyway, I hope this is somewhat useful.
I am trying to convert a hex string into a signed integer.
I am able to easily transfer it into an unsigned value with hexdec() but this does not give a signed value.
Edit:
code in VB - the two "AA" hex values are representative.
Dim bs(2) As Byte
bs(1) = "AA"
bs(2) = "AA"
Dim s As Short
s = BitConverter.ToInt16(bs, 1)
Check out this comment via php.net:
hexdec() returns unsigned integers. For example hexdec("FFFFFFFE") returns 4294967294, not -2. To convert to signed 32-bit integer you may do:
<?php
echo reset(unpack("l", pack("l", hexdec("FFFFFFFE"))));
?>
As said on the hexdec manual page :
The function can now convert values
that are to big for the platforms
integer type, it will return the value
as float instead in that case.
If you want to get some kind of big integer (not float), you'll need it stored inside a string... This might be possible using BC Math functions.
For instance, if you look in the comments of the hexdec manual page, you'll find this note
If you adapt that function a bit, to avoid a notice, you'll get :
function bchexdec($hex)
{
$dec = 0;
$len = strlen($hex);
for ($i = 1; $i <= $len; $i++) {
$dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i))));
}
return $dec;
}
(This function has be copied from the note I linked to ; and only a bit adapted by me)
And using it on your number :
$h = 'D5CE3E462533364B';
$f = bchexdec($h);
var_dump($f);
The output will be :
string '15406319846273791563' (length=20)
So, not the kind of big float you had ; and seems OK with what you are expecting :
Result from calc.exe =
15406319846273791563
Hope this help ;-)
And, yes, user notes on the PHP documentation are sometimes a real gold mine ;-)
I've been trying to find a decent answer to this question and so I wrote this function which works well for a Hex string input, returning a signed decimal value.
public function hex_to_signed_int($hex_str){
$dec = hexdec($hex_str);
//test is value negative
if($dec & pow(16,strlen($hex_str))/2 ){ return $dec-pow(16,strlen($hex_str));}
return $dec;
}
I am trying to pass over from php a string into C++, i managed to figure out how to pass numbers, but it doesn't work for letters. Here's what i have that works for PHP
<?php
$r = 5;
$s = 12;
$x= 3;
$y= 4;
$q= "Hello World";
$c_output=`project1.exe $r $s $x $y $q`; // pass in the value to the c++ prog
echo "<pre>$c_output</pre>"; //received the sum
//modify the value in php and output
echo "output from C++ programm is" . ($c_output + 1);
?>
This sends the variables r,s,x,y, and q to the C++ programm project1.exe and IT WORKS, but the problem is that it doesn't work for the string variable $q.
Here's the code that I have in my C++ programm, it's simple:
#include<iostream>
#include<cstdlib>
#include<string>
using namespace std;
int main(int in, char* argv[]) {
int val[2];
for(int i = 1; i < in; i++) { // retrieve the value from php
val[i-1] = atoi(argv[i]);
}
double r = val[0];
double s = val[1];
double x = val[2];
double y = val[3];
double q = val[4]; // here's the problem, as soon as i try to define val[4] as a string or char, it screws up
cout << r;
cout <<s;
cout << x;
cout << y;
cout << q;
// will output to php
return 0;
}
It works, but for the string "Hello world" which i pass through $q from PHP doesn't give me the string back (i know it's defined as a double, but as soon as i try to change it to a string or a char variable the code just doesn't compile).
Please explain to me how i have to go around this problem so that $q can be processed as a string. FYI, I am a newbie to programming (6 months in).
Try not converting the final argument using atoi(argv[i]). Just keep it as argv[i].
for(int i = 1; i < in-1; i++)
{
val[i-1] = atoi(argv[i]);
}
q = argv[i];
It doesn't work for letters because you are doing atoi(..)(which converts char-string to integer) in the C++ program.
Have some means of letting the program know what to expect -- whether a number or a string. May be the first argument can help the program differentiate, like may be the following:
$c_output = `project1.exe nnsnns 1 2 string1 3 4 string2`
Then you could do:
for(int i = 0/*NOTE*/,len=strlen(argv[1]); i < len; i++) { // retrieve the value from php
if (argv[1][i] == 'n'){
//argv[2+i] must be an integer
}else if (argv[1][i] == 's'){
//argv[2+i] is a string
}
}
Of course you should check if (strlen(argv[1]) == in-2).
BTW, in the C++ code above, val is a array holding 2 ints; and you are trying to access much beyond index 1.
To pass one single string to the C++ you would do something like the following:
$output = `project1.exe $q`; //Read below.
NOTE: $q must be a single word. No spaces, no extra characters like '|', '&', or any other character which the shell might interpret differently. $q must be clean before you pass that on to C++ Program. If $q is more than one word, use quotes.
C++ Part (Just try the following, then you can modify as you go along)
cout<<argv[1]<<endl;
Given a randomly generated string, how do I convert it to make it URL safe -- and then "un convert" it?
PHP's bin2hex function (see: http://www.php.net/manual/en/function.bin2hex.php) seems to safely convert strings into URL safe characters. The hex2bin function (see: http://www.php.net/manual/en/function.hex2bin.php) is probably not ready yet. The following custom hex2bin function works sometimes:
function hex2bin($hexadecimal_data)
{
$binary_representation = '';
for ($i = 0; $i < strlen($hexadecimal_data); $i += 2)
{
$binary_representation .= chr(hexdec($hexadecimal_data{$i} . $hexadecimal_data{($i + 1)}));
}
return $binary_representation;
}
It only works right if the input to the function is a valid bin2hex string. If I send it something that was not a result of bin2hex, it dies. I can't seem to get it to throw an exception in case something is wrong.
Any suggestions what I can do? I'm not set on using hex2bin/bin2hex. All I need to to be able to convert a random string into a URL safe string, then reverse the process.
What you want to do is URL encode/decode the string:
$randomString = ...;
$urlSafe = urlencode($randomString);
$urlNotSafe = urldecode($urlSafe); // == $randomString
You can use urlencode()/urldecode().
I use document.getElementById("text").value.length to get the string length through javascript, and mb_strlen($_POST['text']) to get the string length by PHP and both differs very much. Carriage returns are converted in javascript before getting the string length, but I guess some characters are not being counted.
For example,
[b]15. Umieszczanie obrazka z logo na stronie zespołu[/b]
This block of text is calculated 57 in javascript and 58 in PHP. When the text gets long, the difference increases. Is there any way to overcome this?
If you're trying to get the length of an UTF-8 encoded string in PHP, you should specify the encoding in the second parameter of mb_strlen, like so:
mb_strlen($_POST['text'], 'UTF-8')
Also, don't forget to call stripslashes on the POST-var.
I have found an mb_strlen equivalent function for Javascript, maybe this might be useful for someone else:
function mb_strlen(str) {
var len = 0;
for(var i = 0; i < str.length; i++) {
len += str.charCodeAt(i) < 0 || str.charCodeAt(i) > 255 ? 2 : 1;
}
return len;
}
Thanks to all that tried to help!
I notice that there is a non-standard character in there (the ł) - I'm not sure how PHP counts non-standard - but it could be counting that as two. What happens if you run the test without that character?
This should do the trick
function mb_strlen (s) {
return ~-encodeURI(s).split(/%..|./).length;
}
Just type more than one line in your text area and you'll see the diference going bigger and bigger...
This came from the fact Javascript value.length don't count the end of line when all PHP length functions take them in account.
Just do:
// In case you're using CKEditot
// id is the id of the text area
var value = eval('CKEDITOR.instances.'+id+'.getData();');
// String length without the CRLF
var taille = value.length;
// get number of line
var nb_lines = (value.match(/\n/g) || []).length;
// Now, this value is the same you'll get with strlen in PHP
taille = taille + nb_lines;