Removing these extra characters - php

I'm working on an application and I'm stuck here.
I'm making a product delete page, where the id is passed in the URL so that I can search the database and select the particular record.
Since passing the id naked is not a good idea, so therefore I'm encrypting the id in a hash and then passing. But since the hash have some spaces in between, when I try to use it in my application..extra space characters are added in the hash to fill in the spaces.
Here's my encrypt function :-
function getHash($recordid)
{
global $db;
$key_value="12466X##";
$plain_text=$recordid;
$encrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $plain_text, MCRYPT_ENCRYPT);
return $encrypted_text;
}
Here's what I get output for $plain_text = 1 when I do not pass in the URL and simply print it.
ÑÛo‡Ó‰-7
But, if I pass it via URL, it gets converted to this :-
%D1%DBo%87%D3%89-7
Therefore surely I wouldn't get the correct results when I decrypt it.
Is there any way I can get the original value after decrypting it (1 in this example), or could I entirely use a different decrypt, encrypt function so that I get rid of this problem?
Thank you.

Since these are all 8-bit characters, when they get encoded, they're converted to their %XX Hex representation. The web server does the reverse for you when it's in the Query part of the URL, so you should be ok. Still, it's safer to base64-encode the crypted string before making an URL of it, and base64-decode it when you get it back, so you need to deal with ascii characters only.

Related

Trouble creating auth string using PHP HMAC SHA1 and Base64

So I am working with this API and using Laravel, and I am trying to build an auth string. This is the documentation I was given, but I am having a little trouble as this is something relatively new to me.
Here are the auth instructions:
The authentication parameter is a string and it can calculated by the
caller or the caller can choose to save this value as a parameter
together with connection ID and API key.
The authentication is a base64 string of a HMAC SHA1 hash. This is
computed by using the binary of API Key in in
########################## format in all lower case and UTF8 encoding as the key and computer HMAC SHA1 hash on the binary of
Connection ID in ################################ format in all lower
case and UTF8 encoding.
The result binary hash is then base64 encoded and the text result is
what should be passed as the authentication parameter. In C# the code
to calculate the authentication may look like:
HMACSHA1 hmac = new HMACSHA1(
UTF8Encoding.UTF8.GetBytes(apiKey.ToString("N").ToLower())
);
string authentication = Convert.ToBase64String(
hmac.ComputeHash(
UTF8Encoding.UTF8.GetBytes(connectionId.ToString("N").ToLower())
)
);
As an example the following credentials:
Connection ID: 5fecbc200f0e4a7cbf41040e11047e56
API Key: 2de51c4fd0f04b9fabeb95225e87da70
Should result in a computed authentication value of
m5/Vc1RzhUETQvEtx/JdIglQpTg=
So what i have been trying is:
$a = strtolower('5fecbc200f0e4a7cbf41040e11047e56');
$b = strtolower('2de51c4fd0f04b9fabeb95225e87da70');
$z = hash_hmac("sha1", utf8_encode(decbin($b)), utf8_encode(decbin($a)), true);
dd(base64_encode($z));
Which outputs QjG3kzUs7U1UukNd++3t24pBWNk=
I have tried a few more variations, but I am just lost on this one. First time really decoding or encoding anything. Would greatly appreciate any tips, ideas, or snippets that can help me figure this out. Already spent a few hours on this and it's bugging me..
First: Get rid of utf8_encode() and just generally don't use it. It assumes that the input string is ISO-88591-1 and if it is anything else it will silently corrupt the data. This function has an incredibly misleading name, and I would go as far as to suggest that no one should ever use it or the corresponding utf8_decode() which will break your data in the same manner, but reversed.
If you need to convert string encodings in PHP use something that explicitly defines the input and output encodings, eg: mb_convert_encoding(). [you still don't need it for this]
Second: Whatever you think decbin() does, you're incorrect. It converts an integer into a literal, capital-S String composed of 0 and 1 characters.
Third: PHP strings have no inherent encoding and are roughly equivalent to byte arrays if you twisted my arm for a description. The bytes you put into them are the bytes you get out of them.
Fourth: I'm not exactly a C# expert [or intermediate, or even beginner] but that example code is horrendous. What even is the significance of the N in connectionId.ToString("N")? I can't find any documentation about this.
Start simple, use meaningful variable names, build up, and read the docs.
$connectionID = strtolower('5fecbc200f0e4a7cbf41040e11047e56');
$apiKey = strtolower('2de51c4fd0f04b9fabeb95225e87da70');
$hash = hash_hmac("sha1", $connectionID, $apiKey, true);
var_dump(base64_encode($hash));
Output:
string(28) "m5/Vc1RzhUETQvEtx/JdIglQpTg="

Encrypted values (mcrypt_encrypt) in URL parameters generating different results while requesting.How to tackle the situation?

I am using the following function to encrypt a string ($str) using a key ($key) to make a unique key.
Sample Code:
<?php
$key = "####";
$str = "123456789";
$encrypted_key = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $str, MCRYPT_MODE_CBC, md5(md5($key))));
echo $encrypted_key; // 3rfmDKb/Ig5FuUnkY8fiHpqA3FD4PflXMksJw+6WAns=
?>
The function is returning values consisting special characters including '+' . I am storing this values in database as a unique ID.
However in certain conditions, I need to pass the $encrypted_key through URLs . i.e; for using it with RESFful web services
Sample URL:
www.example.com/index.php?encrypted_key=3rfmDKb/Ig5FuUnkY8fiHpqA3FD4PflXMksJw+6WAns=
But this when requested through URL will decode '+' into 'spaces'
Code:
echo $encrypted_key = $_REQUEST['encrypted_key'];
// 3rfmDKb/Ig5FuUnkY8fiHpqA3FD4PflXMksJw 6WAns=
This conversion is further affecting the DB checks :
'3rfmDKb/Ig5FuUnkY8fiHpqA3FD4PflXMksJw 6WAns=' against '3rfmDKb/Ig5FuUnkY8fiHpqA3FD4PflXMksJw+6WAns='
Also I am having a concern of storing these encrypted values into indexed MySQL DB columns.
What should be the best practice to be adopted here? Any advise will be highly appreciated.
This answer only addresses the representation, not the likely-to-be-wrong use of crypto.
When you build objects that have special representation rules like database queries, paths in URLs, HTML code, JS code, and so on, you must ensure that you perform the proper kind of encoding of the values so that they roundtrip without harm.
For database query parameters, do not use string concatenation. Use prepared statements and placeholders.
For URLs, use the proper URL encoding function or an URL builder to construct your URL, do not blindly concatenate strings.
First, is not a good idea to use encrypted values as Unique ID or as Conditional Field, because they will change for the same value. This is very commom in encryption. If an encryption algorithm don't change the result for the same entry, it is not a good encryption.
Second, I had the same problem to deal with encryption and URL, and in my case a made my own encryption algorithm, using only valid characters for URL.
It is not dificult to implement an encryption: I used the ASCII code, one simple key, one simple math function, and nothing more. To decryption, I "reversed" the math function.

