Generate API Client Key and Client Secret with php - php

I am creating a custom payment processing component for Joomla. This component has an API that allows users to process payment from other sources such as Woocomerce, Wix etc.
I will like to know if it is safe to generate the "Client Key" and the "Client Secret" with my own written PHP script.
//Client Key
$key = md5(microtime(true).mt_Rand());
//Client Secret
$secret = bin2hex(random_bytes(32));
If not, I will be glad if someone can point me to a more reliable script.
Thank you

Generating a key using PHP is not inherently unsafe, as long as you take some precautions. While your question may attract a lot of opinion-based suggestions which may all be correct, I'd suggest some pointers
md5 should be avoided whenever possible. Nowadays, collision attacks for md5 are simple enough to be considered trivial even if you are using a random salt upong hash generation. You should at least use sha1 (which is also somewhat easy to collide, albeit no as easy as md5) or sha256.
There's a lot of alternatives in case you want to stay away from sha1/sha256 too, although sha256 is, by 2018 standards, secure enough as a hashing algorithm. I would, however, use something other than microtime as the hash input parameter. Even though you're salting it, it's quite predictable. Just to err on the safe side of predictability, I'd advise concatenating something extra (i.e., microtime.mt_rand.something_else_which_is_also_random)
As for the secret, I'd suggest something more robust. There's no such thing as true randomness in PHP from a cryptological standpoint, so random_bytes may be more predictable and exploitable than it would seem at first glance. That, combined with the fact that bin2hex is just a conversion and not a one-way function, makes the whole secret a weak link. I'd use a longer string (32 seems weak) and combine it with something else (perhaps a bitwise XOR with a random string of equal length)

Related

Is this PHP implementation of pbkdf2 hashing for password generation considered safe?

I am looking at implementing key generation from a password using PBKDF2. Since PHP 5.5, there is the function http://www.php.net/manual/en/function.hash-pbkdf2.php, but my server is running on PHP 5.3. After a quick search on the web, I found this custom implementation in PHP: https://gist.github.com/rsky/5104756 My question to someone more experienced in the field is if it is considered safe?
If it compiles to correct test vectors then I would not worry overmuch on security for key derivation functions.
You may have to worry about side channel attacks if you are on a machine that also provides access to other users. In that case you probably have to worry about side channel attacks on the hash algorithm; normally it's tricky to perform time based attacks on symmetric algorithms on a fast CPU though (unprotected RSA is much easier).
It is important that salt values are large enough and do not repeat, so check the secure random number implementation on the system.
Note that there are multiple levels of "safe". Without exact details of the system, use case, thread models etc. nobody could or should give you more than a generic answer.

Is it a good/clever idea to trick a hacker into thinking an encryption is md5, when it is not?

$clear_text = "hello";
$salt_ = sha1("758hF4H7gJi98U6o");
$salt = substr($salt_, 0, 12);
$hash = substr(hash("sha512", $clear_text), 0, 20).$salt;
As you can see, $hash generates a 32 character string, making it look identical to md5. So a hacker will be trying to decrpyt this md5 hash when in fact it is nothing like that!
Would this be cunning, and would it be a good idea?
Don't try to invent your own crypto, use standardized hashing algorithms like bcrypt, scrypt or PBKDF2.
Please refer to:
https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords
https://security.stackexchange.com/questions/18197/why-shouldnt-we-roll-our-own
There is a principle in security which is called Kirckhoff's principle, one of the rules is "It must not be required to be secret, and it must be able to fall into the hands of the enemy without inconvenience" Suggest the attacker has access to your machine and is able to dump your source files as well as your database it won't take him very long to discover your algorithm.
Now from there your own rolled algorithm doesn't really provide any additional protection from normal sha512+salt. The speed at which he would be able to attack the hashes would be the same with or without your algorithm. Meaning your scheme is useless once the algorithm as been found.
$salt_ = sha1("758hF4H7gJi98U6o");
Hashing entropy does not provide better entropy. See What should be used as a salt?. Summary: encode a unique and unpredictable value.
$hash = substr(hash("sha512", $clear_text), 0, 20).$salt;
You should use multiple iterations of hashing. See How to securely hash passwords. Summary: PBKDF2, BCrypt, SCrypt provide this.
Would this be cunning
No, and it'd be essentially irrelevant if your code was read as well.
and would it be a good idea
It'd more likely be a nuisance for anybody who ever had to maintain it in the future. It's probably not a bad idea on the face of it in that altering the hash format may confuse somebody, but you can consider that in-hand with reading The valid role of obscurity. If you're going to alter the hash format, spend that effort to encrypt it so it can't be attacked without the encryption key. The effort to find the key would probably be the same, but it'd be a much easier decision to defend.

