Java的Rsa公钥解密转php,求解

1. 运行环境#

1). 当前使用的 Laravel 版本?#

Laravel 9

2). 当前使用的 php/php-fpm 版本?#

PHP 版本:8,0

3). 业务环境#

开发环境

2. 问题描述?#

有一段 java 的 demo,用 rsa 公钥解密的。该如何用 php 实现

package com.test;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;

import java.nio.charset.Charset;

/**
 * 3.0api 加解密 加签验签
 *
 * @author Admin
 */
public class VerifyRsaTest {


    /**
     * 加解密 加签验签
     */
    public static void main(String[] args) throws Exception {


        String publicKey="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyxVgchYx/xx3jWyKPxb4s7boVOSDLxu7MP2U0NNAqtWSNMRRF+5sAjMd3RyeftsRT/QWAf2Rs9P/oZikGP0yqpsrWYHgbLcYLqIsgNPr6yOk855gvHB5szRsQggK0d4hl562Lx5T9DvHuM5u2jChsqZ7PvRXmNa+SDBtEB/3fnwIDAQAB";
        String aa="C5rKZS/HWcEcaSFVyjmmOThYeEaEUwzK7kJf9NK5MkzkWxFH7VoQJS77c19jm9mt1YlhL5RGIficRi2W2+O8yMsT1Jps/7zvtzgV3lMp4ZBWciRg7/UU5CJq/CrVtfxHYrNQKn5eFTpaDX/cENb8u47vxtjZpwPhbNIc7HSCCLVZ0qSUgKCFHS/JNMGnin8rpCOL0ON5nEzmJnyDhlQikTVDTgDYdDyGokOkGnIUrD9JcMQ0sSLQXRk3qT3zfCAamgRWhDUDgUG+7HHoya5nFwjJ+UHq7pfxcu+gFDDWvHqAN1q+ayl1kb7hf0NSYjG0/d/MB2LT5XLxhDgVIQSwGiHRB/1nHIiNJGQnEirtsNcGSl9hXZ7PPaAm5Oo2gadIFh8ro0BKwnlmha6WmRS47sf7De3zlRVeSLWYXJYyniFj9+LumdUOgwWaZHrJXSpQSTj2GQtwLy0yjirkWKJXt2YfpeEXsUpaZib0Rbo8yuruvZqM1aAKtMwGRdBwTvKXECA6uCqizBPBtyNRRAUL7AvwZCKHJQdAY1u4yhKngDYEwO651PPVO/IkKw9CbC4mRpfhD5sIFoqIcFyl0f4ns/USip5gKUofKGv0hStQD8Hq9JIQEvR9M5lkx2KZarudIttZiZKycqMUA4xCHsJetbohBDQwMHY3I0tsKjy3WuiWbzJsuJrQD4qfbp72UOKjD+zdeyTzykdKOPEYvmsEucSlubFrd8jmQlyWjR/3roQCqlhGlZmH7CGf+epSewULOjQP6geUh1Zl2p0CJNBNd8olCqIHFt4AQqb1GhdVLcDpOg63HBGj8O+WiLbM9sE7umDYizmC7ImNIQ0mPRPuBw==";

        String str =  URLUtil.decode(aa, Charset.defaultCharset(),false);

        String decrypt = decryptRsaPublicKey(str, publicKey);
        System.out.println("对接方解密,decrypt = " + decrypt);

    }

    // RSA公钥解密
    public static String decryptRsaPublicKey(String targetData, String publicKeyBase64) {
        // RSA公钥解密
        RSA rsa = SecureUtil.rsa(null, publicKeyBase64);
        byte[] decrypt = rsa.decrypt(Base64.decode(targetData), KeyType.PublicKey);
        return new String(decrypt, CharsetUtil.CHARSET_UTF_8);
    }
}

