paragonie/sodium_compat

libsodium的纯PHP实现;如果存在PHP扩展则使用该扩展


README

Build Status Psalm Status Latest Stable Version Latest Unstable Version License Downloads

Sodium Compat是Sodium密码学库(libsodium)的纯PHP polyfill,这是PHP 7.2.0+的一个核心扩展,在其他情况下在PECL中可用。

如果您已安装PHP扩展,Sodium Compat将有机会透明地使用PHP扩展而不是我们的实现。

主要版本和分支

sodium_compat v1.21.0是master分支的最后一个v1.x版本。从现在开始,所有支持PHP 5.2 - 8.0和32位整数的未来版本将位于v1.x分支

更新的sodium_compat版本(即v2.0.0)将继续存在于master分支中,除非需要新的主要版本。此工作的目标是提高代码可读性和性能,同时减少样板代码。

如有疑问,请参阅master分支中的README文件以获取最新版本信息

我应该使用哪个版本?

如果您需要32位PHP支持(PHP_INT_SIZE == 4),请继续使用sodium_compat v1.x。如果您想提高性能并减小依赖项,请使用v2.x。

我们建议库和框架设置如下Composer版本约束

{
    "require": {
        /* ... */
        "paragonie/sodium_compat": ">= 1"
        /* ... */
    }
}

应用程序应相反地指定对其和其部署有意义的实际版本。

重要!

此加密库尚未由专注于密码学或密码分析的独立第三方正式审计。

如果您在使用sodium_compat之前需要此类审计,并且有进行此类审计的资金,请提交一个问题或联系security at paragonie dot com,以便我们帮助启动这个过程。

然而,sodium_compat已被Joomla!和Magento等知名开源项目采用,例如Joomla!Magento。此外,sodium_compat由专注于安全PHP开发和PHP密码学的Paragon Initiative Enterprises开发,并由许多其他专注于PHP的安全专家非正式审查。

如果您想了解我们为防止sodium_compat成为系统中漏洞来源而采取的防御性安全措施,请阅读加密安全PHP开发

安装Sodium Compat

如果您正在使用Composer

composer require paragonie/sodium_compat

从源安装

如果您不使用Composer,请下载一个发布tarball(应使用我们的GnuPG公钥签名),提取其内容,然后包含我们项目的autoload.php脚本。

<?php
require_once "/path/to/sodium_compat/autoload.php";

PHP存档(Phar)发布

自版本 1.3.0 开始,sodium_compat 发布版本 包含 PHP 归档 (.phar 文件) 及其关联的 GPG 签名。首先,下载这两个文件,并使用我们的 GPG 公钥进行验证,如下所示

# Getting our public key from the keyserver:
gpg --fingerprint 7F52D5C61D1255C731362E826B97A1C2826404DA
if [ $? -ne 0 ]; then
    echo -e "\033[33mDownloading PGP Public Key...\033[0m"
    gpg  --keyserver pgp.mit.edu --recv-keys 7F52D5C61D1255C731362E826B97A1C2826404DA
    # Security <[email protected]>
    gpg --fingerprint 7F52D5C61D1255C731362E826B97A1C2826404DA
    if [ $? -ne 0 ]; then
        echo -e "\033[31mCould not download PGP public key for verification\033[0m"
        exit 1
    fi
fi

# Verifying the PHP Archive
gpg --verify sodium-compat.phar.sig sodium-compat.phar

现在,只需将此 .phar 文件包含到您的应用程序中。

<?php
require_once "/path/to/sodium-compat.phar";

支持

libsodium 的商业支持 可由多个供应商提供。如果您需要在您的项目中使用 sodium_compat 获得帮助,请联系 Paragon Initiative Enterprises

非商业报告将通过 Github issues 进行。我们无法保证免费解决将 sodium_compat 集成到第三方软件中的问题的可用性,但我们将努力修复我们库中的任何错误(安全相关或其他)。

支持合同

如果您的公司在其产品或服务中使用此库,您可能对从 Paragon Initiative Enterprises 购买支持合同 感兴趣。

使用 Sodium Compat

真正的 Polyfill

根据对 libsodium RFC 的第二次投票,PHP 7.2 使用 sodium_* 而不是 \Sodium\*

<?php
require_once "/path/to/sodium_compat/autoload.php";

$alice_kp = sodium_crypto_sign_keypair();
$alice_sk = sodium_crypto_sign_secretkey($alice_kp);
$alice_pk = sodium_crypto_sign_publickey($alice_kp);