openssl_public_encrypt and JSON

Let's say we need to store in a crypted way some confidential data into a db. And say that we need them into json format as will be more suitable for data reconstruction.
There's something that I miss that is driving me crazy.
Take that json for instance
$json = {"customer":{"customer_address":"Fake address 123","customer_city":"Fake City","customer_company":"","customer_countrycode":"it","customer_email":"","customer_telephone":"+39.347.xxxxxxx","customer_zip":"yyyyy"},"currency_code":"EUR","commision_amount":"84"}
now I want to crypt this json and I do the following
$pubKey = openssl_pkey_get_public($puk);
openssl_public_encrypt($json, $json_crypted, $pubKey);
if I echo $json_crypted it doesn't show anything, but if I remove some field (like customer_company, that is empty) all seems to work. I've tried to find something into documentation about this strange behaviour but I can't find anything.
Is someone aware of the reason behind that result?
Edit
Even if I remove other field (not an empty one) all seems to work. I'm speechless because it has to be a silly thing that I can't understand
From the comments in documentation:
http://www.php.net/manual/en/function.openssl-public-encrypt.php#95307
openssl_private_encrypt() has a low limit for the length of the data
it can encrypt due to the nature of the algorithm.
To encrypt the larger data you can use openssl_encrypt() with a random
password (like sha1(microtime(true))), and encrypt the password with
openssl_public_encrypt(). This way the data can be encrypted with a
public key and decrypted with the private one.
Your json must exceed the length limit...

sha1 encode exact value of parameter instead of the variable value

I'm working with an application that requires sha1 encoding for certain form values.
The problem is that when I use the following
<?php echo(hash("sha1","par1=".$_POST['p1']."&par2=".$_POST['p2'])); ?>
It gives me a sha1 encoding of the actual string, while I want to get a sha1 encoding of the posted values, so in this example I want to get
<?php echo(hash("sha1","par1=firstvalue&par2=secondvalue")); ?>
How can I realize this? Is it actually that simple and am I thinking way to difficult?
That because it identifies that para1=some_value as string not para1 as variable and some_value string
To achieve what you want you should hash every variable alone
Or I suggest that you implement your own encoding algorithm
Why not do it like this? Though I would have though either way would result in the same thing....
$hash_this = "par1=".$_POST['p1']."&par2=".$_POST['p2'];
echo sha1($hash_this);
Though that will do it if you want to hash the string of the values all together, rather than the values, if you want to store the values - then you should probably hash each value, so you could at least compare them later. Useful for a login system where you want to save a password to a database, which is more secure than literally just storing the password...
$password = sha1($_POST['password']);
If you hash the string, you have no idea which value is wrong

obfuscate or encrypt some plain text data in PHP

