RSA加解密中必须考虑到的密钥长度、明文长度和密文长度问题。明文长度需要小于密钥长度,而密文长度则等于密钥长度。因此当加密内容长度大于密钥长度时,有效的RSA加解密就需要对内容进行分段。
这是因为,RSA算法本身要求加密内容也就是明文长度m必须0
这样,对于1024长度的密钥。128字节(1024bits)-减去11字节正好是117字节,但对于RSA加密来讲,padding也是参与加密的,所以,依然按照1024bits去理解,但实际的明文只有117字节了。
所以如果要对任意长度的数据进行加密,就需要将数据分段后进行逐一加密,并将结果进行拼接。同样,解码也需要分段解码,并将结果进行拼接。
Php实现
if (! function_exists('url_safe_base64_encode')) {
function url_safe_base64_encode ($data) {
return str_replace(array('+','/', '='),array('-','_', ''), base64_encode($data));
}
}
if (! function_exists('url_safe_base64_decode')) {
function url_safe_base64_decode ($data) {
$base_64 = str_replace(array('-','_'),array('+','/'), $data);
return base64_decode($base_64);
}
}
class XRsa
{
const CHAR_SET = "UTF-8";
const BASE_64_FORMAT = "UrlSafeNoPadding";
const RSA_ALGORITHM_KEY_TYPE = OPENSSL_KEYTYPE_RSA;
const RSA_ALGORITHM_SIGN = OPENSSL_ALGO_SHA256;
protected $public_key;
protected $private_key;
protected $key_len;
public function __construct($pub_key, $pri_key = null)
{
$this->public_key = $pub_key;
$this->private_key = $pri_key;
$pub_id = openssl_get_publickey($this->public_key);
$this->key_len = openssl_pkey_get_details($pub_id)['bits'];
}
/*
* 创建密钥对
*/
public static function createKeys($key_size = 2048)
{
$config = array(
"private_key_bits" => $key_size,
"private_key_type" => self::RSA_ALGORITHM_KEY_TYPE,
);
$res = openssl_pkey_new($config);
openssl_pkey_export($res, $private_key);
$public_key_detail = openssl_pkey_get_details($res);
$public_key = $public_key_detail["key"];
return [
"public_key" => $public_key,
"private_key" => $private_key,
];
}
/*
* 公钥加密
*/
public function publicEncrypt($data)
{
$encrypted = '';
$part_len = $this->key_len / 8 - 11;
$parts = str_split($data, $part_len);
foreach ($parts as $part) {
$encrypted_temp = '';
openssl_public_encrypt($part, $encrypted_temp, $this->public_key);
$encrypted .= $encrypted_temp;
}
return url_safe_base64_encode($encrypted);
}
/*
* 私钥解密
*/
public function privateDecrypt($encrypted)
{
$decrypted = "";
$part_len = $this->key_len / 8;
$base64_decoded = url_safe_base64_decode($encrypted);
$parts = str_split($base64_decoded, $part_len);
foreach ($parts as $part) {
$decrypted_temp = '';
openssl_private_decrypt($part, $decrypted_temp,$this->private_key);
$decrypted .= $decrypted_temp;
}
return $decrypted;
}
/*
* 私钥