我尝试用下面的 php 代码,无法解密。解密出来是 null。请问该如何才能用 php 实现

        $publicKey="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyxVgchYx/xx3jWyKPxb4s7boVOSDLxu7MP2U0NNAqtWSNMRRF+5sAjMd3RyeftsRT/QWAf2Rs9P/oZikGP0yqpsrWYHgbLcYLqIsgNPr6yOk855gvHB5szRsQggK0d4hl562Lx5T9DvHuM5u2jChsqZ7PvRXmNa+SDBtEB/3fnwIDAQAB";
        $txt="C5rKZS/HWcEcaSFVyjmmOThYeEaEUwzK7kJf9NK5MkzkWxFH7VoQJS77c19jm9mt1YlhL5RGIficRi2W2+O8yMsT1Jps/7zvtzgV3lMp4ZBWciRg7/UU5CJq/CrVtfxHYrNQKn5eFTpaDX/cENb8u47vxtjZpwPhbNIc7HSCCLVZ0qSUgKCFHS/JNMGnin8rpCOL0ON5nEzmJnyDhlQikTVDTgDYdDyGokOkGnIUrD9JcMQ0sSLQXRk3qT3zfCAamgRWhDUDgUG+7HHoya5nFwjJ+UHq7pfxcu+gFDDWvHqAN1q+ayl1kb7hf0NSYjG0/d/MB2LT5XLxhDgVIQSwGiHRB/1nHIiNJGQnEirtsNcGSl9hXZ7PPaAm5Oo2gadIFh8ro0BKwnlmha6WmRS47sf7De3zlRVeSLWYXJYyniFj9+LumdUOgwWaZHrJXSpQSTj2GQtwLy0yjirkWKJXt2YfpeEXsUpaZib0Rbo8yuruvZqM1aAKtMwGRdBwTvKXECA6uCqizBPBtyNRRAUL7AvwZCKHJQdAY1u4yhKngDYEwO651PPVO/IkKw9CbC4mRpfhD5sIFoqIcFyl0f4ns/USip5gKUofKGv0hStQD8Hq9JIQEvR9M5lkx2KZarudIttZiZKycqMUA4xCHsJetbohBDQwMHY3I0tsKjy3WuiWbzJsuJrQD4qfbp72UOKjD+zdeyTzykdKOPEYvmsEucSlubFrd8jmQlyWjR/3roQCqlhGlZmH7CGf+epSewULOjQP6geUh1Zl2p0CJNBNd8olCqIHFt4AQqb1GhdVLcDpOg63HBGj8O+WiLbM9sE7umDYizmC7ImNIQ0mPRPuBw==";
        //        $txt = urldecode($txt);
        $publicKey = "-----BEGIN PUBLIC KEY-----\n"
        . wordwrap($publicKey, 64, "\n", true)
        . "\n-----END PUBLIC KEY-----";
        $publicKeyResource = openssl_pkey_get_public($publicKey);
        openssl_public_decrypt(base64_decode($txt), $decryptedData, $publicKeyResource);
        dd($decryptedData);

3. 您期望得到的结果?#

{“amt”:1000.0000,”createTime”:1694663267000,”errorCode”:”36020”,”errorMsg”:” 账户可用余额不足”,”idCard”:”500231198602096055”,”merchantBatchId”:”20230914114746614223”,”merchantId”:1701443988206407682,”merchantOrderId”:”202309141147466142231”,”mobile”:”13983211095”,”orderBatchNo”:”202309141147478V2Y1X”,”orderNo”:”202309141147478V2Y1X00001”,”payeeAcc”:”oDely66AF4G-lD17AZTSx6D_rTLk”,”payeeName”:” 杨小军”,”platFee”:0.0000,”splitFlag”:”0”,”status”:”60”,”tradeEndTime”:1694663267000}

4. 您实际得到的结果?#

null

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
最佳答案

RSA 对原文长度(根据密钥)是有要求的,hutool 里面会自动切片处理,php 不会的,要手动处理,按照 128 切片就好了。


function decryptRsaPublicKey($targetData, $publicKeyBase64)
{
    // 构建公钥
    $publicKey = "-----BEGIN PUBLIC KEY-----\n" .
        chunk_split($publicKeyBase64, 64, "\n") .
        '-----END PUBLIC KEY-----';

    // 将目标数据进行 Base64 解码
    $decodedData = base64_decode($targetData);

    // 加载公钥
    $keyResource = openssl_pkey_get_public($publicKey);
    if (!$keyResource) {
        throw new Exception('Invalid public key');
    }

    $decrypted = '';
    $maxLength = 128; // 1024位密钥的块大小为128字节
    $offset = 0;

    // 分片解密
    while ($offset < strlen($decodedData)) {
        $chunk = substr($decodedData, $offset, $maxLength);
        $offset += $maxLength;
        $decryptedChunk = '';

        // 公钥解密
        if (!openssl_public_decrypt($chunk, $decryptedChunk, $keyResource)) {
            throw new Exception('Failed to decrypt data');
        }
        $decrypted .= $decryptedChunk;
    }

    // 释放密钥资源
    openssl_free_key($keyResource);

    return $decrypted;
}

