【PHP】RSA长字符串分段加密(117)解密(128)
Q1:为什么RSA对长字符串需分段进⾏加、解密?
RSA对明⽂长度和密⽂长度有限制,如果要加密的明⽂太长则会出错。RSA 1024bit 加密明⽂最⼤长度117字节,解密要求密⽂最⼤长度为128字节,所以在加密和解密的过程中
需要分块进⾏。
Q2:解决办法?
RSA密钥长度1024bit,加密的时候117个字符加密⼀次,然后把所有的密⽂拼接成⼀个密⽂;解密的时候需要128个字符解密⼀下,然后拼接成数据。
Q3:RSA不同的密钥长度,在分段加、解密时,分段字节数是不同的
若RSA密钥长度为M bit,分段加密字节数为(M/8-11),分段解密字节数为(M/8)。
如:
1024bit:分段加密字节数为117,分段解密字节数为128。
2048bit:分段加密字节数为245,分段解密字节数为256。
Demo 1:
private $private_key = "-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDvluFNiF8IrIsddK0OXBAvVBJH11OKvy9er1tRGn9yEJoHCJY3
EU/xz2LasCK8AwgRIqGJbvDBgRa70c3QT9j+wPqNqqJCSoSEKifnDUk1RgUReJT6
iqWaJyfM+WM3aHnKl61RZL4NV5qKe4CHMtaH/JtBCC/JzpuFER1P1IhCtQIDAQAB
AoGAaFYQb68/k4twWbeB1YsKEVJPU7HV08pGWrmKztr3PTk1mnKG2BxV8DwcFJg3
yCCZ1rx6FFuXxOzudYR8WIctO4wdsEbFky/cEGsfc6JJjiktmZaQ7MvobGNwnoFJ
QvRxDd+5uD87JE19iBSgUpLVtXbv+pZxSpD70vitnMdSctECQQD66Z5HsuC8DUPu
OLQHNN4ra5Op179Xlq7LiEFW4GaVgonw24kiLX23c7CK7295Rgxct1fwQKyuU9br
n2uj8toDAkEA9HJ85BWlm2OfUm6VI3Q99rjlpCnhRyz70+sEtf7if1SpctVxNTkX
UOnXlpPTohjAHNhzh9fa1hh/ySH9sRMu5wJAa//8uh3br/YBxFsx2lw+OPBQGe4c
lSXtzPu0LCHg5f/PQhYs28I696jbV6IiGFA3Z/0e4/HiohLCUp9HJMWWYwJACE53
pfyCUyRwfomZccn6bQ7dZtWxfQyvRgU/dLvDkJYc5/UO0sMs4qf/lnNRhrmWlaRZ
UK1qF0pf1ULdbw360wJBAObrYopW2kvIlE09j9SEgNtgVsmfZlf85c4EAZrFJP/T
8nMNKQGo92Gd3HvbjJ+ZBOP1IFt+FDAsXeSLWLAwJrg=
-----END RSA PRIVATE KEY-----";
private $public_key = "-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvluFNiF8IrIsddK0OXBAvVBJH
11OKvy9er1tRGn9yEJoHCJY3EU/xz2LasCK8AwgRIqGJbvDBgRa70c3QT9j+wPqN
qqJCSoSEKifnDUk1RgUReJT6iqWaJyfM+WM3aHnKl61RZL4NV5qKe4CHMtaH/JtB
CC/JzpuFER1P1IhCtQIDAQAB
-
----END PUBLIC KEY-----
";
public function rsa(){
$content = "这是⼀段⽂字";
$res = $this->superLongPublicKeyEncrypt($content,$this->public_key,false,true);
var_dump($res);
$content = "kx/V8UtfahIOfsIC6lTTSX+ZVWock6SR2+Y/IbU0wmYrEkOB3ZO0qUQthVQVoEHaUSPYGLKLDTbuYOaQAN6JoHGh0YvVZ/8O92y4aUfyCdBlt2QMdY6yTKd2FvP4j5oc0buUrKXgX1GCksi6XT6QOsruxgzSAyFX67vGyf/0E1QdJewFlL $res = $this->superLongPrivateKeyDecrypt($content,$this->private_key,false,true);
var_dump($res);
}
public function superLongPublicKeyEncrypt($content, $rsaPublicKey, $choicePath = true, $withBase6
4 = false)
{
if ($choicePath) {
$pubKeyId = openssl_pkey_get_public($rsaPublicKey);//绝对路径读取
} else {
$pubKeyId = $rsaPublicKey;//公钥
}
$RSA_ENCRYPT_BLOCK_SIZE = 117;
$result = '';
$data = str_split($content, $RSA_ENCRYPT_BLOCK_SIZE);
foreach ($data as $block) {
openssl_public_encrypt($block, $dataEncrypt, $pubKeyId, OPENSSL_PKCS1_PADDING);
$result .= $dataEncrypt;
}
if ($withBase64) {
return base64_encode($result);
} else {
return $result;
}
}
public static function superLongPrivateKeyDecrypt($content, $rsaPrivateKey, $choicePath = true, $withBase64 = false)
{
if ($choicePath) {
$priKeyId = openssl_pkey_get_private($rsaPrivateKey);//绝对路径
} else {
$priKeyId = $rsaPrivateKey;//私钥
}
if ($withBase64) {
$data = base64_decode($content);
}
$RSA_DECRYPT_BLOCK_SIZE = 128;
$result = '';
$data = str_split($data, $RSA_DECRYPT_BLOCK_SIZE);
foreach ($data as $block) {
openssl_private_decrypt($block, $dataDecrypt, $priKeyId, OPENSSL_PKCS1_PADDING);
$result .= $dataDecrypt;
}
if ($result) {
return $result;
} else {
return false;
}
}
Demo 2:
<?php
/**
* PHP实现RSA分段加密、解密
*
* Class RSA
*/
class RSA
{
public $privateKey = './rsa_private_key.pem'; //私钥地址
public $publicKey = './rsa_public_key.pem'; //公钥地址
public $pri_key = '-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDvluFNiF8IrIsddK0OXBAvVBJH11OKvy9er1tRGn9yEJoHCJY3
EU/xz2LasCK8AwgRIqGJbvDBgRa70c3QT9j+wPqNqqJCSoSEKifnDUk1RgUReJT6php实例代码解密
iqWaJyfM+WM3aHnKl61RZL4NV5qKe4CHMtaH/JtBCC/JzpuFER1P1IhCtQIDAQAB
AoGAaFYQb68/k4twWbeB1YsKEVJPU7HV08pGWrmKztr3PTk1mnKG2BxV8DwcFJg3
yCCZ1rx6FFuXxOzudYR8WIctO4wdsEbFky/cEGsfc6JJjiktmZaQ7MvobGNwnoFJ
QvRxDd+5uD87JE19iBSgUpLVtXbv+pZxSpD70vitnMdSctECQQD66Z5HsuC8DUPu
OLQHNN4ra5Op179Xlq7LiEFW4GaVgonw24kiLX23c7CK7295Rgxct1fwQKyuU9br
n2uj8toDAkEA9HJ85BWlm2OfUm6VI3Q99rjlpCnhRyz70+sEtf7if1SpctVxNTkX
UOnXlpPTohjAHNhzh9fa1hh/ySH9sRMu5wJAa//8uh3br/YBxFsx2lw+OPBQGe4c
lSXtzPu0LCHg5f/PQhYs28I696jbV6IiGFA3Z/0e4/HiohLCUp9HJMWWYwJACE53
pfyCUyRwfomZccn6bQ7dZtWxfQyvRgU/dLvDkJYc5/UO0sMs4qf/lnNRhrmWlaRZ
UK1qF0pf1ULdbw360wJBAObrYopW2kvIlE09j9SEgNtgVsmfZlf85c4EAZrFJP/T
8nMNKQGo92Gd3HvbjJ+ZBOP1IFt+FDAsXeSLWLAwJrg=
-----END RSA PRIVATE KEY-----';
public $pub_key = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvluFNiF8IrIsddK0OXBAvVBJH
11OKvy9er1tRGn9yEJoHCJY3EU/xz2LasCK8AwgRIqGJbvDBgRa70c3QT9j+wPqN
qqJCSoSEKifnDUk1RgUReJT6iqWaJyfM+WM3aHnKl61RZL4NV5qKe4CHMtaH/JtB
CC/JzpuFER1P1IhCtQIDAQAB
-----END PUBLIC KEY-----';
/**
* RSA constructor.
* @param null $publicKeyPath
* @param null $privateKeyPath
* @param null $publicKey
* @param null $privateKey
* @throws FileNotFoundException
*/
public function __construct($publicKeyPath=null, $privateKeyPath=null, $publicKey=null, $privateKey=null) { if ($this->checkKeyFile($publicKeyPath)) {
$this->pub_key = openssl_pkey_get_public(file_get_contents($publicKeyPath));
}
if ($this->checkKeyFile($privateKeyPath)) {
$this->pri_key = openssl_pkey_get_private(file_get_contents($privateKeyPath));
}
if (!is_null($publicKey)) {
$this->pub_key = openssl_pkey_get_public($this->formatterPublicKey($publicKey));
}
if (!is_null($privateKey)) {
$this->pri_key = openssl_pkey_get_private($this->formatterPrivateKey($privateKey));
}
}
/**
* 校验⽂件是否存在
* @param $keyPath string ⽂件路径
* @return bool
* @throws FileNotFoundException
*/
public function checkKeyFile($keyPath)
{
if (!is_null($keyPath)) {
if(!file_exists($keyPath)) {
throw new FileNotFoundException($keyPath);
}
return true;
}
return false;
}
/**
* 格式化公钥
* @param $publicKey string 公钥
* @return string
*/
public function formatterPublicKey($publicKey)
{
if (str_contains('-----BEGIN PUBLIC KEY-----', $publicKey)) return $publicKey;
$str = chunk_split($publicKey, 64, PHP_EOL);//在每⼀个64字符后加⼀个\n
$publicKey = "-----BEGIN PUBLIC KEY-----".PHP_EOL.$str."-----END PUBLIC KEY-----";
return $publicKey;
}
/**
* 格式化私钥
* @param $privateKey string 公钥
* @return string
*/
public function formatterPrivateKey($privateKey)
{
if (str_contains('-----BEGIN RSA PRIVATE KEY-----', $privateKey)) return $privateKey;
$str = chunk_split($privateKey, 64, PHP_EOL);//在每⼀个64字符后加⼀个\n
$privateKey = "-----BEGIN RSA PRIVATE KEY-----".PHP_EOL.$str."-----END RSA PRIVATE KEY-----"; return $privateKey;
}
/**
* 公钥加密(分段加密)
* emptyStr 需要加密字符串
*/
public function encrypt($str) {
$crypted = array();
$data = $str;
$dataArray = str_split($data, 117);
foreach($dataArray as $subData){
$subCrypted = null;
openssl_public_encrypt($subData, $subCrypted, $this->pub_key);
$crypted[] = $subCrypted;
}
$crypted = implode('',$crypted);
return base64_encode($crypted);
}
/**
* 私钥解密(分段解密)
* @encrypstr 加密字符串
*/
public function decrypt($encryptstr) {
$encryptstr = base64_decode($encryptstr);
$decrypted = array();
$dataArray = str_split($encryptstr, 128);
foreach($dataArray as $subData){
$subDecrypted = null;
openssl_private_decrypt($subData, $subDecrypted, $this->pri_key);
$decrypted[] = $subDecrypted;
}
$decrypted = implode('',$decrypted);
return $decrypted;
}
}
$result = new RSA();
$data = '{"phone":"152********","name":"张三","inAcctNo":"8239472342342342","idNo":"342422165897654326","inAcctBankName":"平安银⾏"}'; $dataEn = $result->encrypt($data);
echo $dataEn;
echo "<pre>";
$dataDe = $result->decrypt($dataEn);
echo $dataDe;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论