$message = 'This is a test message.';
$signature = sodium_crypto_sign_detached($message, $alice_sk);
if (sodium_crypto_sign_verify_detached($signature, $message, $alice_pk)) {
    echo 'OK', PHP_EOL;
} else {
    throw new Exception('Invalid signature');
}

通用 Polyfill

如果您的用户使用 PHP < 5.3,或者您想编写无论 PECL 扩展是否可用都能工作的代码,您将希望使用 ParagonIE_Sodium_Compat 类来满足大部分的 libsodium 需要。

以上示例,适用于通用使用

<?php
require_once "/path/to/sodium_compat/autoload.php";

$alice_kp = ParagonIE_Sodium_Compat::crypto_sign_keypair();
$alice_sk = ParagonIE_Sodium_Compat::crypto_sign_secretkey($alice_kp);
$alice_pk = ParagonIE_Sodium_Compat::crypto_sign_publickey($alice_kp);

$message = 'This is a test message.';
$signature = ParagonIE_Sodium_Compat::crypto_sign_detached($message, $alice_sk);
if (ParagonIE_Sodium_Compat::crypto_sign_verify_detached($signature, $message, $alice_pk)) {
    echo 'OK', PHP_EOL;
} else {
    throw new Exception('Invalid signature');
}

一般情况下:如果您将 sodium_ 替换为 ParagonIE_Sodium_Compat::,任何为 libsodium PHP 扩展编写的现有代码都应无需额外代码更改即可与我们的 polyfill 一起工作。

由于这不需要命名空间,此 API 在 PHP 5.2 上公开的。

自版本 0.7.0 以来,我们有自己的命名空间 API(《ParagonIE\Sodium\*》),以便在 PHP 5.3+ 的软件中使用时能够简化。如果您想使用我们的文件加密功能而无需每次都编写 ParagonIE_Sodium_File,这很有用。它不在 PHP < 5.3 上公开,因此如果您项目支持 PHP < 5.3,请使用下划线方法。

要了解如何使用 Libsodium,请阅读 在 PHP 项目中使用 Libsodium

帮助,Sodium_Compat 很慢!我怎样才能让它变快?

有三种方法可以使它变快

  1. 使用更新版本的 PHP(至少 7.2)。
  2. 从 PECL 安装 libsodium PHP 扩展.
  3. 如果前两种选项对您不可用
    1. 验证您所使用的处理器实际上是否实现了恒定时间乘法 (constant-time multiplication)。Sodium_compat 支持,但它必须牺牲一些速度以实现跨平台的安全性。
    2. 如果您100%确定您的处理器是安全的,您可以将 ParagonIE_Sodium_Compat::$fastMult = true; 设置为真,而不会损害您的加密密钥的安全性。如果您的处理器 不是 安全的,那么您需要决定您想要速度还是安全性,因为您不能两者兼得。

我如何在运行时判断 sodium_compat 会变慢?

自版本 1.8 以来,您可以使用 polyfill_is_fast() 静态方法确定 sodium_compat 在运行时是否会变慢。

<?php
if (ParagonIE_Sodium_Compat::polyfill_is_fast()) {
    // Use libsodium now
    $process->execute();
} else {
    // Defer to a cron job or other sort of asynchronous process
    $process->enqueue();
}

文档

首先,您想阅读 Libsodium 快速参考。它旨在回答,“我应该使用哪个函数来解决 [常见问题]?”

如果快速参考页面中没有找到答案,请查看 在 PHP 项目中使用 Libsodium