// 测试数据
$publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyxVgchYx/xx3jWyKPxb4s7boVOSDLxu7MP2U0NNAqtWSNMRRF+5sAjMd3RyeftsRT/QWAf2Rs9P/oZikGP0yqpsrWYHgbLcYLqIsgNPr6yOk855gvHB5szRsQggK0d4hl562Lx5T9DvHuM5u2jChsqZ7PvRXmNa+SDBtEB/3fnwIDAQAB';
$txt = 'C5rKZS/HWcEcaSFVyjmmOThYeEaEUwzK7kJf9NK5MkzkWxFH7VoQJS77c19jm9mt1YlhL5RGIficRi2W2+O8yMsT1Jps/7zvtzgV3lMp4ZBWciRg7/UU5CJq/CrVtfxHYrNQKn5eFTpaDX/cENb8u47vxtjZpwPhbNIc7HSCCLVZ0qSUgKCFHS/JNMGnin8rpCOL0ON5nEzmJnyDhlQikTVDTgDYdDyGokOkGnIUrD9JcMQ0sSLQXRk3qT3zfCAamgRWhDUDgUG+7HHoya5nFwjJ+UHq7pfxcu+gFDDWvHqAN1q+ayl1kb7hf0NSYjG0/d/MB2LT5XLxhDgVIQSwGiHRB/1nHIiNJGQnEirtsNcGSl9hXZ7PPaAm5Oo2gadIFh8ro0BKwnlmha6WmRS47sf7De3zlRVeSLWYXJYyniFj9+LumdUOgwWaZHrJXSpQSTj2GQtwLy0yjirkWKJXt2YfpeEXsUpaZib0Rbo8yuruvZqM1aAKtMwGRdBwTvKXECA6uCqizBPBtyNRRAUL7AvwZCKHJQdAY1u4yhKngDYEwO651PPVO/IkKw9CbC4mRpfhD5sIFoqIcFyl0f4ns/USip5gKUofKGv0hStQD8Hq9JIQEvR9M5lkx2KZarudIttZiZKycqMUA4xCHsJetbohBDQwMHY3I0tsKjy3WuiWbzJsuJrQD4qfbp72UOKjD+zdeyTzykdKOPEYvmsEucSlubFrd8jmQlyWjR/3roQCqlhGlZmH7CGf+epSewULOjQP6geUh1Zl2p0CJNBNd8olCqIHFt4AQqb1GhdVLcDpOg63HBGj8O+WiLbM9sE7umDYizmC7ImNIQ0mPRPuBw==';


$d = decryptRsaPublicKey($txt, $publicKey);


var_dump($d);
// string(489) "{"amt":1000.0000,"createTime":1694663267000,"errorCode":"36020","errorMsg":"账户可用余额不足","idCard":"500231198602096055","merchantBatchId":"20230914114746614223","merchantId":1701443988206407682,"merchantOrderId":"202309141147466142231","mobile":"13983211095","orderBatchNo":"202309141147478V2Y1X","orderNo":"202309141147478V2Y1X00001","payeeAcc":"oDely66AF4G-lD17AZTSx6D_rTLk","payeeName":"杨小军","platFee":0.0000,"splitFlag":"0","status":"60","tradeEndTime":1694663267000}"
8个月前 评论
神的孩子丶都在跳舞 (楼主) 8个月前
讨论数量: 6

RSA 对原文长度(根据密钥)是有要求的,hutool 里面会自动切片处理,php 不会的,要手动处理,按照 128 切片就好了。


function decryptRsaPublicKey($targetData, $publicKeyBase64)
{
    // 构建公钥
    $publicKey = "-----BEGIN PUBLIC KEY-----\n" .
        chunk_split($publicKeyBase64, 64, "\n") .
        '-----END PUBLIC KEY-----';

    // 将目标数据进行 Base64 解码
    $decodedData = base64_decode($targetData);

    // 加载公钥
    $keyResource = openssl_pkey_get_public($publicKey);
    if (!$keyResource) {
        throw new Exception('Invalid public key');
    }

    $decrypted = '';
    $maxLength = 128; // 1024位密钥的块大小为128字节
    $offset = 0;

    // 分片解密
    while ($offset < strlen($decodedData)) {
        $chunk = substr($decodedData, $offset, $maxLength);
        $offset += $maxLength;
        $decryptedChunk = '';

        // 公钥解密
        if (!openssl_public_decrypt($chunk, $decryptedChunk, $keyResource)) {
            throw new Exception('Failed to decrypt data');
        }
        $decrypted .= $decryptedChunk;
    }

    // 释放密钥资源
    openssl_free_key($keyResource);

    return $decrypted;
}

