phpseclib3使用RSA加密大体积JSON内容触发LengthException如何解决
RSA加密长内容报错解决方案
你遇到的
LengthException: Message too long报错核心原因是RSA作为非对称加密算法,本身不支持加密超过密钥长度限制的长明文。2048位RSA密钥使用默认OAEP填充时,最大可加密明文长度仅为214字节左右,远低于你2500+字符的JSON内容体积,单纯提升密钥长度会导致加密/解密性能指数级下降,且依然无法覆盖无限长度的动态内容。
推荐方案:混合加密(行业标准实现)
混合加密结合了非对称加密(RSA)的密钥交换安全性,和对称加密(AES)加密长内容的高性能,是当前处理长内容加密的通用方案,逻辑如下:
- 生成随机AES对称密钥,用于加密实际的长JSON内容
- 用RSA公钥加密这个AES密钥(AES密钥长度固定,比如256位即32字节,远低于RSA加密长度限制)
- 最终输出内容由RSA加密后的AES密钥 + AES加密后的JSON密文 + AES解密必需的iv、认证标签组成,解密时反向操作即可
加密端实现代码
<?php require_once './vendor/autoload.php'; use phpseclib3\Crypt\RSA; use phpseclib3\Crypt\AES; // 加载RSA公钥 $publicKey = RSA::load("<RSAKeyValue><Modulus>wb4VVQwvfEtXlD3MKQF9320ltOS6/IbSXntFt8rcKiO/1xfO7a8wDFqMny57Xpokq+ROMXapCkAUictZf0e4cmXHaEwSbdUIeDxvYU4eSuhTAR9kaV3jilmheFyyAhfvkF0goz1YY/ulU/ATNXXqrTSa+bLTdwjyUI+naxyx+w9Y52vMHe52ZUv6JnVIjER0NBLQO9nvEHXJizHrWqErubdXN9DDvRygtuyrW4GEV0CHjayckl7YIhtY0LuYDd3d9qMn4ZzBpBOfPNP2cMhfw4Lc/hd3WrkjCAb7FDPQmW4LynEskoBsdRZsx/NhDMDqUPuyi5IQcEqXxid8C7D0AQ==</Modulus><Exponent>AQAB</Exponent><P>+2vVwjUKJKgqLFSbWzlv7yHoz6PSoZZuBbAuP1fkjVdDartNcGEa/vblG3OSMciJEJ7Uxf2u+U6WtwIDZPJoiMVtTSSfwNv0SjLQzumngdfB46z/o2ZsQBcYeko+G51bawxfjJH0MtqNPMzB1okGDNqg+ANKEvuWHI5Zoo+CtXc=</P><Q>xUVXVd+TGzSlxUVBzUa9maTz2k+opuzA/7sFnUUu2JuSgDw11r4hEINhUEZDKJPgCwiP51ujbHFenv86vreBc4zoGp8tcf5Qe4uD0i/7o9KwqUJrHLxzH7tQTykh2V6R+/IcmL7jMND3XuACjalPit+TFAH+qvt4A70C0YG8YEc=</Q><DP>EJiPpaAmqUDId+Cl2KGz987/NSWVM8FgRdPZWakNlx7ZfmQaun5Ob+IQQX2hetPH6GbzmJYkRKShYjcpzjIKIG0Xx+3Q9cQPHg64pc/alMGPNN4oibqrDpf3r6rS6rO6YxiP/hFsUycGB6tkaCrnUVXlJjnhW9trjzr+Q7LBaAU=</DP><DQ>gpnRpCyMO6qzRNMBKWH4DExElPe/9CMx8xxiLyiqRwVYDEXQbwcY5NHWD0s1Exwza5qTitwEabr0pdbbkX/z2AglcdqIP7valLBc6T6THnZSNvyd5TxuC0f7dy0IF9ygUWiMviNCTgNKgilUB21cF9jEiq53Z8NsRS1RPFrj1+k=</DQ><InverseQ>QBnUSbXBRzjejeCXc8D4RFym576G9mFyQKXEoCUKL8+keAJN/8zD9wX99I1lt8OsLIgr1ToNT8AuA0D3PsO3nxlbq70MF0bjoDqoN2mM4mQmcjsS78rdwiHaXfj6XZYdGuJ6r6dfiBAUqWKfrQL8FRqdsQhtMmELEKs0lNOYrMk=</InverseQ><D>BGAOi0UjLWNmLurWWXa3KPyGBXfE4T8KMSgHgwcJwcnc4zaeba+vHhhNZKrgDlrcyST2vxc26gxYamQ1OTKdb7fssOZG5EQTVOPIgCILfRWSCkxzMA32vYEYrGcrffCccF4qBoW0IU3lhee+B08KZa7ycQEg1WdWUYts9HZJbqn37gGsfyleWeazKrmkv6Ek3+qBItFAYaBffXl3S8CP3tXoY+tcDRStMvluJnCE4i1LOoAVXuxxCNZi6dyjbD5tshAvbnzpdJU/RCQMAVPN5BMCO9KasKAyUFuqMz+VjhEBp7l42HrAwAyS9FIzU5to2g7YK+AsBKDg8dzz6Sv5IQ==</D></RSAKeyValue>"); // 1. 生成AES-256-GCM加密实例 $aes = new AES('gcm'); $aesKey = random_bytes(32); // 256位随机AES密钥 $iv = random_bytes($aes->getBlockLength() >> 3); // 随机IV $aes->setKey($aesKey); $aes->setIV($iv); // 2. 加密JSON内容 $jsonContent = json_encode($array); $aesCiphertext = $aes->encrypt($jsonContent); $tag = $aes->getTag(); // GCM模式认证标签,解密必需 // 3. 用RSA公钥加密AES密钥 $encryptedAesKey = $publicKey->encrypt($aesKey); // 4. 打包所有内容,转base64方便传输/存储,可按实际需求调整分隔符 $finalCiphertext = base64_encode(json_encode([ 'encrypted_aes_key' => base64_encode($encryptedAesKey), 'iv' => base64_encode($iv), 'tag' => base64_encode($tag), 'ciphertext' => base64_encode($aesCiphertext) ]));
解密端实现代码
<?php require_once './vendor/autoload.php'; use phpseclib3\Crypt\RSA; use phpseclib3\Crypt\AES; // 加载RSA私钥 $privateKey = RSA::load('你的RSA私钥内容'); // 解包加密内容 $encryptData = json_decode(base64_decode($finalCiphertext), true); $encryptedAesKey = base64_decode($encryptData['encrypted_aes_key']); $iv = base64_decode($encryptData['iv']); $tag = base64_decode($encryptData['tag']); $aesCiphertext = base64_decode($encryptData['ciphertext']); // 1. 用RSA私钥解密得到AES密钥 $aesKey = $privateKey->decrypt($encryptedAesKey); // 2. 用AES密钥解密原始JSON内容 $aes = new AES('gcm'); $aes->setKey($aesKey); $aes->setIV($iv); $aes->setTag($tag); $originalJson = $aes->decrypt($aesCiphertext); $array = json_decode($originalJson, true);
不推荐备选方案:RSA分段加密
如果特殊场景必须仅使用RSA加密,可将明文按RSA最大加密长度拆分后分段加密,解密时分段拼接。但该方案性能远低于混合加密,且安全性更低,仅可作为临时兼容方案使用。
内容的提问来源于stack exchange,提问作者Dominique Altrez
相关产品推荐
相关产品推荐