Should sensitive data be encrypted through both script and database means?

I don't know too much about encryption, but is there any benefit to encrypting the already encrypted, lets say passwords? I am aware of salts, but before this is done, does it matter or not?
Encryption is 2-way thing, when hashing is 1-way. You can decrypt encrypted sting, while you can't revert hash.
One simple, but good example is using md5 hash + salt: MD5('password' + 'random_string') - no matter PHP or MySQL you use - result is the same. So what you have here - is hash of 'passwordrandom_string', which can be unlikely matched using a dictionaries.
So every time you check the password you do:
if (md5($password . 'random_string') == $hash_from_db)
Updated: but if you really concerned about security (this usually needs to be done only if your application works with very sensitive data), and say more - you have crazy paranoia and insanity about it: there are a lot of hashing methods over the Internet. Find something with random salt (so every password can have almost unlimited amount of hashes), make few changes, combine it with other hashing algorithm - problem solved.
One thing you should know - sometimes the slower hashing works - the better. That means if you somehow have a rat-hole in login-attempts counter this will really slow down bruteforce process.
One example you can take a look on - bcrypt (it uses Java for hashing). Not saying you should use it, just an example of what you should look for.
This question has some relevant discussion on the topic. There are cases in which it would be a bad idea and could potentially weaken the encryption as pointed out in the linked thread, so you wouldn't want to do this unless you're really sure of what you're getting into.
The fundamental basis for encryption is that it's easier to encrypt (polynomial time) than it is to decrypt (non-polynomial time). The only way encryption breaks is if either/both of the following is true:
There's a vulnerability in your encryption scheme which decreases the gap between the polynomial time it take you to encrypt and the non-polynomial time you expect it to take an attacker to decrypt.
Someone has sufficient computational resources to decrypt your data (in non-polynomial time).
It sounds like there are cases where double encryption could actually make issue #1 more probable, so that's dangerous. But issue #2 seems like the bigger one to me. The idea is that an attacker with sufficient computational resources will be able to decrypt my data -- an act which implies that they're willing/able to invest orders of magnitude more computational resources to decrypt my data than I was in encrypting it.
If we accept on fiat that an attacker has the vast computational resources required to decrypt my data, the thought that they could have 2x that many resources doesn't seem unreasonable at all, to me.
And realize also that if you're using the same key, then there's really no added security whatsoever -- once they crack one, they've cracked them both. Potentially there could be value in using two different encryption techniques with two different keys to encrypt something in order to protect against issue #1 popping up for either encryption scheme, but that's surely debatable.
It depends on what you mean by encryption. If you're actually encrypting information on the database using for example Microsoft's SQL Server encryption engine, then yes it does matter. You should not rely on database level encryption as it's not really secure. The key is still stored on the machine and only prevents naive attackers who do not seek out that key along with the database.
Generally, databases also support exporting data in plaintext when the database is encrypted. This means that if an attacker gets into the system, they can just do that. If they only have the hard drives (external drive is stolen), then it saves you.
Passwords should be hashed in your application and then sent to a database, generally. It's considered secure to generate a 64 byte salt and then use SHA-512(salt || password) where || denotes binary concatenation. Don't use randomized ASCII text for salts and stick with secure random number generators such as /dev/urandom or Microsoft's CryptGenRandom. This makes it so attackers cannot store pre-computed lists of hashes for reverse lookups of common passwords.
If you want to prevent the stolen backup drive scenario you need to also make sure you are backing up your database, keeping encryption on, and storing the keys in a secure environment away from the encrypted database. We call this "separating the lock from the key". Since this doesn't help you in the situation where your database is exported, you also want to do hashing as I mentioned earlier. Hashing in addition to encryption will make it so that 1.) Attackers can't get at other less sensitive information such as names and addresses and 2.) Attackers can't even begin to attempt recovery of passwords or other credentials.
The bottom line is that it depends on your threat model.
You do get some benefits from encrypting twice using different keys. For instance, a file encrypted with weaker ciper and subsequently encrypted again with a stronger cipher and key strength will be harder to break than just having the weak cipher alone. The analogy is putting a flimsy lock box inside of a bank's vault. But, in general, you're better of encrypting with a strong cipher than encrypting twice with a weak cipher.
There are also some instances where it is appropriate for something to be encrypted twice, such as when you cross multiple trust barriers. For instance, you might encrypt your files before sending them to a cloud provider (who you may not trust). If the cloud provider needs to send files to another offsite backup company (who the cloud provide may not trust), they might encrypt it again.
That said, for passwords, you are probably better off with using a strong hash (e.g. sha1) alongside a salt for storing passwords.
Yes. It does matter. Storing sensitive data anywhere in plaintext goes beyond bad practice. It's dangerous. Even the standard md5 hash is considered "broken" now, and shouldn't be used on its own without salting it, and perhaps using other hashing combinations in tandem with it. Just to shake things up.
$salt = 'Yh%Gg^!&ud$*';
$encryption = md5(sha1($salt.md5(md5($salt.$_POST['pwd']))));
$query = mysql_query("SELECT * FROM users WHERE name=$uname AND pass=$encryption");
Not exactly the most secure, but if anybody gets their hands on the table information, they won't be able to crack it without knowing the salt and hashing combination.
Ultimately, you need to make an educated decision based on the sensitivity of the data. If you're storing user passwords of any kind, even YOU shouldn't know what they are.

