0

I want to encrypt/secure my phoneNumber column in MySQL so for this purpose I used bcrypt but unable to decrypt this

Here is my code

$password="abcd";
echo $pwd=password_hash($password, PASSWORD_DEFAULT);   //$2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Now I want to dcrypt so I tried with the following code but showing me "invalid password", where I am wrong?

if (password_verify($password, $pwd)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}
Atomzwieback
  • 585
  • 6
  • 18
amit
  • 1
  • 1
  • 18
  • 28
  • The above code works OK - it DOES verify the password as given – Professor Abronsius Jul 16 '20 at 08:17
  • @ProfessorAbronsius: if above code is right then how can we decrypt this and pass the data ? – amit Jul 16 '20 at 08:22
  • 3
    It is not `encryption` as such - it is `hashing` - but you can `hash` the phone number and verify that a supplied phone number is valid but you cannot reverse engineer the hash to return the original phone number. Where is the `BCRYPT` in your code? – Professor Abronsius Jul 16 '20 at 08:25
  • @ProfessorAbronsius: i want to send data (with phone number) so for this purpose what should i do ? which type of encryption/security should use ? – amit Jul 16 '20 at 08:32
  • Does this answer your question? [How do you Encrypt and Decrypt a PHP String?](https://stackoverflow.com/questions/16600708/how-do-you-encrypt-and-decrypt-a-php-string) – M. Eriksson Jul 16 '20 at 08:46
  • Just remember that passwords should _never_ be encrypted, they should _only_ be hashed and _never_ be sent or outputted at all, anywhere. Wanted to point that out since it's a bit confusing when you say it's about phone numbers while your question show us code for passwords. – M. Eriksson Jul 16 '20 at 08:49
  • @MagnusEriksson: understand so for phoneNumber what should i do ? – amit Jul 16 '20 at 08:58
  • Look at the duplicate link or the answer below by @ProfessorAbronsius – M. Eriksson Jul 16 '20 at 08:59
  • I'm voting to close as unclear, because the code shown in the question is the correct solution to a different problem, and your actual requirements aren't really specified. Beware if editing or asking a new question that "how do I do encryption" is probably too broad for this site (it fails the "if you can imagine a whole book..." test on https://stackoverflow.com/help/dont-ask) so you'll need to do some research first and narrow it down to an implementation question. – IMSoP Jul 16 '20 at 10:23
  • You can't decrypt bcrypt hashes. You can only check if a raw plaintext password corresponds with a hash. If you want to decrypt a bcrypt hash you have to bruteforce it which will take a very long time. – erik Jul 16 '20 at 08:26

2 Answers2

0

A very basic encryption class, such as the following, would allow you to encrypt and decrypt data - the encrypted data can be stored in the db or sent via email etc - no promises are made about the levels of security offered however as it was quickly put together.

The longer the pubkey and hashsecret the better...

<?php

    class encryption{
        
        public function __construct(){
            $this->config=array(
                'hashalgo'      =>  'sha256',
                'cipher'        =>  'AES-128-CBC',
                'hashsecret'    =>  'banana womble hippopotamus pomegranate',
                'pubkey'        =>  'CAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
bjCCASIwDQYJKoZIhvcNAQEBBQADggEPA'
            );
        }
        
        private function makehash( $data, $key ){
            return hash_hmac( $this->config['hashalgo'], $data, $key, true );
        }
    
        public function encrypt( $data=false ){
            $conf=(object)$this->config;
            
            if( !empty( $data ) && in_array( $conf->cipher, openssl_get_cipher_methods() ) ){
                
                $ivlen = openssl_cipher_iv_length( $conf->cipher );
                $iv = openssl_random_pseudo_bytes( $ivlen );
                
                $encrypted = openssl_encrypt( $data, $conf->cipher, $conf->pubkey, $options=OPENSSL_RAW_DATA, $iv );
                $hash = $this->makehash( $encrypted, $conf->pubkey );
                
                return base64_encode( $iv . $hash . $encrypted );
            }
            return false;
        }
        
        public function decrypt( $data ){
            $conf=(object)$this->config;
            if( !empty( $data ) && in_array( $conf->cipher, openssl_get_cipher_methods() ) ){
                
                $shalength=32;
                $data = base64_decode( $data );
                $ivlen = openssl_cipher_iv_length( $conf->cipher );
                $iv = substr( $data, 0, $ivlen );
                $hash = substr( $data, $ivlen, $shalength );
                
                $encrypted = substr( $data, $ivlen + $shalength );
                $decrypted = openssl_decrypt( $encrypted, $conf->cipher, $conf->pubkey, $options=OPENSSL_RAW_DATA, $iv );
                
                if( $decrypted && hash_equals( $hash, $this->makehash( $encrypted, $conf->pubkey ) ) ){
                    return $decrypted;
                }
            }
            return false;
        }   
    }
    
    
    
    $obj=new encryption;
    
    
    $password="pocahontas";
    $encrypted=$obj->encrypt( $password );
    $decrypted=$obj->decrypt( $encrypted );
    
    printf('<pre>
    Password: %s
    Encrypted: %s
    Decrypted: %s
    </pre>',$password,$encrypted,$decrypted);

?>

This will output something like:

Password: pocahontas
Encrypted: Hvx3j9lwtEII3pR+m05TYDv+BV0IwLa8dQavGgaeQCJITSCU88AYhZrt+swMYNKOD3VQX6PN0mcA/rDkdwmqGw==
Decrypted: pocahontas

As you can see the original password is encrypted with different values each time but always decodes to the same original password when decrypted.

Professor Abronsius
  • 33,063
  • 5
  • 32
  • 46
0

As stated in other comments the bcrypt-method is good for comparing passwords ("is the password correct?") but not as a source for encryption/decryption.

For a minor security level (saving a telephone number) I believe a combination of a key derivation method (here PBKDF2) and AES in ECB mode is OK for that, because ECB mode is getting unsecure when the data is longer than the block length of 16 bytes (most telephone numbers should fit in this length of 16 :-). If you need a more secure level you should consider to use GCM mode but that would be another question.

My code is simulating an encryption and later decryption within one PHP-class; usually that would be done in separate classes and therefore I'm using "doubled" variable names (e.g. 'salt' and 'saltToDecrypt') and it is using the openssl-library available on almost all modern PHP implementations (I'm using PHP 7.3).

The code is full of echoing to "prove" that the variables on encryption side are the same as on decryption side, they can get commented out in production.

The code does not do ANY error handling (e.g. wrong password given on decryption side) and is for education only.

The result will show the correct decryption and because of the random element in 'salt' each run of the program (with same plaintext and password) gets a different encoded string.

Here is the output:

Encryption with AES ECB mode and PBKDF2 key derivation<br>
plaintext              : 0123-45678-90123<br>
password               : myPassword<br>
salt                   : 2dccc75991638322d6b1954726f969bcbfc86b00e9928a759c0ea9618eedd4f8<br>
hash                   : a86178ca7aebf3cde4b8472ac5825cea<br>
ecbEncrypt             : NWt6Cyi11m7Vzwm1tsRhE6l8S5IH8Ko9HIgYeKg7yFQ=<br>
token                  : Tld0NkN5aTExbTdWendtMXRzUmhFNmw4UzVJSDhLbzlISWdZZUtnN3lGUT06Oi3Mx1mRY4Mi1rGVRyb5aby/yGsA6ZKKdZwOqWGO7dT4<br>

Decryption
passwordToDecrypt      : myPassword<br>
dataToDecrypt          : NWt6Cyi11m7Vzwm1tsRhE6l8S5IH8Ko9HIgYeKg7yFQ=<br>
saltToDecrypt          : 2dccc75991638322d6b1954726f969bcbfc86b00e9928a759c0ea9618eedd4f8<br>
hashToDecrypt          : a86178ca7aebf3cde4b8472ac5825cea<br>
decrypted plaintext    : 0123-45678-90123<br>

Code:

<?php
echo PHP_EOL . "Encryption with AES ECB mode and PBKDF2 key derivation" . '<br>' . PHP_EOL;
// https://stackoverflow.com/questions/62930372/how-to-use-bcrypt-in-mysql-with-php/62931080#62931080

$plaintext = "0123-45678-90123"; // telephone number
$password = "myPassword";
echo "plaintext              : " . $plaintext . '<br>' . PHP_EOL;
echo "password               : " . $password . '<br>' . PHP_EOL;
$iterations = 10000; // better to use higher iterations but this slows down the process (but this is wanted !)

// generate password hash with pbkdf2 and encrypt
$salt = openssl_random_pseudo_bytes(32);
$hash = hash_pbkdf2("sha256", $password, $salt, $iterations, 32);
echo "salt                   : " . bin2hex($salt) . '<br>' . PHP_EOL;
echo "hash                   : " . $hash . '<br>' . PHP_EOL;
$ecbEncrypt = openssl_encrypt($plaintext, "aes-256-ecb", $hash, $options=0);
echo "ecbEncrypt             : " . $ecbEncrypt . '<br>' . PHP_EOL;
$token = base64_encode($ecbEncrypt . '::' . $salt);
echo "token                  : " . $token . '<br>' . PHP_EOL;
// save this token in the database

// load the token from the database and decrypt
echo PHP_EOL . "Decryption" . PHP_EOL;
$passwordToDecrypt = "myPassword";
$iterationsToDecrypt = 10000; // better to use higher iterations but this slows down the process (but this is wanted !)
$tokenLoad = $token;
list($dataToDecrypt, $saltToDecrypt) = explode('::', base64_decode($tokenLoad), 2);
echo "passwordToDecrypt      : " . $passwordToDecrypt . '<br>' . PHP_EOL;
echo "dataToDecrypt          : " . $dataToDecrypt . '<br>' . PHP_EOL;
echo "saltToDecrypt          : " . bin2hex($saltToDecrypt) . '<br>' . PHP_EOL;
$hashToDecrypt = hash_pbkdf2("sha256", $passwordToDecrypt, $saltToDecrypt, $iterationsToDecrypt, 32);
echo "hashToDecrypt          : " . $hashToDecrypt. '<br>' . PHP_EOL;
$ecbDecrypt = openssl_decrypt($dataToDecrypt, "aes-256-ecb", $hashToDecrypt, $options=0);
echo "decrypted plaintext    : " . $ecbDecrypt . '<br>' . PHP_EOL;
?>
Michael Fehr
  • 5,827
  • 2
  • 19
  • 40