// 测试数据
$publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyxVgchYx/xx3jWyKPxb4s7boVOSDLxu7MP2U0NNAqtWSNMRRF+5sAjMd3RyeftsRT/QWAf2Rs9P/oZikGP0yqpsrWYHgbLcYLqIsgNPr6yOk855gvHB5szRsQggK0d4hl562Lx5T9DvHuM5u2jChsqZ7PvRXmNa+SDBtEB/3fnwIDAQAB';
$txt = 'C5rKZS/HWcEcaSFVyjmmOThYeEaEUwzK7kJf9NK5MkzkWxFH7VoQJS77c19jm9mt1YlhL5RGIficRi2W2+O8yMsT1Jps/7zvtzgV3lMp4ZBWciRg7/UU5CJq/CrVtfxHYrNQKn5eFTpaDX/cENb8u47vxtjZpwPhbNIc7HSCCLVZ0qSUgKCFHS/JNMGnin8rpCOL0ON5nEzmJnyDhlQikTVDTgDYdDyGokOkGnIUrD9JcMQ0sSLQXRk3qT3zfCAamgRWhDUDgUG+7HHoya5nFwjJ+UHq7pfxcu+gFDDWvHqAN1q+ayl1kb7hf0NSYjG0/d/MB2LT5XLxhDgVIQSwGiHRB/1nHIiNJGQnEirtsNcGSl9hXZ7PPaAm5Oo2gadIFh8ro0BKwnlmha6WmRS47sf7De3zlRVeSLWYXJYyniFj9+LumdUOgwWaZHrJXSpQSTj2GQtwLy0yjirkWKJXt2YfpeEXsUpaZib0Rbo8yuruvZqM1aAKtMwGRdBwTvKXECA6uCqizBPBtyNRRAUL7AvwZCKHJQdAY1u4yhKngDYEwO651PPVO/IkKw9CbC4mRpfhD5sIFoqIcFyl0f4ns/USip5gKUofKGv0hStQD8Hq9JIQEvR9M5lkx2KZarudIttZiZKycqMUA4xCHsJetbohBDQwMHY3I0tsKjy3WuiWbzJsuJrQD4qfbp72UOKjD+zdeyTzykdKOPEYvmsEucSlubFrd8jmQlyWjR/3roQCqlhGlZmH7CGf+epSewULOjQP6geUh1Zl2p0CJNBNd8olCqIHFt4AQqb1GhdVLcDpOg63HBGj8O+WiLbM9sE7umDYizmC7ImNIQ0mPRPuBw==';


$d = decryptRsaPublicKey($txt, $publicKey);


var_dump($d);
// string(489) "{"amt":1000.0000,"createTime":1694663267000,"errorCode":"36020","errorMsg":"账户可用余额不足","idCard":"500231198602096055","merchantBatchId":"20230914114746614223","merchantId":1701443988206407682,"merchantOrderId":"202309141147466142231","mobile":"13983211095","orderBatchNo":"202309141147478V2Y1X","orderNo":"202309141147478V2Y1X00001","payeeAcc":"oDely66AF4G-lD17AZTSx6D_rTLk","payeeName":"杨小军","platFee":0.0000,"splitFlag":"0","status":"60","tradeEndTime":1694663267000}"
8个月前 评论
神的孩子丶都在跳舞 (楼主) 8个月前

RSA 对原文长度(根据密钥)是有要求的,hutool 里面会自动切片处理,php 不会的,要手动处理,按照 128 切片就好了。


