PHP实现RSA报文加密解密以及签名和验签
RSA分段解密
有时和java接口对接,会用到分段解密
参考:https://www.cnblogs.com/meetuj/p/14954533.html
PHP 私钥分段解密
public function superLongPrivateKeyDecrypt($content,$key_file){
$data = base64_decode($content); //有时需要两次 base64_decode 解码
$key = openssl_pkey_get_private(file_get_contents($key_file));
$RSA_DECRYPT_BLOCK_SIZE = 128; //对应 1024位的秘钥
$result = '';
$data = str_split($data, $RSA_DECRYPT_BLOCK_SIZE);
foreach ($data as $block) {
// openssl_private_decrypt($block, $dataDecrypt, $key, OPENSSL_PKCS1_PADDING);
$r = openssl_private_decrypt($block, $dataDecrypt, $key, OPENSSL_NO_PADDING);
if( ! $r ) log('err '. openssl_error_string() );
$result .= $dataDecrypt;
}
if ($result) {
return $result;
} else {
return false;
}
}
JAVA 私钥解密
/**
* 私钥解密
*
* @param encryptedData
* 已加密数据
* @param privateKey
* 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
PHP实现RSA签名和验签
密钥生成
Mac和Linux 用户
安装openssl
生成1024位的私钥,不指定的话默认2048位
后逐条输入如下指令:
$ openssl #进入 OpenSSL 程序
OpenSSL> genrsa -out rsa_private_key.pem 1024 #生成私钥
OpenSSL> pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_private_key_pkcs8.pem #Java开发者需要将私钥转换成PKCS8格式
OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem #生成公钥
OpenSSL> exit #退出 OpenSSL 程序
拓展:RSA加密算法, PKCS#1 和PKCS#8区别是什么?
疑问:使用base64_encode编码之后出现的+和/在http的get传输过程中会出现+变成空格的请。
可以使用下面两个方法解决:
function _base64url_encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
function _base64url_decode($data) {
$str = str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT);
return base64_decode($str);
}
PHP实现RSA用私钥签名
$privatekey = openssl_get_privatekey( file_get_contents($private_key_file_path) );
$signedStr = '';
openssl_sign($signStr, $signedStr, $privatekey, OPENSSL_ALGO_SHA256);
openssl_free_key($privatekey);
$sign = $this->_base64url_encode($signedStr);
PHP实现RSA用公钥验签
$public_key = openssl_get_publickey( file_get_contents($pub_key_file_path) );
if(empty($public_key)){
return false;
}
$sign = base64_decode($sign);
$ok = openssl_verify( $sign_str, $sign, $public_key, OPENSSL_ALGO_SHA256 ); //SHA256
openssl_free_key( $public_key );
if ($ok == 1) {
$result = true;
} elseif ($ok == 0) {
$result = false;
} else {
MLog::write('DEBUG', __CLASS__.' ' . __FUNCTION__ . ' 0 openssl_error_str '.json_encode(openssl_error_string));
}
posted on 2020-08-05 15:39 aworkstory 阅读(2395) 评论(0) 编辑 收藏 举报