libsodium no PHP 7

Sobre

O que é criptografia?

é a prática e o estudo de técnicas para comunicação segura na presença de terceiros
é a construção e análise de protocolos que previnam terceiros de ler mensagens privadas

O que é criptografia?

Criptografia Simétrica

Utiliza uma mesma chave para criptografar e descriptografar os textos

Criptografia Simétrica

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

Exemplo de criptografia simétrica utilizando OpenSSL

Criptografia Simétrica

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',          // cifra
        '@rw97`b#1,EquJ[L2P2',  // chave
        OPENSSL_RAW_DATA,       // flags
        $iv                     // iv / nonce
    );
}

Exemplo de criptografia simétrica utilizando OpenSSL

Criptografia Assimétrica

  • Chave pública: utilizada para criptografar (escrever)
  • Chave privada: utilizada para descriptografar (ler)

Criptografia Assimétrica

public function encrypt($data, $publicKeyPath) {
    $public = openssl_pkey_get_public("file://{$publicKeyPath}");
    openssl_public_encrypt($data, $crypted, $public);
    return $crypted;
}

Exemplo de criptografia assimétrica utilizando OpenSSL

Criptografia Assimétrica

public function decrypt($data, $privateKeyPath, $passphrase) {
    $key = openssl_pkey_get_private("file://{$privateKeyPath}", $passphrase);
    openssl_private_decrypt($data, $decrypted, $key);
    return $decrypted;
}

Exemplo de criptografia assimétrica utilizando OpenSSL

Tenho certeza que ao invés de omitir o parâmetro $padding nos códigos anteriores, todos usam OPENSSL_PKCS1_OAEP_PADDING, certo?

Afinal, é claro que o parâmetro default (OPENSSL_PKCS1_PADDING) utiliza o padrão PKCS#1 v1.5, que é vulnerável a Padding attacks.

E sabemos que o algoritmo RSA com uma chave de 2048 bits só consegue processar dados de até 214 bytes.

Não é mesmo?

Hashing

é uma função que mapeia dados de tamanho arbitrário para dados de tamanho fixo

Mas eu já sei usar hash!

if (hash('sha512', $_POST['password']) !== $senhaDoBanco) {
    throw new InvalidCredentialsException('Senha não confere!');
}

E você sabe o que é Timing Attack?

ataque que explora operações que não possuem tempo constante

libsodium

Criptografia Simétrica

// Lê a chave
$key = trim(file_get_contents('02-encrypt.key'));

// Gera um nonce
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);

// Prefixa o nonce aos dados para poder ser recuperado pelo decrypt
$ciphertext = sodium_bin2hex(
    $nonce . sodium_crypto_secretbox($plaintext, $nonce, $key)
);
scripts/02-encrypt.php

Criptografia Simétrica

$ciphertext = sodium_hex2bin($ciphertext);

// Lê a chave
$key = trim(file_get_contents('02-encrypt.key'));

// Separa o nonce do texto
$nonce = substr($ciphertext, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$ciphertext = substr($ciphertext, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);

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

Assinatura

// Lê a chave
$key = trim(file_get_contents('03-auth.key'));

// Gera a assinatura para o $ciphertext
$auth = sodium_bin2hex(sodium_crypto_auth($ciphertext, $key));
scripts/03-auth.php

Assinatura - Validando

$auth = sodium_hex2bin($auth);

// Lê a chave
$key = trim(file_get_contents('03-auth.key'));

// Verifica a assinatura
return sodium_crypto_auth_verify($auth, $ciphertext, $key);
scripts/03-checkauth.php

Criptografia Assimétrica

// Cliente 1 - Alice
$aliceKeyPair = sodium_crypto_box_keypair();
$alicePublic = sodium_crypto_box_publickey($aliceKeyPair);
$aliceSecret = sodium_crypto_box_secretkey($aliceKeyPair);

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

Criptografia Assimétrica

// Cliente 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

Criptografia Assimétrica

// Cliente 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

Persistindo senhas

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

Validando senhas

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

Recapitulando...

  • Criptografia não é simples
  • Não invente o seu próprio algoritmo
  • Utilize soluções modernas e atualizadas

Obrigado!