Scott Arciszewski

Scott Arciszewski

Contents

PHP RFC: Make Libsodium a Core Extension

Introduction

As we move towards PHP 7.0.0, we must look at the current state of cryptography in PHP. Libmcrypt hasn't been touched in eight years (last release was in 2007), leaving openssl as the only viable option for PHP 5.x and 7.0 users.

Meanwhile, libsodium bindings have been available in PECL for a while now, and has reached stability.

Libsodium is a modern cryptography library that offers authenticated encryption, high-speed elliptic curve cryptography, and much more. Unlike other cryptography standards (which are a potluck of cryptography primitives; i.e. WebCrypto), libsodium is comprised of carefully selected algorithms implemented by security experts to avoid side-channel vulnerabilities.

I maintain the documentation for the PHP extension here.

Proposal

This proposal is to adopt the libsodium extension (as ext/sodium) in the PHP core in PHP 7.2.0.

Currently, the libsodium extension in PECL uses the `Sodium` namespace, which runs contrary to the coding standards. If this RFC adopted into the PHP core, the namespace can be changed to conform to the coding standards (pending the outcome of a secondary vote).

    // In PECL today:
    $key = \Sodium\randombytes_buf(\Sodium\CRYPTO_SECRETBOX_KEYBYTES);
    $nonce = \Sodium\randombytes_buf(\Sodium\CRYPTO_SECRETBOX_NONCEBYTES);
    $message = \Sodium\crypto_secretbox(
        $plaintext,
        $key,
        $nonce
    );
    
    // If the second vote is against the use of a namespace:
    $key = sodium_randombytes_buf(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
    $nonce = sodium_randombytes_buf(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
    $message = sodium_crypto_secretbox(
        $plaintext,
        $key,
        $nonce
    );

Libsodium has a plethora of useful cryptography features:

  • Password hashing and key derivation (sodium_crypto_pwhash_*)
    • Argon2i (the chosen algorithm of the Password Hashing Competition)
    • Scrypt
  • ECDH over Curve25519 (sodium_crypto_box)
  • Authenticated secret key encryption (sodium_crypto_secretbox)
  • Ed25519 digital signatures (sodium_crypto_sign)
  • AEAD Modes
    • ChaCha20-Poly1305
    • AES-256-GCM

Libsodium (like NaCl, from which it was forked) is widely regarded by cryptography and security industry experts for many reasons:

  • No guesswork. The APIs are simple and powerful.
  • Conservative security. Great effort was taken to perform every security-critical operation in constant time.
  • Best-in-class elliptic curve cryptography.

Libsodium API Subset

  • Mainline NaCl Features
    • \Sodium\crypto_auth()
    • \Sodium\crypto_auth_verify()
    • \Sodium\crypto_box()
    • \Sodium\crypto_box_open()
    • \Sodium\crypto_scalarmult()
    • \Sodium\crypto_secretbox()
    • \Sodium\crypto_secretbox_open()
    • \Sodium\crypto_sign()
    • \Sodium\crypto_sign_open()
  • PECL Libsodium Features
    • \Sodium\crypto_aead_chacha20poly1305_encrypt()
    • \Sodium\crypto_aead_chacha20poly1305_decrypt()
    • \Sodium\crypto_aead_chacha20poly1305_ietf_encrypt()
    • \Sodium\crypto_aead_chacha20poly1305_ietf_decrypt()
    • \Sodium\crypto_box_keypair()
    • \Sodium\crypto_box_keypair_from_secretkey_and_publickey()
    • \Sodium\crypto_box_publickey()
    • \Sodium\crypto_box_publickey_from_secretkey()
    • \Sodium\crypto_box_seal()
    • \Sodium\crypto_box_seal_open()
    • \Sodium\crypto_box_secretkey()
    • \Sodium\crypto_generichash()
    • \Sodium\crypto_generichash_init()
    • \Sodium\crypto_generichash_update()
    • \Sodium\crypto_generichash_final()
    • \Sodium\crypto_kx()
    • \Sodium\crypto_pwhash()
    • \Sodium\crypto_pwhash_str()
    • \Sodium\crypto_pwhash_str_verify()
    • \Sodium\crypto_shorthash()
    • \Sodium\crypto_sign_detached()
    • \Sodium\crypto_sign_keypair()
    • \Sodium\crypto_sign_publickey()
    • \Sodium\crypto_sign_publickey_from_secretkey()
    • \Sodium\crypto_sign_secretkey()
    • \Sodium\crypto_sign_verify_detached()
    • \Sodium\crypto_stream()
    • \Sodium\crypto_stream_xor()
    • \Sodium\compare()
    • \Sodium\memzero()
    • \Sodium\increment()

Because crypto_aead_encrypt() will be the CAESAR finalist, we should tentatively commit to adding that one day. https://competitions.cr.yp.to/caesar.html

We don't need crypto_aead_aes256gcm since that's provided by OpenSSL. We only provide ChaCha20-Poly1305 for e.g. Noise protocol integrations.

We don't need scrypt; we have crypto_pwhash() which is Argon2i.

We don't need several other utilities (bin2hex, hex2bin, etc.). Instead, we should make those existing mainline functions cache-timing safe. We MAY decide to add function aliases (e.g. \Sodium\bin2hex() → \bin2hex()) for compatibility with software already written for ext/sodium.

Proposed PHP Version(s)

This RFC targets PHP 7.2.

RFC Impact

I'm not aware of any potential impact that adopting ext/sodium will have on other RFCs.

Future Scope

With libsodium in the PHP core, we may be able to update the Phar extension to support Ed25519 signatures. This will be a great boon for authentic PHP Archive distribution. The current best option, OpenSSL, may provide inadequate security.

New Constants

See the list of all libsodium constants in the reference. In every case, \Sodium\FOO will be transformed to SODIUM_FOO.

\Sodium\CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES	=>	32
\Sodium\CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES	=>	0
\Sodium\CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES	=>	8
\Sodium\CRYPTO_AEAD_CHACHA20POLY1305_ABYTES	=>	16
\Sodium\CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES	=>	32
\Sodium\CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES	=>	0
\Sodium\CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES	=>	12
\Sodium\CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES	=>	16 
\Sodium\CRYPTO_AUTH_BYTES	=>	32
\Sodium\CRYPTO_AUTH_KEYBYTES	=>	32
\Sodium\CRYPTO_BOX_SEALBYTES	=>	16
\Sodium\CRYPTO_BOX_SECRETKEYBYTES	=>	32
\Sodium\CRYPTO_BOX_PUBLICKEYBYTES	=>	32
\Sodium\CRYPTO_BOX_KEYPAIRBYTES	=>	64
\Sodium\CRYPTO_BOX_MACBYTES	=>	16
\Sodium\CRYPTO_BOX_NONCEBYTES	=>	24
\Sodium\CRYPTO_BOX_SEEDBYTES	=>	32
\Sodium\CRYPTO_KX_BYTES	=>	32
\Sodium\CRYPTO_KX_PUBLICKEYBYTES	=>	32
\Sodium\CRYPTO_KX_SECRETKEYBYTES	=>	32
\Sodium\CRYPTO_GENERICHASH_BYTES	=>	32
\Sodium\CRYPTO_GENERICHASH_BYTES_MIN	=>	16
\Sodium\CRYPTO_GENERICHASH_BYTES_MAX	=>	64
\Sodium\CRYPTO_GENERICHASH_KEYBYTES	=>	32
\Sodium\CRYPTO_GENERICHASH_KEYBYTES_MIN	=>	16
\Sodium\CRYPTO_GENERICHASH_KEYBYTES_MAX	=>	64
\Sodium\CRYPTO_PWHASH_SALTBYTES	=>	16
\Sodium\CRYPTO_PWHASH_STRPREFIX	=>	$argon2i$
\Sodium\CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE	=>	4
\Sodium\CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE	=>	33554432
\Sodium\CRYPTO_PWHASH_OPSLIMIT_MODERATE	=>	6
\Sodium\CRYPTO_PWHASH_MEMLIMIT_MODERATE	=>	134217728
\Sodium\CRYPTO_PWHASH_OPSLIMIT_SENSITIVE	=>	8
\Sodium\CRYPTO_PWHASH_MEMLIMIT_SENSITIVE	=>	536870912
\Sodium\CRYPTO_SCALARMULT_BYTES	=>	32
\Sodium\CRYPTO_SCALARMULT_SCALARBYTES	=>	32
\Sodium\CRYPTO_SHORTHASH_BYTES	=>	8
\Sodium\CRYPTO_SHORTHASH_KEYBYTES	=>	16
\Sodium\CRYPTO_SECRETBOX_KEYBYTES	=>	32
\Sodium\CRYPTO_SECRETBOX_MACBYTES	=>	16
\Sodium\CRYPTO_SECRETBOX_NONCEBYTES	=>	24
\Sodium\CRYPTO_SIGN_BYTES	=>	64
\Sodium\CRYPTO_SIGN_SEEDBYTES	=>	32
\Sodium\CRYPTO_SIGN_PUBLICKEYBYTES	=>	32
\Sodium\CRYPTO_SIGN_SECRETKEYBYTES	=>	64
\Sodium\CRYPTO_SIGN_KEYPAIRBYTES	=>	96
\Sodium\CRYPTO_STREAM_KEYBYTES	=>	32
\Sodium\CRYPTO_STREAM_NONCEBYTES	=>	24

Implementation

References

Links to external references, discussions or RFCs:

Votes

An option needs 2/3 votes to win

Libsodium as a Core Extension in PHP 7.2 (100% approved)
User Vote
aharvey Yes
bishop Yes
bwoebi Yes
colinodell Yes
daverandom Yes
derick Yes
dm Yes
eliw Yes
galvao Yes
gooh Yes
guilhermeblanco Yes
jedisct1 Yes
joey Yes
jpauli Yes
krakjoe Yes
lcobucci Yes
leigh Yes
mbeccati Yes
mike Yes
nikic Yes
ocramius Yes
omars Yes
pmjones Yes
pollita Yes
ramsey Yes
rdohms Yes
remi Yes
salathe Yes
sammyk Yes
sebastian Yes
stas Yes
svpernova09 Yes
tpunt Yes
trowski Yes
yohgaki Yes
yunosh Yes
zeev Yes
Use the current PECL syntax? (100% approved)
User Vote
aharvey Yes, \Sodium\foo
ajf Yes, \Sodium\foo
bishop No, sodium_foo
bwoebi No, sodium_foo
danack No, sodium_foo
daverandom Yes, \Sodium\foo
derick No, sodium_foo
dm Yes, \Sodium\foo
eliw No, sodium_foo
galvao Yes, \Sodium\foo
guilhermeblanco Yes, \Sodium\foo
jedisct1 Yes, \Sodium\foo
jhdxr No, sodium_foo
joey Yes, \Sodium\foo
jpauli No, sodium_foo
kelunik No, sodium_foo
krakjoe Yes, \Sodium\foo
lcobucci Yes, \Sodium\foo
leigh No, sodium_foo
levim Yes, \Sodium\foo
mbeccati No, sodium_foo
nikic Yes, \Sodium\foo
ocramius Yes, \Sodium\foo
omars No, sodium_foo
pmjones No, sodium_foo
pollita No, sodium_foo
ramsey No, sodium_foo
rdohms No, sodium_foo
remi Yes, \Sodium\foo
salathe No, sodium_foo
sammyk No, sodium_foo
sebastian Yes, \Sodium\foo
stas No, sodium_foo
svpernova09 No, sodium_foo
trowski No, sodium_foo
yohgaki No, sodium_foo
yunosh No, sodium_foo
zeev No, sodium_foo