best password encryption and decryption technique to be used with PHP [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Best way to use PHP to encrypt and decrypt?
For my project I want to store password in encrypted format,
so i have stored it using md5('password'), but my project requirement is that we should be able to decrypt the password, and as you all know we can not decrypt md5 encrypted string.
so i have choose it to encode using base64_decode('password') and decode it using base64_decode('encodedpassword').
but i want to know that is it a best practice to use base64_encode ? or is there any other encryption decryption technique with PHP?
First off, md5('password') is not encryption. You cannot recover the original password after you hash the data. NB for technical readers: a brute force attack will not recover the password either, since there are a finite number of hashes and an infinite number of different strings.
Now, base64_encode('password') is also not encryption, except possibly in the very loosest sense of the word. Anyone can look at the Base64 text and recover the original password.
Encryption as it is generally known consists of a plaintext and a private key of some sort. An example of an encryption algorithm would be AES-256 ("Rijndael" is the name of the algorithm which won the AES contest and thus the title). AES-256 uses a 256-bit key and is generally considered very secure when properly implemented.
Cryptography is not a topic which should be approached lightly. It is extremely difficult to get right and the consequences when you do not are, although this seems contradictory, both subtle and severe.
You should very carefully evaluate whether you need to be able to recover the password. In 99.9999999% of all cases, the answer is "no". In fact, I cannot think of a case where the plain-text of the password would matter to you.
After you are done evaluating whether you need to be able to recover the password, decide that you do not need to be able to recover the password.
After that step, if you still believe you need to be able to recover the password, look at already-written crypto libraries for PHP. OpenSSL is a well-tested generally-accepted crypto framework which implements pretty much every popular encryption standard, but it may be a little on the difficult-to-use side. mcrypt is very commonly installed and generally easier to use.
I usually just go w/ sha-1 + a salt.., take a look at the crypt function.
For PHP version 5.3+
You would use Bcrypt, which is the strongest hash I have ever known.
But the problem is that it is slower than other encryptions.
I recommend AES256 which is faster than bcrypt and safe as well

What is the best way to encrypt a very short string in PHP?

I would like to encrypt strings which could potentially only be about three or four characters but run to about twenty characters. A hashing function (md5, sha1, crypt etc) is not suitable as I would like to be able to decrypt the information as well. The mcrypt extension has a thoroughly daunting array of possibilities.
Does anyone have any ideas about the best way to safely encrypt short strings and why? Does anyone have any links to any material introducing a casual programmer to practical encryption scenarios?
I like to use GnuPG for anything that needs to be encrypted on a server and then possibly decrypted either on the server or on another server (which is usually my case). This allows for an extra level of security since in my scenario the encrypting server doesn't have the key to decrypt the data. It also allows for easier manual decryption. There are a few good wrappers available for various languages (another advantage), one for PHP is GnuPGP PHP Class.
mcrypt is linked into most builds of PHP by default. It contains all the primitives you're likely to need. Without knowing more about what you're encrypting, what your threat model is, etc, it's hard to give concrete recommendations on what algorithm, mode of operation, etc to use.
One thing I can say for certain: With short text strings, it's more vital than ever that you MUST use a unique, random Initialization Vector. Otherwise, it's trivial for someone to mount a variety of attacks against the encrypted data.
I highly recommend the suggestions of Chris Kite. Without knowing more about what you're doing, why, and the threats you anticipate needing to protect against AES-128 is likely sufficient. The ability to use symmetric encryption is great for a standalone app that will be both the decryptor and encryptor of data. As both Chris Kite and Arachnid said, due to the small size of your data it's advised that you pad the data and use a random Initialization Vector.
Update: As for why.... if the data is small enough, and the IV can be predicted, it's possible to brute force the plain-text by generating cipher-text for every combination of plain-text with the known IV and matching it up to the captured cipher-text. In short, this is how rainbow tables work.
Now if you're going to encrypt on one server and decrypt on another I'd go with the suggestions of pdavis. By using an asymmetric method you're able to separate the encryption keys from the decryption keys. This way if the server that encrypts data is compromised, the attacker is still unable to decrypt the data.
If you're able to, it'd help the community to know more about your use case for the encryption. As I mentioned above, having a proper understanding of plausible threats is key when evaluating security controls.
I agree with Chris Kite - just use AES 128, this is far sufficient.
I don't know exactly your environment, but I guess you're transmitting the data somehow through the internet.
Don't use ECB, this will always produce the same result for the same plain text.
CBC mode is the way to go and don't forget a random initialization vector. This vector has to be communicated with the cipher text and can be sent in the clear.
Regarding your data, since AES is a block cipher, the outcome is always a multiple of the block size. If you don't want to let the observer know if your data is short or long, add some padding to extend it up to the maximum expected size.
If you want to encrypt and decrypt data within an application, you most likely want to use a symmetric key cipher. AES, which is the symmetric block encryption algorithm certified by the NSA for securing top secret data, is your best choice. There is a pure-PHP implementation available at www.phpaes.com
For your use it sounds like AES128 is sufficient. You will want to use CBC mode with a random initialization vector, or else the same data will always produce the same ciphertext.
Choosing the right encryption algorithm is a good first step, but there are many factors to a secure system which are hard to get right, such as key management. There are good resources out there, such as Applied Cryptography by Bruce Schneier, and Security Engineering by Ross Anderson (available for free online).
Does it matter if anybody can decrypt it? If you're just trying to obfuscate it a little, use ROT13. It's old school.
Any one-way encryption algorithm such as Blowfish will do, I guess. Blowfish is fast and open. You can use Blowfish through the crypt() function. AFAIK there are no encryption algorithm that work especially well on small strings. One thing to be aware of though is that brute-forcing such small strings will be very easy. Maybe you should encrypt the string along with a 'secret' salt value for additional security.
You can use the general programming ideas without relying in built in encryption/decription functions Example create a function call it
function encryptstring($string) {
$string_length=strlen($string);
$encrychars="";
/**
*For each character of the given string generate the code
*/
for ($position = 0;$position<$string_length;$position++){
$key = (($string_length+$position)+1);
$key = (255+$key) % 255;
$get_char_to_be_encrypted = SUBSTR($string, $position, 1);
$ascii_char = ORD($get_char_to_be_encrypted);
$xored_char = $ascii_char ^ $key; //xor operation
$encrypted_char = CHR($xored_char);
$encrychars .= $encrypted_char;
}
/**
*Return the encrypted/decrypted string
*/
return $encrychars;
}
On the page with link to include the id's required to be encrypted
/**
*While passing the unique value to a link
*Do the following steps
*/
$id=57;//or if you are fetching it automatically just pass it here
/**
*For more security multiply some value
*You can set the multiplication value in config file
*/
$passstring=$id*346244;
$encrypted_string=encryptstring($passstring);
$param=urlencode($encrypted_string);
/**
*Derive the url for the link
*/
echo 'something' ;
On the target file that get opened after the link is clicked
/**
*Retriving the value in the target file
*Do the following steps
*/
$fetchid=$_GET['aZ98#9A_KL'];
$passstring=urldecode(stripslashes($fetchid));
$decrypted_string= encryptstring($passstring);
/**
*Divide the decrypted value with the same value we used for the multiplication
*/
$actual_id= $decrypted_string/346244;

Categories