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

浏览器环境下JS前端加密密码,FastAPI后端解密可行方案咨询

浏览器前端加密密码并在FastAPI后端解密的可行方案

你可以直接使用浏览器原生的Web Crypto API(无需安装任何第三方库)结合后端RSA非对称加密来实现需求,以下是具体步骤和代码示例:

1. 后端生成RSA密钥对

首先在FastAPI后端生成RSA私钥和公钥,公钥传给前端用于加密,私钥留在后端解密:

from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.backends import default_backend

# 生成2048位RSA私钥
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
    backend=default_backend()
)

# 导出PEM格式公钥(供前端使用)
public_key_pem = private_key.public_key().public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
).decode('utf-8')

# 导出PEM格式私钥(后端保存,绝对不能暴露)
private_key_pem = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption()
).decode('utf-8')

2. 前端用Web Crypto API加密密码

前端通过Web Crypto API导入公钥,对密码进行加密,转换为Base64字符串后发送给后端:

async function encryptPassword(password, publicKeyPem) {
    // 清理PEM格式的头尾标识和空格
    const cleanPublicKey = publicKeyPem
        .replace(/-----BEGIN PUBLIC KEY-----/, '')
        .replace(/-----END PUBLIC KEY-----/, '')
        .replace(/\s/g, '');
    
    // 将Base64公钥转换为ArrayBuffer
    const keyBuffer = Uint8Array.from(atob(cleanPublicKey), c => c.charCodeAt(0));
    
    // 导入RSA公钥
    const publicKey = await window.crypto.subtle.importKey(
        'spki',
        keyBuffer,
        { name: 'RSA-OAEP', hash: 'SHA-256' },
        false,
        ['encrypt']
    );
    
    // 将密码转换为ArrayBuffer
    const passwordBuffer = new TextEncoder().encode(password);
    
    // 执行加密
    const encryptedBuffer = await window.crypto.subtle.encrypt(
        { name: 'RSA-OAEP' },
        publicKey,
        passwordBuffer
    );
    
    // 转换为Base64字符串便于传输
    return btoa(String.fromCharCode(...new Uint8Array(encryptedBuffer)));
}

// 使用示例:从后端获取公钥后加密密码
// const encryptedPwd = await encryptPassword('用户输入的密码', 后端返回的publicKeyPem);
// 然后通过POST请求将encryptedPwd发送到FastAPI接口

3. FastAPI后端解密密码

后端接收加密后的Base64字符串,用私钥解密得到明文密码:

from fastapi import FastAPI, HTTPException
import base64
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

app = FastAPI()

# 这里替换成你实际保存的私钥内容
PRIVATE_KEY_PEM = """-----BEGIN PRIVATE KEY-----
你的私钥PEM内容
-----END PRIVATE KEY-----"""

@app.post("/verify-password")
async def verify_password(encrypted_password: str):
    try:
        # 加载私钥
        private_key = serialization.load_pem_private_key(
            PRIVATE_KEY_PEM.encode('utf-8'),
            password=None,
            backend=default_backend()
        )
        
        # 将Base64加密字符串解码为字节
        encrypted_bytes = base64.b64decode(encrypted_password)
        
        # 解密密码
        decrypted_bytes = private_key.decrypt(
            encrypted_bytes,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )
        
        # 转换为明文密码
        plain_password = decrypted_bytes.decode('utf-8')
        
        # 注意:拿到明文后不要存储,立即用bcrypt/Argon2等哈希算法处理后验证
        # 示例:比对数据库中存储的密码哈希
        # if bcrypt.checkpw(plain_password.encode('utf-8'), db_password_hash):
        #     return {"status": "success"}
        
        return {"message": "解密成功", "plain_password": plain_password}
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"解密失败: {str(e)}")

关键注意事项

  • 安全要求:必须通过HTTPS传输,避免公钥和加密数据被劫持;后端拿到明文密码后,一定要用bcrypt、Argon2等慢哈希算法处理,绝对不能直接存储明文。
  • 算法一致性:前后端必须使用相同的加密算法和参数(这里用的是RSA-OAEP + SHA-256),否则会解密失败。
  • Web Crypto API限制:该API仅在HTTPS环境或localhost下可用,普通HTTP环境会报错。

内容的提问来源于stack exchange,提问作者KK RR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:08:35