From ef246db31cf5d64bbebf02826b00086809fd12ef Mon Sep 17 00:00:00 2001 From: Milky0217 Date: Mon, 27 Apr 2026 14:27:14 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E5=AE=9D=20RSA2=20=E7=AD=BE=E5=90=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 支持 base64 编码的 PEM 格式私钥(systemd 环境变量) - 使用 Digest + Pkcs1v15Sign::new() 进行签名(自动哈希) - 修复 rsa2_sign 和 rsa2_verify 函数实现 --- src/alipay.rs | 32 ++++++++++++++------------------ src/handlers/payment.rs | 28 +++++++++++++++------------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/alipay.rs b/src/alipay.rs index 525c7dd..1592fa8 100644 --- a/src/alipay.rs +++ b/src/alipay.rs @@ -1,8 +1,9 @@ // src/alipay.rs — 支付宝 RSA2 签名与请求封装 +use rsa::pkcs1v15::{Pkcs1v15Sign, SigningKey, VerifyingKey}; use rsa::pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, LineEnding}; -use rsa::signature::Signer; +use rsa::signature::{Signer, Verifier}; +use rsa::RsaPrivateKey; use rsa::RsaPublicKey; -use rsa::{Pkcs1v15Sign, RsaPrivateKey}; use sha2::{Digest, Sha256}; use std::collections::BTreeMap; use std::env; @@ -76,42 +77,37 @@ pub fn rsa2_sign(content: &str, private_key_pem: &str) -> Result private_key_pem, ) .map_err(|e| format!("Base64 解码失败: {}", e))?; - + let pem_str = String::from_utf8(decoded) .map_err(|e| format!("PEM 字符串格式错误: {}", e))?; - + RsaPrivateKey::from_pkcs8_pem(&pem_str) .map_err(|e| format!("私钥解析失败: {}", e))? } }; - let signing_input = Sha256::digest(content.as_bytes()); - let signature = private_key - .sign(Pkcs1v15Sign::new::(), &signing_input) - .map_err(|e| format!("签名失败: {}", e))?; - + let signing_key = SigningKey::::new(private_key); + let signature = signing_key.sign(content.as_bytes()); Ok(base64::Engine::encode( &base64::engine::general_purpose::STANDARD, - &signature, + signature.to_bytes().as_ref(), )) } /// 验证 RSA2 签名 pub fn rsa2_verify(content: &str, sign: &str, public_key_pem: &str) -> Result { + use sha2::Digest; let public_key = RsaPublicKey::from_public_key_pem(public_key_pem) .map_err(|e| format!("支付宝公钥解析失败: {}", e))?; let sig_bytes = base64::Engine::decode(&base64::engine::general_purpose::STANDARD, sign) .map_err(|e| format!("签名 Base64 解码失败: {}", e))?; - let hashed_content = Sha256::digest(content.as_bytes()); - Ok(public_key - .verify( - Pkcs1v15Sign::new::(), - &hashed_content, - &sig_bytes, - ) - .is_ok()) + let hashed = Sha256::digest(content.as_bytes()); + public_key + .verify(rsa::Pkcs1v15Sign::new::(), &hashed, &sig_bytes) + .map_err(|e| format!("签名验证失败: {}", e))?; + Ok(true) } /// 构建支付宝请求 URL(含签名) diff --git a/src/handlers/payment.rs b/src/handlers/payment.rs index 969b524..2f1287c 100644 --- a/src/handlers/payment.rs +++ b/src/handlers/payment.rs @@ -1,9 +1,10 @@ // handlers/payment.rs — 支付相关处理器(接入支付宝) use actix_web::{get, post, web, HttpRequest, HttpResponse}; use chrono::Utc; +use rsa::pkcs1v15::{Pkcs1v15Sign, SigningKey, VerifyingKey}; use rsa::pkcs8::DecodePrivateKey; -use rsa::signature::{Signer, Verifier}; -use rsa::{Pkcs1v15Sign, RsaPrivateKey}; +use rsa::signature::{SignatureEncoding, Signer, Verifier}; +use rsa::RsaPrivateKey; use serde::Deserialize; use sha2::{Digest, Sha256}; use sqlx::postgres::PgPool; @@ -101,29 +102,30 @@ fn rsa2_sign(content: &str, private_key_pem: &str) -> Result { .map_err(|e| format!("私钥解析失败: {}", e))? } }; - let hashed_content = Sha256::digest(content.as_bytes()); - let signature = private_key - .sign(Pkcs1v15Sign::new::(), &hashed_content) - .map_err(|e| format!("签名失败: {}", e))?; + let signing_key = SigningKey::::new(private_key); + let signature = signing_key.sign(content.as_bytes()); Ok(base64::Engine::encode( &base64::engine::general_purpose::STANDARD, - &signature, + signature.to_bytes().as_ref(), )) } /// 验证 RSA2 签名 +#[allow(dead_code)] fn rsa2_verify(content: &str, sign: &str, public_key_pem: &str) -> Result { use rsa::pkcs8::DecodePublicKey; - use rsa::signature::Verifier; + use rsa::RsaPublicKey; + use sha2::Digest; let public_key = - rsa::RsaPublicKey::from_public_key_pem(public_key_pem) + RsaPublicKey::from_public_key_pem(public_key_pem) .map_err(|e| format!("支付宝公钥解析失败: {}", e))?; let sig_bytes = base64::Engine::decode(&base64::engine::general_purpose::STANDARD, sign) .map_err(|e| format!("签名 Base64 解码失败: {}", e))?; - let hashed_content = Sha256::digest(content.as_bytes()); - Ok(public_key - .verify(Pkcs1v15Sign::new::(), &hashed_content, &sig_bytes) - .is_ok()) + let hashed = Sha256::digest(content.as_bytes()); + public_key + .verify(rsa::Pkcs1v15Sign::new::(), &hashed, &sig_bytes) + .map_err(|e| format!("签名验证失败: {}", e))?; + Ok(true) } // ===== Helper: 调用 alipay.trade.page.pay =====