You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将SubtleCrypto加密的Promise结果通过PHP存入MySQL?

问题分析与解决方案

核心误区说明

CURL作为HTTP客户端请求PHP页面时,只会获取PHP输出的静态内容,不会执行页面中的JavaScript代码。你当前基于浏览器SubtleCrypto的加密逻辑在客户端执行,CURL无法直接拿到加密结果,这是核心矛盾。以下分两种场景给出解决方案:


场景一:优先迁移至PHP服务端加密(推荐)

直接在PHP中用OpenSSL扩展实现RSA-OAEP-SHA512加密,CURL调用后可直接返回结果并完成MySQL存储,完全规避客户端异步问题。

PHP代码示例(CURL直接调用的页面)

<?php
// 待加密数据(可通过GET/POST参数传入)
$rawData = $_POST['data'] ?? 'default_data';
// PEM格式公钥
$publicKey = "-----BEGIN PUBLIC KEY-----
你的公钥内容
-----END PUBLIC KEY-----";

// 配置RSA-OAEP加密参数
$encryptOptions = [
    'padding' => OPENSSL_PKCS1_OAEP_PADDING,
    'digest_alg' => 'sha512'
];

// 执行加密
$encryptSuccess = openssl_public_encrypt($rawData, $encryptedBytes, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);

if ($encryptSuccess) {
    // 转Base64方便传输与存储
    $encryptedBase64 = base64_encode($encryptedBytes);
    
    // 存入MySQL
    $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
    $stmt = $pdo->prepare("INSERT INTO encrypted_data (content) VALUES (?)");
    $stmt->execute([$encryptedBase64]);
    
    // 返回加密结果给CURL
    echo $encryptedBase64;
} else {
    http_response_code(500);
    echo '加密失败:' . openssl_error_string();
}
?>

场景二:必须使用浏览器SubtleCrypto的情况

若因硬件加密等限制必须用浏览器API,需通过无头浏览器执行JS并获取结果,再同步给CURL调用的服务端。同时修正原JS代码的异步问题:

1. 重构JS加密函数(解决Promise外部访问问题)

先补全依赖工具函数,并将加密逻辑改为返回Promise,用async/await处理异步:

// 字符串转ArrayBuffer
function str2ab(str) {
  const buf = new ArrayBuffer(str.length);
  new Uint8Array(buf).set([...str].map(c => c.charCodeAt(0)));
  return buf;
}

// ArrayBuffer转字符串
function ab2str(buf) {
  return String.fromCharCode(...new Uint8Array(buf));
}

// 加密函数:返回Promise,支持async/await调用
async function encryptData(rawData, publicKeyPem) {
  const crypto = window.crypto || window.msCrypto;
  if (!crypto?.subtle) throw new Error('加密API不支持');

  // 解析PEM公钥
  const pemHeader = "-----BEGIN PUBLIC KEY-----";
  const pemFooter = "-----END PUBLIC KEY-----";
  const pemContent = publicKeyPem.slice(pemHeader.length, -pemFooter.length);
  const derBuffer = str2ab(window.atob(pemContent));

  try {
    // 导入公钥
    const key = await crypto.subtle.importKey(
      "spki", derBuffer,
      { name: "RSA-OAEP", hash: "SHA-512" },
      false, ["encrypt"]
    );
    // 执行加密:注意原代码参数顺序错误,修正为(算法配置, 密钥, 待加密数据)
    const encryptedBuf = await crypto.subtle.encrypt(
      { name: "RSA-OAEP" }, key, str2ab(rawData)
    );
    // 转Base64返回
    return btoa(ab2str(encryptedBuf));
  } catch (err) {
    console.error('加密失败:', err);
    throw err;
  }
}

2. 用无头浏览器获取加密结果(供CURL调用)

用Node.js的Puppeteer模拟浏览器执行JS,将结果返回给调用方:

const puppeteer = require('puppeteer');

async function fetchEncryptedResult() {
  const browser = await puppeteer.launch({ headless: 'new' });
  const page = await browser.newPage();

  // 加载包含加密逻辑的页面
  await page.goto('http://your-domain.com/encrypt-page.php');

  // 在页面上下文执行加密
  const encryptedResult = await page.evaluate(async () => {
    // 复制上述str2ab、ab2str、encryptData函数到这里
    return await encryptData('待加密数据', '你的PEM公钥');
  });

  // 将结果发送给PHP存入MySQL
  await fetch('http://your-domain.com/save-to-mysql.php', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: `encrypted_data=${encodeURIComponent(encryptedResult)}`
  });

  await browser.close();
  return encryptedResult;
}

// 执行并输出结果,CURL可调用此脚本的HTTP接口或直接运行
fetchEncryptedResult().then(res => console.log(res));

内容的提问来源于stack exchange,提问作者Ramit.K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:02:20