前言

云计算、大数据普及后,银行、税务、电力等行业积累大量用户敏感数据。传统 AES、RSA 仅能静态加密存储,想要统计、建模必须解密,云端可直接读取明文,隐私泄露风险极高。结合《数据安全法》《个人信息保护法》“数据可用不可见” 的合规要求,同态加密成为解决该痛点的核心密码技术。

本文基于应用密码学课程完整调研成果,通俗拆解同态加密底层原理、主流算法、金融落地场景、现存技术缺陷,附带可直接运行的 Python 演示代码,适合密码学入门学生、金融科技从业者阅读。

一、同态加密基础概念与分类

传统加密流程存在致命短板:数据运算前必须解密,明文会完全暴露给第三方服务器。而同态加密打破这一限制,完整流程分为四步:密钥生成→明文加密→云端密文运算→本地解密。整个过程云端仅处理密文乱码,无法获取原始信息,真正实现数据可用不可见。

按照支持运算能力,同态加密分为三类,商用成熟度差距明显:

  1. 部分同态加密(PHE):当前唯一大规模商用方案,仅支持单一加法或乘法运算,轻量化、运算速度快。代表算法 Paillier(加法,金融统计首选)、ElGamal(乘法,数字签名、数字货币);
  2. 层次全同态加密(SWHE):支持加减乘混合运算,但乘法运算存在次数上限,噪声超标会导致解密失败,BFV、CKKS 多用于银行离线风控、医疗数据建模;
  3. 全同态加密(FHE):理论支持无限次任意运算,但算力消耗巨大,仅停留在实验室研究阶段,暂无线上落地案例。

三类加密算法安全性依托两类经典密码困难问题:Paillier 基于大整数分解难题,ElGamal 依托离散对数难题;BFV、CKKS 采用格密码,具备抵御量子计算机攻击的能力,本科阶段仅作基础了解即可。

二、主流算法原理与数值演示

Paillier 加法同态(金融行业最常用)

Paillier 专门适配金额、营收、人数等数值求和场景,也是本次调研的核心算法。 密钥生成依靠两个大素数构造模数,公钥对外公开用于加密,私钥本地留存;加密时引入随机数保证密文不重复,核心特性为密文相乘等价明文相加。

举直观示例:明文 1=1200、明文 2=3800,分别加密得到 c1、c2;云端直接对两段密文相乘得到新密文,本地解密后结果为 5000。多家银行可上传客户资产密文完成汇总,全程不会泄露各自真实存款数据。

ElGamal 属于乘法同态加密,密文相乘对应明文相乘,适合费率计算、区块链签名,但原生不支持加法,无法单独用于数据统计;BFV 仅支持整数运算,CKKS 优化后可处理浮点数、矩阵,适配收益率、风险系数计算,但二者运算速度远慢于 Paillier。

表 1 主流同态加密算法基础特性对比

算法名称加密类型支持运算处理数据运算速度主要适用场景
Paillier部分加法同态加法、标量乘整数快银行资产求和、税务统计、电力抄表
ElGamal部分乘法同态乘法、标量乘整数较快区块链签名、金额乘积计算
BFV层次全同态加减乘混合整数中等离线整数风控模型计算
CKKS层次全同态浮点数四则运算小数、矩阵慢金融收益率、离线 AI 分析

三、同态加密现存技术瓶颈

目前同态加密大范围商用存在三大难以规避的短板: 第一,密文噪声持续累积。加密生成的随机噪声是安全基础,加法运算噪声缓慢线性增长,乘法运算噪声指数暴涨,一旦超过阈值,密文解密结果会完全失真。Paillier 仅做加法无运算上限,BFV、CKKS 多层乘法运算极易失效。

第二,整体运算效率低下。明文批量数据求和仅需毫秒,Paillier 密文运算需要数秒,CKKS 浮点推理甚至达到分钟级,无法支撑高并发线上金融业务,实时场景只能选用轻量化半同态方案。

第三,密钥与密文存储开销大。同等安全强度下,同态加密密钥、密文体积远大于 RSA、ECC,部署在电力抄表终端、社保卡等低算力设备容易出现内存不足问题,轻量化参数裁剪是主流优化思路。

四、金融与多行业落地应用方案

结合金融、政务、物联网业务场景,整理四类典型落地案例,同时给出分场景算法选型参考。

银行多方联合信贷风控是最典型应用场景:多家银行、消费金融机构需要联合评估客户信用,但明文互通违反隐私法规。采用 Paillier 加密后,各家机构本地加密收入、负债等客户数据,仅上传密文至云端计算平台;云端完成密文求和统计,只下发加密后的风险评分,机构之间全程看不到对方客户原始信息。 