function decryptRsaPublicKey($targetData, $publicKeyBase64)
{
    // 构建公钥
    $publicKey = "-----BEGIN PUBLIC KEY-----\n" .
        chunk_split($publicKeyBase64, 64, "\n") .
        '-----END PUBLIC KEY-----';

    // 将目标数据进行 Base64 解码
    $decodedData = base64_decode($targetData);

    // 加载公钥
    $keyResource = openssl_pkey_get_public($publicKey);
    if (!$keyResource) {
        throw new Exception('Invalid public key');
    }

    $decrypted = '';
    $maxLength = 128; // 1024位密钥的块大小为128字节
    $offset = 0;

    // 分片解密
    while ($offset < strlen($decodedData)) {
        $chunk = substr($decodedData, $offset, $maxLength);
        $offset += $maxLength;
        $decryptedChunk = '';

        // 公钥解密
        if (!openssl_public_decrypt($chunk, $decryptedChunk, $keyResource)) {
            throw new Exception('Failed to decrypt data');
        }
        $decrypted .= $decryptedChunk;
    }

    // 释放密钥资源
    openssl_free_key($keyResource);

    return $decrypted;
}

// 测试数据
$publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyxVgchYx/xx3jWyKPxb4s7boVOSDLxu7MP2U0NNAqtWSNMRRF+5sAjMd3RyeftsRT/QWAf2Rs9P/oZikGP0yqpsrWYHgbLcYLqIsgNPr6yOk855gvHB5szRsQggK0d4hl562Lx5T9DvHuM5u2jChsqZ7PvRXmNa+SDBtEB/3fnwIDAQAB';
$txt = 'C5rKZS/HWcEcaSFVyjmmOThYeEaEUwzK7kJf9NK5MkzkWxFH7VoQJS77c19jm9mt1YlhL5RGIficRi2W2+O8yMsT1Jps/7zvtzgV3lMp4ZBWciRg7/UU5CJq/CrVtfxHYrNQKn5eFTpaDX/cENb8u47vxtjZpwPhbNIc7HSCCLVZ0qSUgKCFHS/JNMGnin8rpCOL0ON5nEzmJnyDhlQikTVDTgDYdDyGokOkGnIUrD9JcMQ0sSLQXRk3qT3zfCAamgRWhDUDgUG+7HHoya5nFwjJ+UHq7pfxcu+gFDDWvHqAN1q+ayl1kb7hf0NSYjG0/d/MB2LT5XLxhDgVIQSwGiHRB/1nHIiNJGQnEirtsNcGSl9hXZ7PPaAm5Oo2gadIFh8ro0BKwnlmha6WmRS47sf7De3zlRVeSLWYXJYyniFj9+LumdUOgwWaZHrJXSpQSTj2GQtwLy0yjirkWKJXt2YfpeEXsUpaZib0Rbo8yuruvZqM1aAKtMwGRdBwTvKXECA6uCqizBPBtyNRRAUL7AvwZCKHJQdAY1u4yhKngDYEwO651PPVO/IkKw9CbC4mRpfhD5sIFoqIcFyl0f4ns/USip5gKUofKGv0hStQD8Hq9JIQEvR9M5lkx2KZarudIttZiZKycqMUA4xCHsJetbohBDQwMHY3I0tsKjy3WuiWbzJsuJrQD4qfbp72UOKjD+zdeyTzykdKOPEYvmsEucSlubFrd8jmQlyWjR/3roQCqlhGlZmH7CGf+epSewULOjQP6geUh1Zl2p0CJNBNd8olCqIHFt4AQqb1GhdVLcDpOg63HBGj8O+WiLbM9sE7umDYizmC7ImNIQ0mPRPuBw==';


$d = decryptRsaPublicKey($txt, $publicKey);


var_dump($d);
// string(489) "{"amt":1000.0000,"createTime":1694663267000,"errorCode":"36020","errorMsg":"账户可用余额不足","idCard":"500231198602096055","merchantBatchId":"20230914114746614223","merchantId":1701443988206407682,"merchantOrderId":"202309141147466142231","mobile":"13983211095","orderBatchNo":"202309141147478V2Y1X","orderNo":"202309141147478V2Y1X00001","payeeAcc":"oDely66AF4G-lD17AZTSx6D_rTLk","payeeName":"杨小军","platFee":0.0000,"splitFlag":"0","status":"60","tradeEndTime":1694663267000}"
8个月前 评论
神的孩子丶都在跳舞 (楼主) 8个月前

博客:关于 php rsa 加密处理 我之前还踩过坑

8个月前 评论
神的孩子丶都在跳舞 (楼主) 8个月前
kolin (作者) 8个月前

之前需要对接一个 Java 的项目,给同事写了个 DEMO,Laravel Command 可直接运行

代码已被折叠,点此展开
8个月前 评论