Introducción

Sodium is a modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more. Its goal is to provide all of the core operations needed to build higher-level cryptographic tools.

add a note

User Contributed Notes 6 notes

up
62
rafayhingoro at hotmail dot com
7 years ago
<?php //Simple Usage/** * Encrypt a message *  * @param string $message - message to encrypt * @param string $key - encryption key * @return string */function safeEncrypt($message, $key){    $nonce = random_bytes(        SODIUM_CRYPTO_SECRETBOX_NONCEBYTES    );    $cipher = base64_encode(        $nonce.        sodium_crypto_secretbox(            $message,            $nonce,            $key        )    );    sodium_memzero($message);    sodium_memzero($key);    return $cipher;}/** * Decrypt a message *  * @param string $encrypted - message encrypted with safeEncrypt() * @param string $key - encryption key * @return string */function safeDecrypt($encrypted, $key){       $decoded = base64_decode($encrypted);    if ($decoded === false) {        throw new Exception('Scream bloody murder, the encoding failed');    }    if (mb_strlen($decoded, '8bit') < (SODIUM_CRYPTO_SECRETBOX_NONCEBYTES + SODIUM_CRYPTO_SECRETBOX_MACBYTES)) {        throw new Exception('Scream bloody murder, the message was truncated');    }    $nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');    $ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');    $plain = sodium_crypto_secretbox_open(        $ciphertext,        $nonce,        $key    );    if ($plain === false) {         throw new Exception('the message was tampered with in transit');    }    sodium_memzero($ciphertext);    sodium_memzero($key);    return $plain;}//Encrypt & Decrypt your message$key = sodium_crypto_secretbox_keygen();$enc = safeEncrypt('Abdul Rafay Hingoro', $key); //generates random  encrypted string (Base64 related)echo $enc;echo '<br>';$dec = safeDecrypt($enc, $key); //decrypts encoded string generated via safeEncrypt function echo $dec;?>//OutputDEx9ATXEg/eRq8GWD3NT5BatB3m31WEDEYLK2V4L0Am5GZGoa2rvYWUpoUeCrm7W/pdgLJrNoE6AA8U=Abdul Rafay Hingoro
up
3
jedisct1 at php dot net
7 years ago
With sensitive data, use `sodium_bin2base64()` and `sodium_base642bin()` than `base64_encode()` and `base64_decode()`.The sodium functions provide better protection against side channels, are more flexible, and perform stricter validation.
up
7
Anonymous
7 years ago
Clearly there isn't much support or documentation for this yet.  Based off the same safeEncrypt implementation here and elsewhere, I updated it to work for me (I'm running libsodium 1.0.8).I added these methods to a utility class.<?php// simple example$message = 'My ultra-sensitive information';$secret_key = Util::generateSecretKey();$encrypted = Util::encrypt($message, $secret_key, 64);$decrypted = Util::decrypt($encrypted, $secret_key, 64);print $decrypted;// outputs 'My ultra-sensitive information'// encrypted data is padded to 64-byte chunks to obfuscate actual data lengthclass Util{    /**     * Get a secret key for encrypt/decrypt     *     * Use libsodium to generate a secret key.  This should be kept secure.     *     * @return string     * @see encrypt(), decrypt()     */    public static function generateSecretKey()    {        return sodium_crypto_secretbox_keygen();    }    /**     * Encrypt a message     *     * Use libsodium to encrypt a string     *     * @param string $message - message to encrypt     * @param string $secret_key - encryption key     * @param int $block_size - pad the message by $block_size byte chunks to conceal encrypted data size. must match between encrypt/decrypt!     * @return string     * @see decrypt()     * @see https://github.com/jedisct1/libsodium/issues/392     */    public static function encrypt($message, $secret_key, $block_size = 1)    {        // create a nonce for this operation. it will be stored and recovered in the message itself        $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);        // pad to $block_size byte chunks (enforce 512 byte limit)        $padded_message = sodium_pad($message, $block_size <= 512 ? $block_size : 512);        // encrypt message and combine with nonce        $cipher = base64_encode($nonce . sodium_crypto_secretbox($padded_message, $nonce, $secret_key));        // cleanup        sodium_memzero($message);        sodium_memzero($secret_key);        return $cipher;    }    /**     * Decrypt a message     *     * Use libsodium to decrypt an encrypted string     *     * @param string $encrypted - the encrypted message     * @param string $key - encryption key     * @param int $block_size - pad the message by $block_size byte chunks to conceal encrypted data size. must match between encrypt/decrypt!     * @return string     * @see encrypt()     * @see https://github.com/jedisct1/libsodium/issues/392     */    public static function decrypt($encrypted, $secret_key, $block_size = 1)    {        // unpack base64 message        $decoded = base64_decode($encrypted);        // check for general failures        if ($decoded === false) {            throw new \Exception('The encoding failed');        }        // check for incomplete message. CRYPTO_SECRETBOX_MACBYTES doesn't seem to exist in this version...        if (!defined('CRYPTO_SECRETBOX_MACBYTES')) define('CRYPTO_SECRETBOX_MACBYTES', 16);        if (mb_strlen($decoded, '8bit') < (SODIUM_CRYPTO_SECRETBOX_NONCEBYTES + CRYPTO_SECRETBOX_MACBYTES)) {            throw new \Exception('The message was truncated');        }        // pull nonce and ciphertext out of unpacked message        $nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');        $ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');        // decrypt it and account for extra padding from $block_size (enforce 512 byte limit)        $decrypted_padded_message = sodium_crypto_secretbox_open($ciphertext, $nonce, $secret_key);        $message = sodium_unpad($decrypted_padded_message, $block_size <= 512 ? $block_size : 512);        // check for encrpytion failures        if ($message === false) {             throw new \Exception('The message was tampered with in transit');        }        // cleanup        sodium_memzero($ciphertext);        sodium_memzero($secret_key);        return $message;    }}?>
up
2
jedisct1 at php dot net
7 years ago
## Encrypt a single message using a secret keyEncryption:```php$secret_key = sodium_crypto_secretbox_keygen();$message = 'Sensitive information';$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);$encrypted_message = sodium_crypto_secretbox($message, $nonce, $secret_key);```Decryption:```php$decrypted_message = sodium_crypto_secretbox_open($encrypted_message, $nonce, $secret_key);```How it works:`$secret_key` is a secret key. Not a password. It's binary data, notsomething designed to be human readable, but rather to have a keyspace as large as possible for a given length.The `keygen()` function creates such a key. That has to remain secret,as it is used both to encrypt and decrypt data.`$nonce` is a unique value. Like the secret, its length is fixed. Butit doesn't have to be secret, and can be sent along with the encryptedmessage. The nonce doesn't have to be unpredicable either. It just hasto be unique for a given key. With the `secretbox()` API, using`random_bytes()` is a totally fine way to generate nonces.Encrypted messages are slightly larger than unencrypted messages,because they include an authenticator, used by the decryption functionto check that the content was not altered.## Encrypt a single message using a secret key, and hide its lengthEncryption:```php$secret_key = sodium_crypto_secretbox_keygen();$message = 'Sensitive information';$block_size = 16;$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);$padded_message = sodium_pad($padded_message, $block_size);$encrypted_message = sodium_crypto_secretbox($padded_message, $nonce, $secret_key);```Decryption:```php$decrypted_padded_message = sodium_crypto_secretbox_open($encrypted_message, $nonce, $secret_key);$decrypted_message = sodium_unpad($decrypted_padded_message, $block_size);```How it works:Sometimes, the length of a message may provide a lot of informationabout its nature. If a message is one of "yes", "no" and "maybe",encrypting the message doesn't help: knowing the length is enough toknow what the message is.Padding is a technique to mitigate this, by making the length amultiple of a given block size.Messages must be padded prior to encryption, and unpadded afterdecryption.
up
2
jedisct1 at php dot net
7 years ago
## Encrypt a file using a secret key<?php$secret_key = sodium_crypto_secretstream_xchacha20poly1305_keygen();$input_file = '/tmp/example.original';$encrypted_file = '/tmp/example.enc';$chunk_size = 4096;$fd_in = fopen($input_file, 'rb');$fd_out = fopen($encrypted_file, 'wb');list($stream, $header) = sodium_crypto_secretstream_xchacha20poly1305_init_push($secret_key);fwrite($fd_out, $header);$tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE;do {    $chunk = fread($fd_in, $chunk_size);    if (stream_get_meta_data($fd_in)['unread_bytes'] <= 0) {        $tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL;    }    $encrypted_chunk = sodium_crypto_secretstream_xchacha20poly1305_push($stream, $chunk, '', $tag);    fwrite($fd_out, $encrypted_chunk);} while ($tag !== SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL);fclose($fd_out);fclose($fd_in);?>Decrypt the file:<?php$decrypted_file = '/tmp/example.dec';$fd_in = fopen($encrypted_file, 'rb');$fd_out = fopen($decrypted_file, 'wb');$header = fread($fd_in, SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES);$stream = sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, $secret_key);$tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE;while (stream_get_meta_data($fd_in)['unread_bytes'] > 0 &&       $tag !== SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL) {    $chunk = fread($fd_in, $chunk_size + SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES);    list($decrypted_chunk, $tag) = sodium_crypto_secretstream_xchacha20poly1305_pull($stream, $chunk);    fwrite($fd_out, $decrypted_chunk);}$ok = stream_get_meta_data($fd_in)['unread_bytes'] <= 0;fclose($fd_out);fclose($fd_in);if (!$ok) {    die('Invalid/corrupted input');}?>How it works:There's a little bit more code than in the previous examples.In fact, `crypto_secretbox()` would work to encrypt as file, but onlyif that file is pretty small. Since we have to provide the entirecontent as a string, it has to fit in memory.If the file is large, we can split it into small chunks, and encryptchunks individually.By doing do, we can encrypt arbitrary large files. But we need to makesure that chunks cannot be deleted, truncated, duplicated andreordered. In other words, we don't have a single "message", but astream of messages, and during the decryption process, we need a wayto check that the whole stream matches what we encrypted.So we create a new stream (`init_push`) and push a sequence of messagesinto it (`push`). Each individual message has a tag attached to it, bydefault `TAG_MESSAGE`. In order for the decryption process to knowwhere the end of the stream is, we tag the last message with the`TAG_FINAL` tag.When we consume the stream (`init_pull`, then `pull` for eachmessage), we check that they can be properly decrypted, and retrieveboth the decrypted chunks and the attached tags. If we read the lastchunk (`TAG_FINAL`) and we are at the end of the file, we know that wecompletely recovered the original stream.
up
2
jedisct1 at php dot net
7 years ago
You may want to use `feof($fd_in)` instead of `stream_get_meta_data($fd_in)['unread_bytes'] <= 0` in the examples above.Or just read the documentation of the PHP extension here: https://github.com/jedisct1/libsodium-php -- it is always more up to date.
To Top