1、PHP 8.4 新特性 - Sodium:支持 AEGIS-128L 和 AEGIS-256

作者: 温新

图书: 【PHP 8.4 新特性】

阅读: 212

时间: 2025-01-18 01:29:32

PHP 8.4 引入了对 AEGIS-128LAEGIS-256 的支持,这两种加密算法是 Sodium 扩展(即 libsodium)中的新功能。它们是高效的 AEAD(Authenticated Encryption with Associated Data)加密模式,提供了强大的性能和安全性,适合对敏感数据进行快速加密和验证。

AEGIS 是一种基于 AES 的认证加密算法家族,其速度比 AES-GCM 更快。PHP 8.4 中的 Sodium 扩展在使用 libsodium 1.0.19 或更高版本编译时支持 AEGIS-128L 和 AEGIS256 加密算法。

PHP 8.4 中的 Sodium 扩展通过 PHP 函数支持 AEGIS-128L 和 AEGIS256,这些函数遵循 _keygen_encrypt_decrypt 的模式,与现有的 aes256gcm、chacha20poly1305、chacha20poly1305_ietf 和 xchacha20poly1305 加密算法的模式一致。这些算法均为带附加数据认证加密(AEAD)算法。

1、新函数和 PHP 常量

PHP 8.4 中的 Sodium 扩展为 AEGIS-128L 和 AEGIS-256 AEAD 算法新增了 6 个 PHP 函数和 4 个 PHP 常量。

1.1、AEGIS-128L 函数和常量

AEGIS-128L 是一种 AEAD 算法,它使用 128 位密钥和 128 位随机数(nonce),可以加密/解密长度小于 2*64 位的数据。

函数

  • sodium_crypto_aead_aegis128l_keygen 函数

    为 AEGIS-128L 生成并返回指定长度(SODIUM_CRYPTO_AEAD_AEGIS128L_KEYBYTES)的加密安全随机密钥。

  • sodium_crypto_aead_aegis128l_encrypt 函数

    使用 AEGIS-128L 算法对明文数据进行加密并认证。

  • sodium_crypto_aead_aegis128l_decrypt 函数

    使用 AEGIS-128L 算法对加密数据进行验证后解密。

函数原型如下:

sodium_crypto_aead_aegis128l_keygen
/**
 * 生成一个随机的 AEGIS-128L 密钥
 * 
 * @return string
 */
function sodium_crypto_aead_aegis128l_keygen(): string {  
}
sodium_crypto_aead_aegis128l_encrypt
/**
 * 使用 AEGIS-128L 加密后进行认证
 *
 * @param string $message 要加密的明文消息
 * @param string $additional_data 额外的认证数据。这些数据用于验证附加到密文后的认证标签,但不会被加密或存储在密文中
 * @param string $nonce 一个必须仅对每条消息使用一次的数字。长度为16字节
 * @param string $key 加密密钥(128位)
 *
 * @return string 
 */
function sodium_crypto_aead_aegis128l_encrypt(string $message, string $additional_data, string $nonce, string $key): string {
}
sodium_crypto_aead_aegis128l_decrypt
/**
 * 验证并解密一条由 sodium_crypto_aead_aegis128l_encrypt() 函数加密的消息
 *
 * @param string $message 由 sodium_crypto_aead_aegis128l_encrypt() 函数创建的加密消息
 * @param string $additional_data 额外的认证数据。这些数据用于验证附加到密文后的认证标签,但不会被加密或存储在密文中。这必须与加密明文消息时传递的值相同
 * @param string $nonce 一个必须仅对每条消息使用一次的数字。长度为16字节。这必须与加密明文消息时传递的nonce值相同
 * @param string $key 加密密钥(128位)
 *
 * @return string 
 */
function sodium_crypto_aead_aegis128l_decrypt(string $message, string $additional_data, string $nonce, string $key): string {
}

常量

  • SODIUM_CRYPTO_AEAD_AEGIS128L_KEYBYTES 常量:指定 AEGIS-128L 算法使用的密钥长度(字节数),值为 16

  • SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES 常量:指定 AEGIS-128L 算法使用的随机数(nonce)长度(字节数),值为 16

  • SODIUM_CRYPTO_AEAD_AEGIS128L_NSECBYTES 常量:值为 0

  • SODIUM_CRYPTO_AEAD_AEGIS128L_ABYTES 常量:值为 32

1.2、AEGIS-256 函数和常量

函数

  • sodium_crypto_aead_aegis256_keygen 函数

    为 AEGIS-256 生成并返回指定长度(SODIUM_CRYPTO_AEAD_AEGIS256_KEYBYTES)的加密安全随机密钥。

  • sodium_crypto_aead_aegis256_encrypt 函数

    使用 AEGIS-256 算法对明文数据进行加密并认证。

  • sodium_crypto_aead_aegis256_decrypt 函数

    使用 AEGIS-256 算法对加密数据进行验证后解密。

sodium_crypto_aead_aegis256_keygen
/**
 * 生成一个随机的 AEGIS-256 密钥
 *
 * @return string
 */
function sodium_crypto_aead_aegis256_keygen(): string {  
}
sodium_crypto_aead_aegis256_encrypt
/**
 * 使用 AEGIS-256 加密并认证
 *
 * @param string $message 要加密的明文消息
 * @param string $additional_data 额外的认证数据。这些数据用于验证附加到密文后的认证标签,但不会被加密或存储在密文中
 * @param string $nonce 一个必须仅对每条消息使用一次的数字。长度为32字节
 * @param string $key 加密密钥(256位)
 *
 * @return string
 */