最后,官方libsodium文档(为C库编写,不是PHP库)也包含大量您可能觉得有用的见解性技术信息。[官方libsodium文档链接](https://download.libsodium.org/doc/)(rel="nofollow noindex noopener external ugc”)。

API覆盖范围

推荐阅读: [Libsodium 快速参考](https://paragonie.com/blog/2017/06/libsodium-quick-reference-quick-comparison-similar-functions-and-which-one-use)(rel="nofollow noindex noopener external ugc”)

  • 主线NaCl功能
    • crypto_auth()
    • crypto_auth_verify()
    • crypto_box()
    • crypto_box_open()
    • crypto_scalarmult()
    • crypto_secretbox()
    • crypto_secretbox_open()
    • crypto_sign()
    • crypto_sign_open()
  • PECL Libsodium 功能
    • crypto_aead_aegis128l_encrypt()
    • crypto_aead_aegis128l_decrypt()
    • crypto_aead_aegis256_encrypt()
    • crypto_aead_aegis256_decrypt()
    • crypto_aead_aes256gcm_encrypt()
    • crypto_aead_aes256gcm_decrypt()
    • crypto_aead_chacha20poly1305_encrypt()
    • crypto_aead_chacha20poly1305_decrypt()
    • crypto_aead_chacha20poly1305_ietf_encrypt()
    • crypto_aead_chacha20poly1305_ietf_decrypt()
    • crypto_aead_xchacha20poly1305_ietf_encrypt()
    • crypto_aead_xchacha20poly1305_ietf_decrypt()
    • crypto_box_xchacha20poly1305()
    • crypto_box_xchacha20poly1305_open()
    • crypto_box_seal()
    • crypto_box_seal_open()
    • crypto_generichash()
    • crypto_generichash_init()
    • crypto_generichash_update()
    • crypto_generichash_final()
    • crypto_kx()
    • crypto_secretbox_xchacha20poly1305()
    • crypto_secretbox_xchacha20poly1305_open()
    • crypto_shorthash()
    • crypto_sign_detached()
    • crypto_sign_ed25519_pk_to_curve25519()
    • crypto_sign_ed25519_sk_to_curve25519()
    • crypto_sign_verify_detached()
    • 仅限高级用户
      • crypto_core_ristretto255_add()
      • crypto_core_ristretto255_from_hash()
      • crypto_core_ristretto255_is_valid_point()
      • crypto_core_ristretto255_random()
      • crypto_core_ristretto255_scalar_add()
      • crypto_core_ristretto255_scalar_complement()
      • crypto_core_ristretto255_scalar_invert()
      • crypto_core_ristretto255_scalar_mul()
      • crypto_core_ristretto255_scalar_negate()
      • crypto_core_ristretto255_scalar_random()
      • crypto_core_ristretto255_scalar_reduce()
      • crypto_core_ristretto255_scalar_sub()
      • crypto_core_ristretto255_sub()
      • crypto_scalarmult_ristretto255_base()
      • crypto_scalarmult_ristretto255()
      • crypto_stream()
      • crypto_stream_keygen()
      • crypto_stream_xor()
      • crypto_stream_xchacha20()
      • crypto_stream_xchacha20_keygen()
      • crypto_stream_xchacha20_xor()
      • crypto_stream_xchacha20_xor_ic()
    • 其他工具(例如 crypto_*_keypair()
      • add()
      • base642bin()
      • bin2base64()
      • bin2hex()
      • hex2bin()
      • crypto_kdf_derive_from_key()
      • crypto_kx_client_session_keys()
      • crypto_kx_server_session_keys()
      • crypto_secretstream_xchacha20poly1305_init_push()
      • crypto_secretstream_xchacha20poly1305_push()
      • crypto_secretstream_xchacha20poly1305_init_pull()
      • crypto_secretstream_xchacha20poly1305_pull()
      • crypto_secretstream_xchacha20poly1305_rekey()
      • pad()
      • unpad()

提供的密码学原语

  • X25519 - 在Curve25519上的椭圆曲线Diffie-Hellman
  • Ed25519 - 在Curve25519上的Edwards曲线数字签名算法
  • Xsalsa20 - 扩展nonce Salsa20流密码
  • ChaCha20 - 流密码
  • Xchacha20 - 扩展nonce ChaCha20流密码
  • Poly1305 - 模2^130 - 5的多项式评估消息认证码
  • BLAKE2b - 密码学散列函数
  • SipHash-2-4 - 快速散列,但不是抗碰撞的;理想用于散列表。

此Polyfill排除的功能

  • sodium_memzero() - 尽管我们公开了这个API端点,但我们无法从PHP可靠地清除缓冲区。

    如果您已安装PHP扩展,sodium_compat将使用原生实现来清除提供的字符串。否则,它将抛出 SodiumException

  • sodium_crypto_pwhash() - 将scrypt或Argon2polyfill到PHP并获得合理的性能是不可行的。用户可能会选择降低安全性的参数以避免拒绝服务(DoS)攻击。

    最佳策略是放弃比赛。

    如果已安装ext/sodium或ext/libsodium,则这些API方法将回退到扩展。否则,我们的polyfill库将抛出 SodiumException

    要检测运行时Argon2i的支持,请使用 ParagonIE_Sodium_Compat::crypto_pwhash_is_available(),它返回一个布尔值(TRUEFALSE)。

  • Libsodium的HKDF API(crypto_kdf_hkdf_*())未被包含,因为PHP自身已经具备HMAC功能,且被认为没有必要。

PHPCompatibility规则集

对于使用PHPCompatibility的用户,以及在其CI流程中使用该工具的用户,现在有一个自定义规则集可供使用,可以防止PHPCompatibility对于此存储库中填充的原生PHP功能抛出误报。

您可以在以下位置找到PHPCompatibilityParagonieSodiumCompat规则集的存储库:GitHubPackagist