为何该Base64字符串可被base64_decode解码却无法被sodium_base642bin处理?
问题:
sodium_base642bin解码Base64字符串失败,而base64_decode正常工作 我的代码:
<?php $a = 'MIIFzzCCBLegAwIBAgIDAfdlMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYDVQQDDBtDT1BFIFNaQUZJUiAtIEt3YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdwaXN1OiA2MB4XDTExMTEwOTA2MDAwMFoXDTEzMTEwOTA2MDAwMFowgdkxCzAJBgNVBAYTAlBMMRwwGgYDVQQKDBNVcnrEhWQgTWlhc3RhIEdkeW5pMRswGQYDVQQFExJQRVNFTDogNjEwNjA2MDMxMTgxGTAXBgNVBAMMEEplcnp5IFByemV3b3Jza2kxTzBNBgNVBBAwRgwiQWwuIE1hcnN6YcWCa2EgUGnFgnN1ZHNraWVnbyA1Mi81NAwNODEtMzgyIEdkeW5pYQwGUG9sc2thDAlwb21vcnNraWUxDjAMBgNVBCoMBUplcnp5MRMwEQYDVQQEDApQcnpld29yc2tpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMm5vjGqHPthJCMqKpqssSISRos0PYDTcEQzyyurfX67EJWKtZj6HNwuDMEGJ02iBNZfjUl7r8dIi28bSKhNlsfycXZKYRcIjp0+r5RqtR2auo9GQ6veKb61DEAGIqaR+uLLcJVTHCu0w9oXLGbRlGth5eNoj03CxXVAH2IfhbNwIDAQABo4IChzCCAoMwDAYDVR0TAQH/BAIwADCCAUgGA1UdIAEB/wSCATwwggE4MIIBNAYJKoRoAYb3IwEBMIIBJTCB3QYIKwYBBQUHAgIwgdAMgc1EZWtsYXJhY2phIHRhIGplc3Qgb8Wbd2lhZGN6ZW5pZW0gd3lkYXdjeSwgxbxlIHRlbiBjZXJ0eWZpa2F0IHpvc3RhxYIgd3lkYW55IGpha28gY2VydHlmaWthdCBrd2FsaWZpa293YW55IHpnb2RuaWUgeiB3eW1hZ2FuaWFtaSB1c3Rhd3kgbyBwb2RwaXNpZSBlbGVrdHJvbmljem55bSBvcmF6IHRvd2FyenlzesSFY3ltaSBqZWogcm96cG9yesSFZHplbmlhbWkuMEMGCCsGAQUFBwIBFjdodHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN6eS9wb2xpdHlrYS5odG1sMAkGA1UdCQQCMAAwIQYDVR0RBBowGIEWai5wcnpld29yc2tpQGdkeW5pYS5wbDAOBgNVHQ8BAf8EBAMCBkAwgZ4GA1UdIwSBljCBk4AU3TGldJXipN4oGS3ZYmnBDMFs8gKhd6R1MHMxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYDVQQDDBtDT1BFIFNaQUZJUiAtIEt3YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdwaXN1OiA2ggJb9jBIBgNVHR8EQTA/MD2gO6A5hjdodHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN6eS9DUkxfT1pLMzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQBYPIqnAreyeql7/opJjcar/qWZy9ruhB2q0lZFsJOhwgMnbQXzp/4vv93YJqcHGAXdHP6EO8FQX47mjo2ZKQmi+cIHJHLONdX/3Im+M17V0iNAh7Z1lOSfTRT+iiwe/F8phcEaD5q2RmvYusR7zXZq/cLL0If0hXoPZ/EHQxjN8pxzxiUx6bJAgturnIMEfRNesxwghdr1dkUjOhGLf3kHVzgM6j3VAM7oFmMUb5y5s96Bzl10DodWitjOEH0vvnIcsppSxH1C1dCAi0o9f/1y2XuLNhBNHMAyTqpYPX8Yvav1c+Z50OMaSXHAnTa20zv8UtiHbaAhwlifCelUMj93S'; echo strlen(base64_decode($a)) . " "; echo strlen(sodium_base642bin($a, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING));
base64_decode可以正常解码该字符串,但sodium_base642bin无论使用哪个$id参数(SODIUM_BASE64_VARIANT_ORIGINAL、SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING、SODIUM_BASE64_VARIANT_URLSAFE和SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING)均解码失败,抛出异常:
Fatal error: Uncaught SodiumException: sodium_base642bin(): Argument #1 ($string) must be a valid base64 string
解决思路
核心原因是两个函数的校验严格程度不同:
base64_decode是宽松模式:会自动忽略非Base64字符(换行、空格等),对长度不符合4倍数的字符串也会尝试补全解码。sodium_base642bin是严格模式:要求输入完全符合指定Base64变体的规范,包括字符合法性、长度匹配。
1. 清理输入字符串
首先移除所有非目标Base64变体允许的字符:
- 标准Original变体(
+、/、=):保留A-Za-z0-9+/=,过滤其他字符 - URL-safe变体(
-、_):保留A-Za-z0-9-_=,过滤其他字符
示例代码:
// 清理标准Original Base64字符串 $cleaned = preg_replace('/[^A-Za-z0-9+\/=]/', '', $a);
2. 处理Padding与长度规范
Base64编码的长度必须满足:总字符数×6能被8整除(对应原始字节数为整数)。
- 如果字符串包含
=,使用SODIUM_BASE64_VARIANT_ORIGINAL变体 - 如果无
=,先检查长度是否符合规范,若不符合则补=后再用带padding的变体,或直接尝试无padding变体:
$mod = strlen($cleaned) % 4; if ($mod !== 0) { $cleaned .= str_repeat('=', 4 - $mod); $decoded = sodium_base642bin($cleaned, SODIUM_BASE64_VARIANT_ORIGINAL); } else { $decoded = sodium_base642bin($cleaned, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING); }
3. 适配URL-safe Base64
如果字符串是URL-safe格式(用-代替+、_代替/),先转换为标准格式再解码:
$urlSafeCleaned = str_replace(['-', '_'], ['+', '/'], $a); $urlSafeCleaned = preg_replace('/[^A-Za-z0-9+\/=]/', '', $urlSafeCleaned); $decoded = sodium_base642bin($urlSafeCleaned, SODIUM_BASE64_VARIANT_ORIGINAL);
完整示例
<?php $a = '你的长字符串'; // 清理标准Original Base64字符 $cleaned = preg_replace('/[^A-Za-z0-9+\/=]/', '', $a); // 选择对应变体解码 if (str_contains($cleaned, '=')) { $decoded = sodium_base642bin($cleaned, SODIUM_BASE64_VARIANT_ORIGINAL); } else { $mod = strlen($cleaned) % 4; if ($mod !== 0) { $cleaned .= str_repeat('=', 4 - $mod); $decoded = sodium_base642bin($cleaned, SODIUM_BASE64_VARIANT_ORIGINAL); } else { $decoded = sodium_base642bin($cleaned, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING); } } echo strlen($decoded);
内容的提问来源于stack exchange,提问作者neubert
相关产品推荐
相关产品推荐