除此之外,税务系统企业营收汇总、电力远程抄表、区块链隐私数字货币交易均能使用同态加密保护隐私:税务局通过密文累加统计区域总税收,无法查看单家企业经营数据;电力终端轻量化加密用电量,仅统计片区总用电;Paillier 搭配 ElGamal 可加密区块链转账金额,隐藏真实交易数额。

表 2 不同业务场景算法选型参考

业务场景核心计算需求推荐算法选型理由
银行跨机构客户资产求和整数加法统计Paillier速度快、部署简单,适配实时汇总
税务局企业营收汇总大额整数求和Paillier政务并发量低,轻量化易实现
电力远程抄表片区统计小整数累加轻量化 Paillier资源开销小,适配低算力终端
银行离线风险系数计算小数多层运算CKKS支持浮点数,适合离线建模
区块链隐私转账交易金额加减、签名Paillier+ElGamal 混合兼顾加法统计与乘法签名

五、优化思路与行业发展趋势

针对效率、存储缺陷,当下主流优化手段分为三类:裁剪加密安全参数缩小密文体积、批量编码单条密文承载多组数值、分场景搭配不同算法(实时统计用 Paillier,离线建模用 CKKS),平衡功能与算力消耗。

长期来看,轻量化半同态加密会全面普及,成为银行、政务隐私保护基础工具;硬件加速芯片将降低全同态加密运算延迟,拓展离线金融大数据分析场景;国内持续推进同态加密适配 SM 系列国产商用密码,同时国家逐步出台统一行业标准,降低企业开发使用门槛。

六、Python 代码实战:简化版 Paillier 实现

下面代码适配 Python3.5 及以上低版本 IDLE,解决旧版本 pow 模逆不兼容、密钥生成卡顿问题,完整复现前文 1200+3800 密文加法示例,注释清晰可直接运行。

import random
import math

# 最大公约数
def gcd(a, b):
    while b:
        a, b = b, a % b
    return a

# 最小公倍数
def lcm(a, b):
    return a * b // gcd(a, b)

# 扩展欧几里得求模逆,兼容低版本Python
def mod_inverse(a, mod):
    old_r, r = a, mod
    old_s, s = 1, 0
    while r != 0:
        quotient = old_r // r
        old_r, r = r, old_r - quotient * r
        old_s, s = s, old_s - quotient * s
    if old_r != 1:
        raise Exception("无模逆元")
    return old_s % mod

# 提速素数判断
def is_prime(num):
    if num < 2:
        return False
    if num == 2:
        return True
    if num % 2 == 0:
        return False
    for i in range(3, int(math.sqrt(num)) + 1, 2):
        if num % i == 0:
            return False
    return True

# 24位短素数,快速生成密钥
def get_prime(bit_len=24):
    while True:
        num = random.getrandbits(bit_len)
        if is_prime(num):
            return num

# Paillier加密类
class Paillier:
    def __init__(self):
        print("正在生成密钥,请稍等...")
        self.p = get_prime(24)
        self.q = get_prime(24)
        self.n = self.p * self.q
        self.n_sq = self.n ** 2
        self.lambda_ = lcm(self.p - 1, self.q - 1)
        self.g = self.n + 1

        def L(x):
            return (x - 1) // self.n

        g_lambda = pow(self.g, self.lambda_, self.n_sq)
        temp_L = L(g_lambda)
        self.mu = mod_inverse(temp_L, self.n)
        self.pk = (self.n, self.g)
        self.sk = (self.lambda_, self.mu)

    def encrypt(self, m):
        r = random.randrange(1, self.n)
        while gcd(r, self.n) != 1:
            r = random.randrange(1, self.n)
        c = (pow(self.g, m, self.n_sq) * pow(r, self.n, self.n_sq)) % self.n_sq
        return c

    def decrypt(self, c):
        def L(x):
            return (x - 1) // self.n
        temp = pow(c, self.lambda_, self.n_sq)
        m = (L(temp) * self.mu) % self.n
        return m

    def cipher_add(self, c1, c2):
        return (c1 * c2) % self.n_sq

# 测试程序
if __name__ == "__main__":
    phe = Paillier()
    m1 = 1200
    m2 = 3800
    c1 = phe.encrypt(m1)
    c2 = phe.encrypt(m2)
    c_sum = phe.cipher_add(c1, c2)
    res = phe.decrypt(c_sum)
    print("明文1:{},明文2:{}".format(m1, m2))
    print("密文相加解密结果:{}".format(res))
    print("明文相加预期结果:{}".format(m1 + m2))

更多推荐