I used the solution accepted for this question for encrypting by id for example in /index.php?id=3 . The problem is I cannot send the encrypted value as an url, example /index.php?id=dsf13f3343f23/23=. Because sometimes it will have weird characters in the url e.g. notice the =
sign in the end
Answers
They produce different outputs because you provided different inputs, i.e. different character encodings: Firefox uses UTF-8 and your PHP script uses Windows-1252. Although in both character sets the characters are at the same position (ß
=0xDF, ä
=0xE4), i.e. the have the same code point, they encode that code point differently:
CP | UTF-8 | Windows-1252
------+--------+--------------
0xDF | 0xC39F | 0xDF
0xE4 | 0xC3A4 | 0xE4
Use the same character encoding (preferably UTF-8) and you’ll get the same result.
You use a random IV to encrypt, and the a different random IV to decrypt. The decrypted string will never ever match the original. To properly decrypt the original string you must use the same IV that was used during encryption. Usually this is achieved by prepending the IV used to the encrypted string. At decryption time you must first extract the IV from the value, initialize the key with this value, then decrypt the rest usign the properly initialized key.
I don't have a parser to validate this but it should be something like:
private function _code_encryption($enc_type,$a_string){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
if($enc_type == self::ENCRYPT_STRING){
//encrypt then return base64 encoded
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, self::AUTH_ENCRYPTION_KEY, $a_string, MCRYPT_MODE_CBC, $iv);
return base64_encode($iv.$encrypted);
} elseif ($enc_type == self::DECRYPT_STRING){
$decoded = base64_decode($a_string);
$iv = substr($decoded,0,$iv_size);
$cipher = substr($decoded,$iv_size);
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, self::AUTH_ENCRYPTION_KEY, $cipher, MCRYPT_MODE_CBC, $iv);
return trim($decrypted);
}
}
url encoding a "raw" unicode doesn't really make sense. What you need to do is .encode("utf8")
first so you have a known byte encoding and then .quote()
that.
The output isn't very pretty but it should be a correct uri encoding.
>>> s = u'1234567890-/:;()$&@".,?!'[]{}#%^*+=_|~<>u20acxa3xa5u2022.,?!''
>>> urllib2.quote(s.encode("utf8"))
'1234567890-/%3A%3B%28%29%24%26%40%22.%2C%3F%21%27%5B%5D%7B%7D%23%25%5E%2A%2B%3D_%5C%7C%7E%3C%3E%E2%82%AC%C2%A3%C2%A5%E2%80%A2.%2C%3F%21%27'
Remember that you will need to both unquote()
and decode()
this to print it out properly if you're debugging or whatever.
>>> print urllib2.unquote(urllib2.quote(s.encode("utf8")))
1234567890-/:;()$&@".,?!'[]{}#%^*+=_|~<>€£¥•.,?!'
>>> # oops, nasty  means we've got a utf8 byte stream being treated as an ascii stream
>>> print urllib2.unquote(urllib2.quote(s.encode("utf8"))).decode("utf8")
1234567890-/:;()$&@".,?!'[]{}#%^*+=_|~<>€£¥•.,?!'
This is, in fact, what the django functions mentioned in another answer do.
The functions django.utils.http.urlquote() and django.utils.http.urlquote_plus() are versions of Python’s standard urllib.quote() and urllib.quote_plus() that work with non-ASCII characters. (The data is converted to UTF-8 prior to encoding.)
Be careful if you are applying any further quotes or encodings not to mangle things.
There does appear to be a standard, it is RFC 3548, Section 4, Base 64 Encoding with URL and Filename Safe Alphabet:
This encoding is technically identical to the previous one, except for the 62:nd and 63:rd alphabet character, as indicated in table 2.
+
and /
should be replaced by - (minus)
and _ (understrike)
respectively. Any incompatible libraries should be wrapped so they conform to RFC 3548.
Note that this requires that you URL encode the (pad) =
characters, but I prefer that over URL encoding the +
and /
characters from the standard base64 alphabet.
The weird characters in the values passed in the URL should be escaped, using
urlencode(
).For example, the following portion of code :
would give you :
Which works fine, as an URL parameter.
And if you want to build aquery string with several parameters, take a look at the
http_build_query()
function.For example :
will give you :
This function deals with escaping and concatenating the parameters itself ;-)