function sodium_crypto_aead_aegis256_encrypt(string $message, string $additional_data, string $nonce, string $key): string {
}
sodium_crypto_aead_aegis256_decrypt
/**
 * 验证并解密一条由 sodium_crypto_aead_aegis256_encrypt() 函数加密的消息
 *
 * @param string $ciphertext 由 sodium_crypto_aead_aegis256_encrypt() 函数创建的加密消息
 * @param string $additional_data 额外的认证数据。这些数据用于验证附加到密文后的认证标签,但不会被加密或存储在密文中。这必须与加密明文消息时传递的值相同
 * @param string $nonce 一个必须仅对每条消息使用一次的数字。长度为32字节。这必须与加密明文消息时传递的nonce值相同
 * @param string $key 加密密钥(256位)
 *
 * @return string|false 
 */
function sodium_crypto_aead_aegis256_decrypt(string $ciphertext, string $additional_data, string $nonce, string $key): string|false {
}

常量

  • SODIUM_CRYPTO_AEAD_AEGIS256_KEYBYTES 常量:指定 AEGIS-256 算法使用的密钥长度(字节数),值为 32
  • SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES 常量:指定 AEGIS-256 算法使用的随机数(nonce)长度(字节数),值为 32
  • SODIUM_CRYPTO_AEAD_AEGIS256_NSECBYTES 常量:值为 0
  • SODIUM_CRYPTO_AEAD_AEGIS256_ABYTES 常量:值为 32

2、检查 AEGIS-128L 和 AEGIS-256 可用性

没有专门的函数类似于 sodium_crypto_aead_aes256gcm_is_available 来返回 AEGIS-128L 和 AEGIS-256 AEAD 算法是否可用。

注意:

新的函数和常量只有在满足所有要求时才会声明。**这些要求包括 x86_64 或 aarch64 CPU、PHP 8.4 以及 Sodium 扩展必须编译有 libsodium 1.0.19 或更高版本。**检查其中一个新函数的存在性可以作为这些算法可用性的检查:

if (function_exists('sodium_crypto_aead_aegis256_encrypt')) {
    // AEGIS-128L 和 AEGIS-256 可用。
    echo '可用';
} else {
    // AEGIS-128L 和 AEGIS-256 不可用。
    echo '不可用';
}

现在查看一个 libsodium 版本:

sodium support enabled
libsodium headers version 1.0.18
libsodium library version 1.0.18

我的版本是 1.0.18,因此这个代码会输出不可用。要想使用这些函数,就必须要升级 libsodium 扩展到 1.0.19 或更高版本。

3、案例

sodium support enabled
sodium compiled version 2.0.22
libsodium headers version 1.0.20
libsodium library version 1.0.20

使用 AEGIS-128L 进行加密和解密

<?php
// 密钥 (必须是 16 字节,适合 AEGIS-128L)
$key = random_bytes(SODIUM_CRYPTO_AEAD_AEGIS128L_KEYBYTES);

// Nonce (随机数,必须是 16 字节)
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES);

// 要加密的消息
$message = "这是需要加密的敏感数据。";

// 关联数据(可选,用于完整性校验,不会加密)
$associated_data = "元数据";

// 加密消息
$encrypted = sodium_crypto_aead_aegis128l_encrypt($message, $associated_data, $nonce, $key);

echo "加密后的数据: " . bin2hex($encrypted) . PHP_EOL;

// 解密消息
$decrypted = sodium_crypto_aead_aegis128l_decrypt($encrypted, $associated_data, $nonce, $key);

if ($decrypted === false) {
    echo "解密失败,可能密钥或 nonce 不匹配。" . PHP_EOL;
} else {
    echo "解密成功,消息为: " . $decrypted . PHP_EOL;
}

密钥和 Nonce

  • 密钥和 Nonce 的大小固定,分别为 16 字节。
  • Nonce 必须唯一,以防止重复攻击。

关联数据

  • 关联数据是加密过程中不加密但需要认证的部分。
  • 常用于存储元信息(如消息头、时间戳)。

加密与解密

  • 加密后返回的是加密数据。
  • 解密时,如果关联数据或 Nonce 不匹配,会返回 false

AEGIS-256 的用法

如果需要更高安全性,使用 AEGIS-256 加密

<?php
// 密钥 (必须是 32 字节,适合 AEGIS-256)
$key = random_bytes(SODIUM_CRYPTO_AEAD_AEGIS256_KEYBYTES);

// Nonce (必须是 32 字节)
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES);

// 加密消息
$encrypted = sodium_crypto_aead_aegis256_encrypt($message, $associated_data, $nonce, $key);

// 解密消息
$decrypted = sodium_crypto_aead_aegis256_decrypt($encrypted, $associated_data, $nonce, $key);

适用场景

  • 敏感数据加密:如支付信息、登录凭证等。
  • 高性能需求:特别是对速度和认证有要求的应用场景。
  • 替代传统 AEAD 算法:如 GCM 或 Chacha20-Poly1305。

4、向后兼容性影响

AEGIS-128L 和 AEGIS-256 算法作为新的函数和常量被添加到 PHP 8.4 的 Sodium 扩展中。

sodium_compat 项目提供了 Sodium 扩展的用户空间 PHP 多填充。该项目有一个开放的问题,旨在添加对 AEGIS-128L 和 AEGIS-256 的支持,尽管在这方面还没有进行任何工作

请登录后再评论