I need to obfuscate or encrypt some plain text data in my php 5.2 application.
I'd prefer a solution that would have input string and output string retain the same length.
This does not need to extremely strong, as there are numerous other layers of security in place. Strong would be good, but this will just keep programmers/dba/support people/etc from accidentally reading the text from within the database.
key considerations
EDIT ADD I'd prefer a solution that would have input string and output string retain the same length.
only string text will be obfuscated/encrypted for storage in a database
the php application will need to obfuscate/encrypt the data before the database save and will need to un-obfuscate/dencrypt following the database read
this is a modification to an existing application
only some columns will need to be obfuscated/encrypted
only some rows will need to be obfuscated/encrypted, based on a Type field
there are only a few load/save points to handle
max column size is already determined for some fields, but not for others, but I'd prefer a solution to work within the existing size of the restricted fields
EDIT, ADD the key will be probably be a composite of some Primary key info +uneditable fields
here is a sample database table and data:
int char(1) varchar(24) int date
MyPrimaryKey RowType UserText UserNo DateChange
------------ ------- ------------------------ -------- ----------------
1 N nothing special here 43 6/20/2009 12:11am
2 N same thing, wow! 78 6/23/2009 1:03pm
3 S fBJKg}.jkjWfF78dlg#45kjg 43 6/25/2009 6:45am
4 N same old, same old text 21 6/25/2009 8:11am
The application would load and display rows 1,2, and 4 normally. However it would conditionally (based on row type) handle the text in row 3 using this obfuscate/encrypt and un-obfuscate/decrypt logic.
Can anyone provide obfuscate/encrypt and un-obfuscate/decrypt functions code, links, and or pointer that would help here?
thanks!
EDIT
I like the simple base64 encoding idea, but is there a method that can keep the data within a fixed size. All methods listed so far have the output value larger than the input value. This will be a problem for some columns, where the user can enter in 50 characters and it is stored in a varchar(50) column.
for simple obfuscation use strtr() - Translate certain characters:
string strtr ( string $str , string $from , string $to )
to encode in php:
$readable='This is a special test string ABC123 ([+,-!#$%&*])';
$unreadable=strtr($readable,' !"#$%&\'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
,'¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ !"#$%&\'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ '
);
print $unreadable; //outputs: "ÕéêôAêôAâAôñæäêâíAõæôõAôõóêïèAÂÃIJ³´A©Ü¬­®¢¤¥¦§«Þª"
to decode in php:
$unreadable='ÕéêôAêôAâAôñæäêâíAõæôõAôõóêïèAÂÃIJ³´A©Ü¬­®¢¤¥¦§«Þª';
$readable=strtr($unreadable,'¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ !"#$%&\'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ '
,' !"#$%&\'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
);
print $readable; //outputs: "This is a special test string ABC123 ([+,-!#$%&*])"
you can easily replicate this logic in the DB if necessary (without looping): Using a Table of Numbers, by Erland Sommarskog
How about base64 encoding? We use to use that to make SMS messages in our SMS Gateway DB unreadable by the developers.
Try these PHP functions convert_uuencode and convert_uudecode:
function encrypt_decrypt ($data, $encrypt) {
if ($encrypt == true) {
$output = base64_encode (convert_uuencode ($data));
} else {
$output = convert_uudecode (base64_decode ($data));
}
return $output;
}
$enc_txt = encrypt_decrypt ("HELLO DATA", true);
echo $enc_txt."\n"; // KjIkNSwzJFxAMSQlNDAwYGAKYAo=
echo encrypt_decrypt ($enc_txt, false); // HELLO DATA
There are a few options.
If you want very strong, you could look into mcrypt.
But if it's only so working developers cant read the text without some work to actually do it. Then you could just BASE64 encode it or uuencode it
If you have mcrypt installed (all my current PHP environments have), you could use mcrypt_encrypt and mcrypt_decrypt like this:
function encrypt ($text) {
global $key;
return mcrypt_encrypt (MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, "abcdefghijklmnopqrstuvwxyz012345");
}
function decrypt ($secret) {
global $key;
return rtrim (mcrypt_decrypt (MCRYPT_RIJNDAEL_256, $key, $secret, MCRYPT_MODE_ECB, "abcdefghijklmnopqrstuvwxyz012345"), "\0");
}
which uses a global $key and AES (very strong).
Drawbacks are performance (in comparison to simpler ones like Base64) and that you somehow have to fix a key.
Cheers,
if you're using mysql around version 5, then you don't even need much php for it, you can do it inside your query with the mysql string functions encrypt(text, password) and decrypt(text, password)
http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html
DECODE(crypt_str,pass_str)
Decrypts the encrypted string crypt_str using pass_str as the password. crypt_str should be a string returned from ENCODE().
ENCODE(str,pass_str)
Encrypt str using pass_str as the password. To decrypt the result, use DECODE().
The result is a binary string of the same length as str.
The strength of the encryption is based on how good the random generator is. It should suffice for short strings.
update: another possibility would be rot13 ^^
Try using the mcrypt library. It's not included with standard PHP, but it's easily downloadable and very commonly used. Here's a quick tutorial on what you can do with it.
It's best to make sure the key you use for the encryption is stored in a secure place, but if you aren't really concerned about security, you'd probably be OK just hardcoding the key into your code somewhere.

Categories