libsodium in PHP 7

About me

Vinícius Campitelli

Vinícius Campitelli

  • Member of PHPSP, a PHP group based in Sao Paulo
  • PHP Developer at OTTera
  • Cybersecurity enthusiast
  • 10+ years developing with PHP

About me

Cryptography is...

... the practice and study of techniques for secure communication in the presence of third parties called adversaries
... about constructing and analyzing protocols that prevent third parties or the public from reading private messages
Wikipedia

Cryptography is...

Plaintext

Encryption Decryption
Ciphertext 42a14c854f

Symmetric Cryptography

Uses the same key for both encryption and decryption

Also known as Secret-key Cryptography

Symmetric Cryptography


                            public function encrypt($data) {
                                $iv = random_bytes(
                                    openssl_cipher_iv_length('aes-256-ctr')
                                );
                                $ciphertext = openssl_encrypt(
                                    $data,
                                    'aes-256-ctr',         // cipher
                                    '@rw97`b#1,EquJ[L2P2', // key
                                    OPENSSL_RAW_DATA,      // flags
                                    $iv                    // iv (nonce)
                                );
                                return base64_encode(
                                    $iv . $ciphertext
                                );
                            }
                        

Simple symmetric cryptography example using OpenSSL

Symmetric Cryptography


                            public function encrypt($data) {
                                $iv = random_bytes(
                                    openssl_cipher_iv_length('aes-256-gcm')
                                );
                                $ciphertext = openssl_encrypt(
                                    $data,
                                    'aes-256-gcm',         // cipher
                                    '@rw97`b#1,EquJ[L2P2', // key
                                    OPENSSL_RAW_DATA,      // flags
                                    $iv,                   // iv (nonce)
                                    $tag,                  // tag
                                    null,                  // aad
                                    16                     // tag length
                                );
                                return base64_encode(
                                    $iv . $tag . $ciphertext
                                );
                            }
                        

Simple symmetric cryptography example using OpenSSL

Symmetric Cryptography


                            public function decrypt($data) {
                                $data = base64_decode($data);
                                $ivSize = openssl_cipher_iv_length('aes-256-ctr');
                                $iv = substr($data, 0, $ivSize);
                                $data = substr($data, $ivSize);

                                return openssl_decrypt(
                                    $data,
                                    'aes-256-ctr',         // cipher
                                    '@rw97`b#1,EquJ[L2P2', // key
                                    OPENSSL_RAW_DATA,      // flags
                                    $iv                    // iv (nonce)
                                );
                            }
                        

Simple symmetric cryptography example using OpenSSL

Asymmetric Cryptography

 

Public key

Can be distributed to others

Private key

Must remain with the owner

Also known as Public-key Cryptography

Asymmetric Cryptography

If you want others to communicate with you...

Public key

Used by them to write texts to you


Encryption

Private key

Used by you to read those texts


Decryption

Asymmetric Cryptography

If you want to communicate with others...

Public key

Used by them to verify the texts were written by you


Decryption

Private key

Used by you to write texts
 


Encryption

Asymmetric Cryptography


                                public function encrypt(
                                    string $data,
                                    string $publicKeyPath
                                ): string {
                                    $public = openssl_pkey_get_public(
                                        "file://{$publicKeyPath}"
                                    );
                                    if (! openssl_public_encrypt($data, $crypted, $public)) {
                                        throw new \RuntimeException("Can't encrypt data");
                                    }
                                    return $crypted;
                                }
                            

Simple asymmetric cryptography using OpenSSL

Asymmetric Cryptography


                                public function decrypt(
                                    string $data,
                                    string $privateKeyPath,
                                    string $passphrase = null
                                ): string {
                                    $key = openssl_pkey_get_private(
                                        "file://{$privateKeyPath}",
                                        $passphrase
                                    );
                                    if (! openssl_private_decrypt($data, $decrypted, $key)) {
                                        throw new \RuntimeException("Can't decrypt data");
                                    }
                                    return $decrypted;
                                }
                            

Simple asymmetric cryptography using OpenSSL

Asymmetric Cryptography

But I'm sure that instead of omitting that $padding parameter in the previous codes, we always use OPENSSL_PKCS1_OAEP_PADDING, right?

Asymmetric Cryptography

After all, it's pretty obvious that the default OPENSSL_PKCS1_PADDING value uses PKCS#1 v1.5, which is vulnerable to Padding attacks

Asymmetric Cryptography

And it's common knowledge that the RSA algorithm with a 2048 bit key can't handle data blocks larger than 214 bytes

RIGHT?

Hashing

A hash function is any function that can be used to map data of arbitrary size to fixed-size values
Wikipedia

Hashing

