RSA-openresty、php、分段加密、明文过长
PHP公钥加密:
1 <?php 2 $pubKey = <<<EOF 3 -----BEGIN PUBLIC KEY----- 4 ... 这里是示意... 5 -----END PUBLIC KEY----- 6 EOF; 7 $pubKey = openssl_pkey_get_public($pubKey); 8 $part_len = openssl_pkey_get_details($pubKey)['bits'] / 8 - 11; // 如果明文过长,加密时候需要分段; 因为明文长度必须比 RSA 钥模长(modulus) 短至少11个字节, 也就是 RSA_size(rsa) – 11 9 if (!$pubKey) { 10 echo 'pubKey Error'; 11 exit(0); 12 } 13 $data = <<<EOF 14 码农 15 EOF; 16 17 $a = microtime(true) * 1000; 18 $parts = str_split($data, $part_len); 19 foreach ($parts as $part) { 20 $encrypted_temp = ''; 21 openssl_public_encrypt($part, $encrypted_temp, $pubKey); 22 $encrypted .= $encrypted_temp; 23 } 24 $encrypted = base64_encode($encrypted); 25 $b = microtime(true) * 1000; 26 echo $encrypted; 27 echo $b - $a, PHP_EOL;
Lua(OpenResty)私钥解密:
1 local decrypt = function() 2 local rsa_priv_key = [[ 3 -----BEGIN PRIVATE KEY----- 4 ... 这里是示意... 5 -----END PRIVATE KEY----- 6 ]] 7 8 local encrypted = "密文" 9 encrypted = ngx.decode_base64(encrypted) 10 if not encrypted then 11 return nil, "Base64 decode err" 12 end 13 14 -- lua-resty-rsa https://github.com/spacewander/lua-resty-rsa 15 -- 注意直接opm install spacewander/lua-resty-rsa 有问题 需要github上直接下载然后替换 16 local priv, err = resty_rsa:new({ private_key = rsa_priv_key}) 17 if not priv then 18 return nil, "new rsa err: " .. err 19 end 20 local chunkSize = 2048 / 8; -- 2048 为密钥长度 因为公钥加密后 长度都跟密钥长度一致 21 local decrypted = '' 22 for i = 1, #encrypted, chunkSize do 23 sub_encrypted = encrypted:sub(i, i + chunkSize - 1) 24 decrypted = decrypted .. priv:decrypt(sub_encrypted) 25 end 26 return decrypted, nil 27 end
RSA加密填充方式:
RSA_PKCS1_PADDING, -- RSA_size - 11 必须 比 RSA 钥模长(modulus) 短至少11个字节
如果你的明文不够128字节
加密的时候会在你的明文中随机填充一些数据,所以会导致对同样的明文每次加密后的结果都不一样。
对加密后的密文,服务器使用相同的填充方式都能解密。解密后的明文也就是之前加密的明文。
RSA_SSLV23_PADDING, -- RSA_size - 11 必须 比 RSA 钥模长(modulus) 短至少11个字节
RSA_NO_PADDING, -- RSA_size 可以和RSA钥模长一样长,如果输入的明文过长,必须切割, 然后填充 加密的时候会在你的明文前面,前向填充零。解密后的明文也会包括前面填充的零,这是服务器需要注意把解密后的字段前向填充的
RSA_PKCS1_OAEP_PADDING, -- RSA_size - 42 or RSA_size(rsa) – 41
总结:
- 在不同的padding模式下,使用相同长度的密钥可以加密的数据最大长度不同;
- 在不同密钥长度下,使用相同的padding模式可以加密的数据最大长度也不同;