Help, I use crypto asymmetric encryption symmetric key, passed to PHP there is an error!
Đang mở
Chưa có ai nhận issue này.
Bug
Extension: openssl
Status: Needs Triage
- Ngôn ngữ chính
- C
- Star
- 40.4k
- Fork
- 8.1k
- Merge trung bình
- 2 ngày 13 giờ
- Pull request đã merge (30 ngày)
- 96
Mô tả
Description
It has been confirmed that:
- PHP 8.1.29
- The private key matches the public key
- Data transfer is complete
- Base64 encoding used for transmission
js:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>test</title>
</head>
<form id="login_form" method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES); ?>">
<body>
<div class="container">
<input type="text" name="ad_name" id="ad_name" maxlength="20" size="20" required autofocus><br>
<input type="password" name="ad_pass" id="pass" maxlength="20" size="20" autocomplete="off" required><br>
<input type="hidden" id="encryptedData" name="encryptedData">
<input type="submit" id="submit" value="submit">
</div>
</body>
</form>
<script>
// 数据处理
async function sendEncryptedMessage(data) {
try {
const key = await generateKey();
const rawKey = await exportKey(key);
console.log('密钥:', key);
console.log('原始密钥:', rawKey);
// 公钥接收
const publicKeyBase64 = "<?php echo $publickey_base64; ?>";
const publicKeyPem = atob(publicKeyBase64);
// 公钥加密
const publicKeyArrayBuffer = pemToArrayBuffer(publicKeyPem);
const encrypted = await asymmetricEncrypt(rawKey, publicKeyArrayBuffer);
return {encrypted: encrypted};
} catch (error) {
console.error('数据处理失败:', error);
}
}
// 表单提交
document.getElementById('login_form').addEventListener('submit', async function(event) {
event.preventDefault(); // 阻止明文提交
const formData = new FormData(this);
const data = {};
formData.forEach((value, key) => {
data[key] = value;
});
const encryptedData = await sendEncryptedMessage(JSON.stringify(data));
document.getElementById('encryptedData').value = JSON.stringify(encryptedData);
HTMLFormElement.prototype.submit.call(this); // 确保正确调用表单的 submit 方法
});
// 生成AES-GCM对称密钥。
async function generateKey() {
try {
const key = await crypto.subtle.generateKey(
{ name: 'AES-GCM', length: 256 },
true,
['encrypt', 'decrypt']
);
return key;
} catch (error) {
console.error('密钥生成失败:', error);
}
}
// 导出密钥为原始格式
async function exportKey(key) {
try {
const exportedKey = await crypto.subtle.exportKey('raw', key);
return new Uint8Array(exportedKey);
} catch (error) {
console.error('密钥导出失败:', error);
}
}
// 将PEM格式的公钥转换为ArrayBuffer
function pemToArrayBuffer(pem) {
const b64Lines = pem.replace(/-----[^-]+-----/g, "").replace(/\s+/g, "");
const b64 = atob(b64Lines);
const buffer = new ArrayBuffer(b64.length);
const view = new Uint8Array(buffer);
for (let i = 0; i < b64.length; i++) {
view[i] = b64.charCodeAt(i);
}
return buffer;
}
// ArrayBuffer转换为Base64
function arrayBufferToBase64(buffer) {
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
// 公钥加密
async function asymmetricEncrypt(data, publicKey) {
try {
const keyObject = await crypto.subtle.importKey(
'spki',
publicKey,
{ name: 'RSA-OAEP', hash: 'SHA-256' },
false,
['encrypt']
);
const encrypted = await crypto.subtle.encrypt({ name: 'RSA-OAEP' }, keyObject, new TextEncoder().encode(data));
const base64String = arrayBufferToBase64(encrypted);
return base64String;
} catch (error) {
console.error('公钥加密失败:', error);
}
}
</script>
</html>
PHP:
<?php
session_start();
// 如果会话中没有RSA密钥对,则生成新的密钥对
if (!isset($_SESSION['private_key']) || !isset($_SESSION['public_key'])) {
// 生成 RSA 密钥对
$config = array(
'digest_alg' => 'sha256',
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
);
$res = openssl_pkey_new($config);
// 获取私钥和公钥
openssl_pkey_export($res, $privateKey);
$publicKey = openssl_pkey_get_details($res)['key'];
// 将密钥对存储在会话中
$_SESSION['private_key'] = $privateKey;
$_SESSION['public_key'] = $publicKey;
}
// 从会话中获取私钥和公钥
$privateKey = $_SESSION['private_key'];
$publicKey = $_SESSION['public_key'];
$publickey_base64 = base64_encode($publicKey); // base64编码传送
// 私钥解密
function decryptWithPrivateKey($encryptedKeyBase64, $privateKeyPem) {
$encryptedKey = base64_decode($encryptedKeyBase64);
// 将PEM格式的私钥转换为OpenSSL可用的格式
$privateKey = openssl_pkey_get_private($privateKeyPem);
echo 'Base64解码后的加密密钥: ' . bin2hex($encryptedKey) . PHP_EOL;
if (!$privateKey) {
throw new Exception('加载私钥失败');
} else {
echo '私钥加载成功' . PHP_EOL;
}
// 使用私钥解密AES-GCM密钥
$decryptedKey = '';
$result = openssl_private_decrypt($encryptedKey, $decryptedKey, $privateKey, OPENSSL_PKCS1_OAEP_PADDING); // OPENSSL_PKCS1_OAEP_PADDING OPENSSL_NO_PADDING
if (!$result) {
throw new Exception('解密失败: ' . openssl_error_string());
}
// 打印解密后的AES-GCM密钥
echo "解密后的AES-GCM密钥: " . bin2hex($decryptedKey);
return $decryptedKey;
}
// 消息接收
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$hashedPassword = json_decode($_POST['encryptedData'], true);
echo 'cryptoBase64:' . PHP_EOL . bin2hex(base64_decode($hashedPassword['encrypted'])) . PHP_EOL;
// 私钥解密
$decryptedKey = decryptWithPrivateKey($hashedPassword['encrypted'], $privateKey);
};
?>
error:
Fatal error: Uncaught Exception: 解密失败: error:0200009F:rsa routines::pkcs decoding error in /home/runner/GigaLowestTransversal/index.php:44 Stack trace: #0 /home/runner/GigaLowestTransversal/index.php(57): decryptWithPrivateKey('MibsVVKMmL1uN9w...', '-----BEGIN PRIV...') #1 {main} thrown in /home/runner/GigaLowestTransversal/index.php on line 44
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Tái hiện HTML/JavaScript và PHP được cung cấp trong index.php bằng PHP 8.1.29, sau đó kiểm tra quá trình mã hóa RSA-OAEP và đường dẫn openssl_private_decrypt cùng với lỗi đã báo cáo. Công việc được xem là hoàn tất khi xác nhận được một lỗi đặc thù của PHP và có một bài kiểm thử php-src tối thiểu, nhưng hiện issue không nêu tên tệp php-src hay bài kiểm thử nào.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- javascript, php
- Lĩnh vực
- backend, security
- Loại issue
- Lỗi
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Cần làm rõ
- Mức phù hợp với người mới
- 15/100