标题:从英特尔迁移到 ARM 架构时解决 Sodium 兼容性问题
简介
在将 PHP 应用程序从基于英特尔的服务器迁移到基于 ARM 的服务器的过程中,Sodium 扩展出现了一个兼容性问题。遇到的具体错误是“Call to undefined function sodium_crypto_aead_aes256gcm_decrypt()”。
本文档概述了问题的发现并提出了使用 OpenSSL 扩展作为替代方案的解决方案。
问题发现
在调查该问题时,发现 sodium_crypto_aead_aes256gcm_is_available() 函数在基于 ARM 的服务器上返回 false,表明在当前环境中不支持 AES-256-GCM 加密和解密。
此兼容性问题归因于 M1 芯片的 ARM 架构,因为 Sodium 扩展可能尚未针对此特定架构进行优化或编译。
解决方案
为了克服兼容性问题并确保加密和解密操作的功能,使用了 OpenSSL 扩展作为替代方案。
原始的基于 Sodium 的代码被修改为利用 OpenSSL 函数进行 AES-256-GCM 加密和解密。
以下代码片段演示了使用 OpenSSL 更新后的 aes256gcm_decrypt() 函数
function aes256gcm_decrypt($secretData, string $keygen, string $nonce)
{
$secretData = preg_replace('/[\r\n\s]/', '', $secretData);
$keygen = preg_replace('/[\r\n\s]/', '', $keygen);
$nonce = preg_replace('/[\r\n\s]/', '', $nonce);
$key = hex2bin($keygen);
$tag = substr($secretData, -32);
$ciphertext = substr($secretData, 0, -32);
try {
$plaintext = openssl_decrypt(
hex2bin($ciphertext),
'aes-256-gcm',
$key,
OPENSSL_RAW_DATA,
hex2bin($nonce),
hex2bin($tag)
);
if ($plaintext === false) {
throw new Exception('解密失败。');
}
return $plaintext;
} catch (Exception $e) {
return $e->getMessage();
}
}
解决方案的关键点
输入数据($secretData、$keygen 和 $nonce)通过使用 preg_replace() 删除换行符和空格来进行清理。
$keygen 使用 hex2bin() 从十六进制字符串转换为二进制格式。
从 $secretData 中提取身份验证标签($tag)和密文($ciphertext)。
openssl_decrypt() 函数用于解密,并使用必要的参数,例如密文、加密算法、密钥、nonce 和标签。
错误处理使用 try-catch 块来捕获和返回在解密过程中可能发生的任何异常。
结论
通过利用 OpenSSL 扩展并相应地修改代码,成功解决了从基于英特尔的服务器迁移到基于 ARM 的服务器时遇到的兼容性问题。
提供的解决方案确保可以在 ARM 架构上无缝地执行 AES-256-GCM 加密和解密操作。