benjy
benjy

Reputation: 4716

Two-way encryption in PHP

My application (obviously) uses a unique ID to distinguish records. This UID is passed in URLs (e.g. ./examplepage.php?UID=$example_int), among other things.

While I obviously have server-side validation in place to make sure clients don't access other clients' data, is there a two-way encryption method I can use in PHP to only pass encrypted UIDs (e.g. ./examplepage.php?EUID=$encrypted_int), to further reduce the chance of anyone thinking "hey, what happens if I increment this integer?"

TIA.

Upvotes: 32

Views: 63571

Answers (7)

Yash
Yash

Reputation: 143

In PHP, Encryption and Decryption of a string is possible using one of the Cryptography Extensions called OpenSSL function for encrypt and decrypt.

openssl_encrypt() Function: The openssl_encrypt() function is used to encrypt the data.

Syntax is as follows :

string openssl_encrypt( string $data, string $method, string $key, $options = 0, string $iv, string $tag= NULL, string $aad, int $tag_length = 16 )

Parameters are as follows :

$data: It holds the string or data which need to be encrypted.

$method: The cipher method is adopted using openssl_get_cipher_methods() function.

$key: It holds the encryption key.

$options: It holds the bitwise disjunction of the flags OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING.

$iv: It holds the initialization vector which is not NULL.

$tag: It holds the authentication tag which is passed by reference when using AEAD cipher mode (GCM or CCM).

$aad: It holds the additional authentication data.

$tag_length: It holds the length of the authentication tag. The length of authentication tag lies between 4 to 16 for GCM mode.

Return Value: It returns the encrypted string on success or FALSE on failure.

openssl_decrypt() Function The openssl_decrypt() function is used to decrypt the data.

Syntax is as follows :

string openssl_decrypt( string $data, string $method, string $key, int $options = 0, string $iv, string $tag, string $aad)

Parameters are as follows :

$data: It holds the string or data which need to be encrypted.

$method: The cipher method is adopted using openssl_get_cipher_methods() function.

$key: It holds the encryption key.

$options: It holds the bitwise disjunction of the flags OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING.

$iv: It holds the initialization vector which is not NULL.

$tag: It holds the authentication tag using AEAD cipher mode (GCM or CCM). When authentication fails openssl_decrypt() returns FALSE.

$aad: It holds the additional authentication data.

Return Value: It returns the decrypted string on success or FALSE on failure.

Approach: First declare a string and store it into variable and use openssl_encrypt() function to encrypt the given string and use openssl_decrypt() function to descrypt the given string.

You can find the examples at : https://www.geeksforgeeks.org/how-to-encrypt-and-decrypt-a-php-string/

Upvotes: 0

Scott Arciszewski
Scott Arciszewski

Reputation: 34093

First, encrypting URL parameters is usually a bad idea, and a separate lookup (based on an index CHAR column generated by a CSPRNG) is better for 99.9% of use cases.

