I'm setting up a PHP email tracking system that uses url parameters to track link click throughs. Something like:
www.example.com?trackToken=10
I'm looking for a simple PHP encode / decode function I can put in place that will take a number (in this case 10) and convert in to strictly to number and letters. something like:
www.example.com?trackToken=7aj8nG93nDpw9M9Nk1
I have found several variations of encrypt / decrypt functions using mcrypt. However, the encrypted output always ends up containing strange characters. These strange characters make it hard for my email messages to be sent/delivered.
Does anyone know of a good encrypt function that only outputs numbers 0-9 and letters a-z or A-Z? Additionally, I'm looking for a decrypt function to complement the encrypt function so I can actually use it.
I'm not looking for something super secure here. Just a way to mask the actual tracking token so the user can't change it on their own.
Base64 should be fine in any modern system - and any system handling email in PHP fits the definition of "modern". There is absolutely no reason I can think of to limit to just alphanumerics. The only catch is that as a URL parameter you don't want to have a '+' or '/' in the string. There is base64url to solve this problem but that doesn't have a standard PHP function. You can easily replicate that by using base64_encode() and str_replace() and to decode str_replace followed by base64_decode():
$coded = str_replace('+','-',str_replace('/','_',base64_encode($original)));
$original = base64_decode(str_replace('_','/',str_replace('-','+',$coded)));
I am using the zend mcrypt function for the encryption of a text.
The encryption is done using the code below,
use Zend\Crypt\BlockCipher;
use Zend\Crypt\Symmetric\Mcrypt;
$blockCipher = new BlockCipher(new Mcrypt(array('algo' => 'aes'));
$blockCipher->setKey('enCryKey');
$result = $blockCipher->encrypt('this is a secret message');
echo "Encrypted text: $result \n";
There are some special characters appearing in the encrypted text. But, i have to use this in a URL and i don't want any special characters in the URL, because of url encoding difference for different mails.
Is there any way to avoid the special characters from the encrypted text which uses zend mcrypt(aes) for encryption?
I am using PHP openssl_sign to create a digital signature using the tutorial here. How can i convert $signature (which contains binary data) to Base64.
You can convert binary to base64 using base64_encode.
Just do:
base64_encode($signature);
Read more here: http://php.net/manual/en/function.base64-encode.php
My web application communicates with the server over JSON protocol. Before sending each JSON message from the web application, I run a hmac-sha1 function on it (on already encoded object) and insert the resulting HMAC into the header of JSON request.
On server side, I decode JSON message with PHP, extract the HMAC, unset() the HMAC from the object and then encode the object back into JSON and create a HMAC of it.
The HMACs match as long as I don't use characters like "ž, š, č". When I use those characters in the message, the HMACs don't match anymore.
In the web application I'm using jQuery.post() to transmit the already encoded JSON string.
If I send the data I got from the web application back to it in the JSON encoded reply, the application will display "ž, č, š" just nicely.
How can I make the HMACs match?
UPDATE:
This is only a problem on latest version of Firefox and Opera. It works fine on IE8 and Chrome. On the former browsers, the JSON string (before it is sent) is:
{"body":[{"name":"Žiga Kraljevič","email":"test#email.com","password":"secretpass"}],"header":{"apiID":"person-27jhfa83ha-js84sjj18dasjd","hmac":"e4259d6ef8f477c020d644409cc16dd9c42301e8"}}
While on the latter browsers (IE8 and Chrome, where it works) is the following:
{"body":[{"name":"\u017diga Kraljevi\u010d","email":"test#email.com","password":"secretpass"}],"header":{"apiID":"person-27jhfa83ha-js84sjj18dasjd","hmac":"e4e9e2d0d8d11728a2b4329ad6dacdb9409b1de1"}}
You're probably running into multiple issues. One of them may well be that the character encoding being used on the client is different from that being used on the server, worth ensuring that they're the same (more about character encoding in Joel's excellent essay). Another may well be that there are multiple correct ways to encode things. The encoders may well be using different ways. For instance, you can encode a " within a string as either \" or \u0022. Both are valid, and they're equivalent, but the hashes won't match. Similarly, I'm a bit surprised you're not running into more trouble when not using accented characters, for instance with whitespace.
What is your hmac-sha1 function, where's it from? If it is taking a JSON String as input then there's an implicit encode-to-bytes step going on here because SHA1 operates on bytes, not UTF-16 code units like JS String.
I would suspect that your JS function is using a “one code unit n per byte n” type of encoding, for easy calculation with tools like getCharCodeAt. This is effectively the same as if the character string input had been encoded to ISO-8859-1. Whereas if you are using encodeURIComponent or posting the raw characters via XMLHttpRequest, the implicit encoding there is UTF-8.
You could convert the String to UTF-8-bytes-stored-as-code-units format for the JS hmac-sha1 function, that might make it match PHP. There's a sneaky idiom to do this:
var utf8= unescape(encodeURIComponent(s));
When POSTing JSON I base64 and urlencode it anyway
URL-encoding should be enough (with encodeURIComponent, not escape which is the wrong thing for absolutely everything except the reverse step of the UTF-8-conversion trick above).
BTW, what's the purpose of this? You do know it doesn't in any way secure the connection between the browser and the server, yeah?
Edit:
I'm using jssha.sourceforge.net for sha1-hmac. In PHP I'm using hash_hmac.
Works for me:
var data= '\u017E, \u010D, \u0161'; // 'ž, č, š' in a Unucode string
var utf8bytes= unescape(encodeURIComponent(data));
var hmac= new jsSHA(utf8bytes).getHMAC('foo', 'ASCII', 'SHA-1', 'HEX');
alert(hmac); // 5d15f0b9...
var form= 'message='+encodeURIComponent(data)+'&hmac='+encodeURIComponent(hmac);
xmlhttprequest.send(form);
...
$utf8bytes= $_POST['message']; // "\xc5\xbe, \xc4\x8d, \xc5\xa1"
// which is 'ž, č, š' as UTF-8 in byte string
$hmac= hash_hmac('sha1', $utf8bytes, 'foo');
echo $hmac; // 5d15f0b9...
echo strtolower($hmac)===strtolower($_POST['hmac']); // true
This uses the binary ('ASCII' to jsSHA) key foo. If you are using a binary key with non-ASCII characters in it, you would have to make sure that those are properly encoded too, in the same way as the data.
The key for HMAC is a shared secret between the server and the client, which has been previously exchanged over a secure connection.
It's not only the key you'd have to send over a secure connection, but the entire page and all scripts in it. Otherwise a man in the middle attack could sabotage your scripts on the way to the browser to replace them with a version that used the secret key to sign bogus messages. If you've got an HTTPS server for all this stuff, fine. I'm not sure what the HMAC would be doing in that case though, it seems a bit involved for an anti-XSRF scheme.
so I have my php API (html Get api for Flash builder and C# apps). So if you want to submit data to it you use string like
http://localhost/cms/api.php?method=someMethod&string=Your_String
If there are english letters in it its ok. But what if I need to pass UTF-8 string like this Русское Имя to my api what shall I do?
Use the rawurlencode() function. It will encode your string byte by byte, but it is not a problem, since UTF-8 is an ASCII aware representation. All code positions below 128 are identical to the ASCII one, all code positions above 127 are represented with byte sequences which are all between 128 and 255, so you will not have problems with it. The input wrapper should decode the parameters into your $_REQUEST array properly.