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

Python中如何在Flask端点共享公钥实现客户端加密

客户端接收并使用Flask返回的RSA公钥加密数据的实现方案

你已经完成了服务器端公钥分发的核心逻辑,下面针对Python客户端和**JavaScript客户端(浏览器/Node.js)**分别给出具体实现方案,同时补充关键的最佳实践:

一、Python客户端实现

如果客户端同样使用Python,推荐用和服务器一致的cryptography库来处理公钥加载和加密:

步骤与代码示例

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

def get_and_use_public_key():
    # 1. 从Flask端点获取公钥
    response = requests.get("http://your-server-domain/bob_publickey")
    public_key_pem = response.json()["publickey"].encode("utf-8")

    # 2. 加载PEM格式的公钥
    public_key = serialization.load_pem_public_key(
        public_key_pem,
        backend=default_backend()
    )

    # 3. 加密数据(注意:2048位RSA密钥最多加密245字节明文)
    plaintext = b"需要加密的敏感数据"
    ciphertext = public_key.encrypt(
        plaintext,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )

    # 4. 将加密字节转为Base64字符串(方便HTTP传输)
    import base64
    ciphertext_b64 = base64.b64encode(ciphertext).decode("utf-8")
    # 后续可将ciphertext_b64发送至服务器
    return ciphertext_b64

二、JavaScript客户端实现

1. 浏览器端(使用Web Crypto API)

浏览器原生支持Web Crypto API,无需额外依赖:

async function encryptWithServerPublicKey() {
    // 1. 获取服务器公钥
    const response = await fetch('http://your-server-domain/bob_publickey');
    const data = await response.json();
    const publicKeyPem = data.publickey;

    // 2. 将PEM格式公钥转为ArrayBuffer
    const pemHeader = "-----BEGIN PUBLIC KEY-----";
    const pemFooter = "-----END PUBLIC KEY-----";
    const publicKeyRaw = publicKeyPem.replace(pemHeader, '').replace(pemFooter, '').replace(/\s/g, '');
    const publicKeyBuffer = Uint8Array.from(atob(publicKeyRaw), c => c.charCodeAt(0));

    // 3. 导入公钥
    const publicKey = await window.crypto.subtle.importKey(
        "spki",
        publicKeyBuffer,
        {
            name: "RSA-OAEP",
            hash: "SHA-256"
        },
        false,
        ["encrypt"]
    );

    // 4. 加密数据(需转为ArrayBuffer)
    const plaintext = new TextEncoder().encode("需要加密的敏感数据");
    const ciphertext = await window.crypto.subtle.encrypt(
        {
            name: "RSA-OAEP"
        },
        publicKey,
        plaintext
    );

    // 5. 转为Base64字符串便于传输
    const ciphertextB64 = btoa(String.fromCharCode(...new Uint8Array(ciphertext)));
    // 发送至服务器
    return ciphertextB64;
}

2. Node.js端(使用内置crypto模块)

Node.js内置crypto模块可直接处理RSA加密:

const axios = require('axios');
const crypto = require('crypto');

async function encryptData() {
    // 1. 获取公钥
    const response = await axios.get('http://your-server-domain/bob_publickey');
    const publicKeyPem = response.data.publickey;

    // 2. 加密数据
    const plaintext = "需要加密的敏感数据";
    const ciphertext = crypto.publicEncrypt(
        {
            key: publicKeyPem,
            padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
            oaepHash: 'sha256'
        },
        Buffer.from(plaintext)
    );

    // 3. 转为Base64字符串
    const ciphertextB64 = ciphertext.toString('base64');
    // 发送至服务器
    return ciphertextB64;
}

三、最佳实践

  • 强制使用HTTPS:公钥的传输必须通过HTTPS,防止中间人攻击替换公钥,否则加密逻辑完全失效。
  • 缓存公钥:客户端无需每次加密都请求公钥,可将获取到的公钥缓存(比如本地存储、内存),仅在密钥轮换时更新。
  • 处理加密长度限制:2048位RSA密钥最多只能加密245字节的明文,若需加密大文件/长文本,建议采用对称加密+RSA加密对称密钥的混合方案:
    1. 客户端生成随机对称密钥(如AES)
    2. 用对称密钥加密大数据
    3. 用服务器公钥加密对称密钥
    4. 将加密后的对称密钥+加密数据一起发送给服务器
  • 密钥轮换机制:定期生成新的密钥对,避免长期使用同一密钥,可在服务器端添加版本标识,客户端通过版本判断是否需要更新公钥。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 05:13:34