With that said: Yes, you can use the OpenSSL extension (don't use mcrypt) to encrypt the data like espradley suggested, however I would caution you to not stop at merely encryption.

Encryption without message authentication is dangerous, especially if you're trusting an end-user with the ciphertext.

The solution, therefore, is to use authenticated encryption, which can be easily accessed with libsodium, available on PECL.

If you cannot for whatever reason install a PECL extension, there are two PHP libraries to choose from: defuse/php-encryption and zend-crypt. They both offer standards compliant authenticated encryption and they're both safe to use (for what it's worth, I frequently perform code audits for cryptography implementations in PHP, I'm not merely some random person on the internet).

Upvotes: 0

espradley
espradley

Reputation: 2148

PHP 5.3 has introduced a new encryption method that is really easy to use: openssl_encrypt and openssl_decrypt. It's not well-documented here, so here's a simple example:

$textToEncrypt = "My super secret information.";
$encryptionMethod = "AES-256-CBC";  // AES is used by the U.S. gov't to encrypt top secret documents.
$secretHash = "25c6c7ff35b9979b151f2136cd13b0ff";

//To encrypt
$encryptedMessage = openssl_encrypt($textToEncrypt, $encryptionMethod, $secretHash);

//To Decrypt
$decryptedMessage = openssl_decrypt($encryptedMessage, $encryptionMethod, $secretHash);

//Result
echo "Encrypted: $encryptedMessage <br>Decrypted: $decryptedMessage";

I chose 256-AES because it's solid and fast. It's been adopted by the U.S. gov't to encrypt top secret documents. It's fast considering machine and software. Here's a list of available encryption methods:

AES-128-CBC, AES-128-CFB, AES-128-CFB1, AES-128-CFB8, AES-128-ECB, AES-128-OFB, AES-192-CBC, AES-192-CFB, AES-192-CFB1, AES-192-CFB8, AES-192-ECB, AES-192-OFB, AES-256-CBC, AES-256-CFB, AES-256-CFB1, AES-256-CFB8, AES-256-ECB, AES-256-OFB, BF-CBC, BF-CFB, BF-ECB, BF-OFB, CAMELLIA-128-CBC, CAMELLIA-128-CFB, CAMELLIA-128-CFB1, CAMELLIA-128-CFB8, CAMELLIA-128-ECB, CAMELLIA-128-OFB, CAMELLIA-192-CBC, CAMELLIA-192-CFB, CAMELLIA-192-CFB1, CAMELLIA-192-CFB8, CAMELLIA-192-ECB, CAMELLIA-192-OFB, CAMELLIA-256-CBC, CAMELLIA-256-CFB, CAMELLIA-256-CFB1, CAMELLIA-256-CFB8, CAMELLIA-256-ECB, CAMELLIA-256-OFB, CAST5-CBC, CAST5-CFB, CAST5-ECB, CAST5-OFB, DES-CBC, DES-CFB, DES-CFB1, DES-CFB8, DES-ECB, DES-EDE, DES-EDE-CBC, DES-EDE-CFB, DES-EDE-OFB, DES-EDE3, DES-EDE3-CBC, DES-EDE3-CFB, DES-EDE3-CFB1, DES-EDE3-CFB8, DES-EDE3-OFB, DES-OFB, DESX-CBC, RC2-40-CBC, RC2-64-CBC, RC2-CBC, RC2-CFB, RC2-ECB, RC2-OFB, RC4, RC4-40, SEED-CBC, SEED-CFB, SEED-ECB, SEED-OFB, aes-128-cbc, aes-128-cfb, aes-128-cfb1, aes-128-cfb8, aes-128-ecb, aes-128-ofb, aes-192-cbc, aes-192-cfb, aes-192-cfb1, aes-192-cfb8, aes-192-ecb, aes-192-ofb, aes-256-cbc, aes-256-cfb, aes-256-cfb1, aes-256-cfb8, aes-256-ecb, aes-256-ofb, bf-cbc, bf-cfb, bf-ecb, bf-ofb, camellia-128-cbc, camellia-128-cfb, camellia-128-cfb1, camellia-128-cfb8, camellia-128-ecb, camellia-128-ofb, camellia-192-cbc, camellia-192-cfb, camellia-192-cfb1, camellia-192-cfb8, camellia-192-ecb, camellia-192-ofb, camellia-256-cbc, camellia-256-cfb, camellia-256-cfb1, camellia-256-cfb8, camellia-256-ecb, camellia-256-ofb, cast5-cbc, cast5-cfb, cast5-ecb, cast5-ofb, des-cbc, des-cfb, des-cfb1, des-cfb8, des-ecb, des-ede, des-ede-cbc, des-ede-cfb, des-ede-ofb, des-ede3, des-ede3-cbc, des-ede3-cfb, des-ede3-cfb1, des-ede3-cfb8, des-ede3-ofb, des-ofb, desx-cbc, rc2-40-cbc, rc2-64-cbc, rc2-cbc, rc2-cfb, rc2-ecb, rc2-ofb, rc4, rc4-40, seed-cbc, seed-cfb, seed-ecb, seed-ofb


IMPORTANT UPDATE!!!

Thanks Hobo and Jorwin for pointing out that in PHP 5.3.3 > there is a new parameter that makes this function a little more secure.

Jorwin referenced this link in his comment, and here is an excerpt that is applicable:

In 5.3.3 they added a new parameter, string $iv (initialization vector) Real parameters are: string openssl_encrypt ( string $data , string $method , string $password, bool $raw_output = false, string $iv )

If $iv is missing, a warning is issued: "Using an empty Initialization Vector (iv) is potentially insecure and not recommended".

If $iv is too short, another warning: "IV passed is only 3 bytes long, cipher expects an IV of precisely 8 bytes, padding with \0"

same IV should be used in openssl_decrypt()

Upvotes: 107

caf
caf

Reputation: 239011

You don't need two-way encryption - encryption is for maintaining secrecy, but what you're really looking for here is authenticity.

HMACs (essentially, keyed hashes) are one way of getting cryptographic authenticity. Accompany the UID with a HMAC of the UID (PHP has a HMAC implementation), using a key that only the server knows. At the start of each request, check the HMAC.

Basically, use the right tool for the right job.

Upvotes: 30

rogeriopvl
rogeriopvl

Reputation: 54056

For two-way encryption check mcrypt, or if you prefer a pure implementation phpseclib.

Upvotes: 2

Miha Hribar
Miha Hribar

Reputation: 5791

While PHP supports many two way hashing algorithms I do not see it being useful in this example. What you need to do is:

  1. Load the row from storage by the provided id
  2. Check that the owner of the row is the authenticated user and if not throw an exception and inform the user not to do that again

But if your heart is set on hashing just pick one of the algorithms provided.

Upvotes: 3

scragar
scragar

Reputation: 6824

Placing a hash next to the ID to ensure it's security, or padding the ID with extra data, or even converting the ID to hex would all work fairly well I think.

Upvotes: -5

Related Questions