But I already know how to use that


                            if (hash('sha512', $_POST['password']) !== $storedPassword) {
                                throw new InvalidCredentialsException();
                            }
                        

Hashing

But do you know about Timing Attacks?

is a side-channel attack in which the attacker attempts to compromise a cryptosystem by analyzing the time taken to execute cryptographic algorithms
Wikipedia

Hashing

And what about Rainbow Tables?

is a precomputed table for caching the output of cryptographic hash functions
Wikipedia

libsodium

Symmetric Cryptography


                            // APP_SECRET_KEY should be
                            // SODIUM_CRYPTO_BOX_SECRETKEYBYTES bytes long

                            // Generates a random nonce
                            $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);

                            $ciphertext = sodium_crypto_secretbox(
                                $plaintext,
                                $nonce,
                                APP_SECRET_KEY
                            );

                            // Prefixing nonce so we can retrieve it when decrypting
                            $ciphertext = sodium_bin2hex($nonce . $ciphertext);
                        
scripts/02-encrypt.php

Symmetric Cryptography


                            $ciphertext = sodium_hex2bin($ciphertext);

                            // Retrieving nonce
                            $nonce = substr(
                                $ciphertext,
                                0,
                                SODIUM_CRYPTO_SECRETBOX_NONCEBYTES
                            );
                            $ciphertext = substr(
                                $ciphertext,
                                SODIUM_CRYPTO_SECRETBOX_NONCEBYTES
                            );

                            // Decrypting
                            $plaintext = sodium_crypto_secretbox_open(
                                $ciphertext,
                                $nonce,
                                APP_SECRET_KEY
                            );
                        
scripts/02-decrypt.php

Authentication


                            // APP_AUTH_KEY should be
                            // SODIUM_CRYPTO_AUTH_KEYBYTES bytes long

                            // Authenticates the specified ciphertext
                            $auth = sodium_bin2hex(
                                sodium_crypto_auth($ciphertext, APP_AUTH_KEY)
                            );
                        
scripts/03-auth.php

Authentication


                            $auth = sodium_hex2bin($auth);

                            // Validates authentication data
                            if (! sodium_crypto_auth_verify(
                                $auth,
                                $ciphertext,
                                APP_AUTH_KEY
                            )) {
                                throw new RuntimeException('Authentication failed');
                            }
                        
scripts/03-checkauth.php

Asymmetric Cryptography


                            // User #1 (Alice)
                            $aliceKeyPair = sodium_crypto_box_keypair();
                            $alicePublic = sodium_crypto_box_publickey($aliceKeyPair);
                            $aliceSecret = sodium_crypto_box_secretkey($aliceKeyPair);

                            // User #2 (Bob)
                            $bobKeyPair = sodium_crypto_box_keypair();
                            $bobPublic = sodium_crypto_box_publickey($bobKeyPair);
                            $bobSecret = sodium_crypto_box_secretkey($bobKeyPair);
                        
scripts/src/SimpleCrypt.php

Asymmetric Cryptography


                            // User #1 (Alice)
                            $nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);

                            $key = sodium_crypto_box_keypair_from_secretkey_and_publickey(
                                $aliceSecret,
                                $bobPublic
                            );

                            $encrypted = sodium_crypto_box($message, $nonce, $key);
                            $ciphertext = $nonce . $encrypted;
                        
scripts/src/SimpleCrypt.php

Asymmetric Cryptography


                            // User #2 (Bob)
                            $nonce = substr($ciphertext, 0, SODIUM_CRYPTO_BOX_NONCEBYTES);
                            $ciphertext = substr($ciphertext, SODIUM_CRYPTO_BOX_NONCEBYTES);

                            $key = sodium_crypto_box_keypair_from_secretkey_and_publickey(
                                $bobSecret,
                                $alicePublic
                            );
                            echo sodium_crypto_box_open($encrypted, $nonce, $key);
                        
scripts/src/SimpleCrypt.php

Storing passwords

sodium_crypto_pwhash_str(
    $password,
    SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
    SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);
// $argon2id$v=19$m=65536,t=2,p=1$20H8uU9EFq7GO2NFPrfDyg$Om/qimxzk9/7mub1s7b ...
scripts/09-pwhash.php

Validating passwords


                            sodium_crypto_pwhash_str_verify(
                            $storedPassword,
                            $inputPassword
                        );
                        
scripts/09-pwhash-verify.php

More examples!

Recap

  • Cryptography is not easy
  • DO NOT use your own algorithms , unless you are a competition-winner cryptologist
  • You CAN use OpenSSL and others libraries (like phpseclib), as long as you know what you're doing (and what they're doing too)
  • To be safe, always use modern and up-to-date solutions

Thanks!