隐私计算 2.2 Shamir秘密共享方案

本文介绍了一种1979年由Shamir提出的秘密分享方法,通过随机多项式和特定的选取点策略,实现了安全地将秘密分成多个部分,且仅需满足一定数量的参与者即可重构原始秘密。以13为例,通过5个随机数和17为模数的操作演示了整个过程,包括秘密分割和重构的详细步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 简介

  • 作者:Shamir
  • 时间:1979年
  • 理念:基于多项式插值算法

2 具体实现

I 秘密分割算法

  • (1)选择一个随机素数 p p p,并产生一个随机的 t − 1 t-1 t1 次多项式;
    f ( x ) = a t − 1 x t − 1 + ⋯ + a 1 x + a 0   m o d   p f(x)=a_{t-1} x^{t-1}+\cdots+a_{1} x+a_{0} \bmod p f(x)=at1xt1++a1x+a0modp
    a 0 = S a_0 = S a0=S S S S为想要分享的秘密),则 f ( 0 ) = a 0 = S f(0) = a_0 = S f(0)=a0=S f ( x ) f(x) f(x)的最高次必须设置为 x t − 1 x^{t-1} xt1

  • (2)选择 n n n 个互不相同的整数 1 ≤ x 1 , … , x n ≤ p − 1 1≤ x_1,…,x_n ≤ p-1 1x1,,xnp1

  • (3)第 i i i 个参与者计算 S i = f ( x i ) S_i = f(x_i) Si=f(xi)作为其分享的秘密;

  • (4)销毁 f ( x ) f(x) f(x)

II 秘密重构算法

  • (1) t t t 个参与者拿出自己的秘密消息。假设 S 1 , … , S t S_1, …, S_t S1,,St 是这 t t t 个秘密,分别对应 x 1 , … , x t x_1, …, x_t x1,,xt。利用这些信息可以重构出 f ( x ) f(x) f(x)
    f ( x ) = ∑ i S i ∏ j ≠ i ( x − x j ) ∏ j ≠ i ( x i − x j )   m o d   p or f ( x ) = ∑ i = 1 t S i ∏ j ∈ { 1 , 2 , … , t } ∖ { i } ( x − x j ) ∏ j ∈ { 1 , 2 , … , t } ∖ { i } ( x i − x j )   m o d   p \begin{array}{l} f(x) = \sum_{i} \frac{S_i \prod_{j \neq i} (x - x_j)}{\prod_{j \neq i} (x_i - x_j)} \bmod p \\ \textrm{or} \\ f(x) = \sum_{i=1}^t \frac{S_i \prod_{j \in \{1, 2, \dots, t\} \setminus \{i\}} (x - x_j)}{\prod_{j \in \{1, 2, \dots, t\} \setminus \{i\}} (x_i - x_j)} \bmod p\\ \end{array} f(x)=ij=i(xixj)Sij=i(xxj)modporf(x)=i=1tj{1,2,,t}{i}(xixj)Sij{1,2,,t}{i}(xxj)modp
    a 0 = S a_0 = S a0=S S S S为想要分享的秘密),则 f ( 0 ) = a 0 = S f(0) = a_0 = S f(0)=a0=S f ( x ) f(x) f(x)的最高次必须设置为 x t − 1 x^{t-1} xt1

  • (2)重构出 f ( x ) f(x) f(x)以后,计算 S = f ( 0 ) S = f(0) S=f(0), 多于 t t t个参与者重构 f ( x ) f(x) f(x)的过程也是适用的。

3 实例

设秘密 S = 13 S = 13 S=13 n = 5 n = 5 n=5, t = 3 t = 3 t=3,选择模数 p = 17 p = 17 p=17
I 秘密分割

  • (1)生成 t − 1 t - 1 t1个小于等于 p p p的随机数, a 1 = 10 a_1 = 10 a1=10 a 2 = 2 a_2 = 2 a2=2 a 0 = S = 13 a_0 = S = 13 a0=S=13
  • (2)分别计算

S 1 = ( 13 + 10 ∗ 1 + 2 ∗ 1 2 )   m o d   17 = 8 S 2 = ( 13 + 10 ∗ 2 + 2 ∗ 2 2 )   m o d   17 = 7 S 3 = ( 13 + 10 ∗ 3 + 2 ∗ 3 2 )   m o d   17 = 10 S 4 = ( 13 + 10 ∗ 4 + 2 ∗ 4 2 )   m o d   17 = 0 S 5 = ( 13 + 10 ∗ 5 + 2 ∗ 5 2 )   m o d   17 = 11 \begin{array}{l} S_{1}=\left(13+10 * 1+2 * 1^{2}\right) \bmod 17=8 \\ S_{2}=\left(13+10 * 2+2 * 2^{2}\right) \bmod 17=7 \\ S_{3}=\left(13+10 * 3+2 * 3^{2}\right) \bmod 17=10 \\ S_{4}=\left(13+10 * 4+2 * 4^{2}\right) \bmod 17=0 \\ S_{5}=\left(13+10 * 5+2 * 5^{2}\right) \bmod 17=11 \end{array} S1=(13+101+212)mod17=8S2=(13+102+222)mod17=7S3=(13+103+232)mod17=10S4=(13+104+242)mod17=0S5=(13+105+252)mod17=11

(3)将 ( S i , i ) (S_i, i) (Si,i)作为钥匙分发给第 i i i个参与者。

II 秘密重构

(1)收集任意 t = 3 t = 3 t=3个参与者的钥匙,例如第1个人的(8, 1),第2个人的(7, 2),第5个人的(11, 5);

(2)列出方程
f ( x ) = ∑ i S i ∏ j ≠ i ( x − x j ) ∏ j ≠ i ( x i − x j )   m o d   p = ( 8 ( x − 2 ) ( x − 5 ) ( 1 − 2 ) ( 1 − 5 ) + 7 ( x − 1 ) ( x − 5 ) ( 2 − 1 ) ( 2 − 5 ) + 11 ( x − 1 ) ( x − 2 ) ( 5 − 1 ) ( 5 − 2 ) )   m o d   17 \begin{array}{l} f(x) &=& \sum_{i} \frac{S_i \prod_{j \neq i} (x - x_j)}{\prod_{j \neq i} (x_i - x_j)} \bmod p \\ &=&(\frac{8(x - 2)(x-5)}{(1-2)(1-5)} + \frac{7(x - 1)(x-5)}{(2-1)(2-5)} + \frac{11(x - 1)(x-2)}{(5-1)(5-2)}) \bmod 17 \\ \end{array} f(x)==ij=i(xixj)Sij=i(xxj)modp((12)(15)8(x2)(x5)+(21)(25)7(x1)(x5)+(51)(52)11(x1)(x2))mod17
计算 S = f ( 0 ) = 13 S = f(0) = 13 S=f(0)=13

或者列出方程组:
a 0 + a 1 ∗ ( 1   m o d   17 ) + a 2 ∗ ( 1 2   m o d   17 ) = 8 a 0 + a 1 ∗ ( 2   m o d   17 ) + a 2 ∗ ( 2 2   m o d   17 ) = 7 a 0 + a 1 ∗ ( 5   m o d   17 ) + a 2 ∗ ( 5 2   m o d   17 ) = 11 \begin{array}{l} a_0 + a_1 * (1 \bmod 17) + a_2 * (1^2 \bmod 17) = 8 \\ a_0 + a_1 * (2 \bmod 17) + a_2 * (2^2 \bmod 17) = 7 \\ a_0 + a_1 * (5 \bmod 17) + a_2 * (5^2 \bmod 17) = 11 \\ \end{array} a0+a1(1mod17)+a2(12mod17)=8a0+a1(2mod17)+a2(22mod17)=7a0+a1(5mod17)+a2(52mod17)=11
求解方程组,得到 a 0 = 13 , a 1 = 10 , a 2 = 2 a_0 = 13, a_1 = 10, a_2 = 2 a0=13,a1=10,a2=2,则 S = a 0 = 13 S = a_0 = 13 S=a0=13

4 代码

package com.duwei.crypto;

import java.math.BigInteger;
import java.util.Random;

/**
 * @BelongsProject: Secure_Aggregation
 * @BelongsPackage: com.duwei.crypto
 * @Author: duwei
 * @Date: 2022/4/28 16:37
 * @Description: Shamir秘密共享方法
 */
public class SecretShare {
    private static BigInteger p;
    private static Random random;

    /**
     * 秘密分享算法
     *
     * @param secret 秘密
     * @param m      系统总用户数
     * @param t      秘密分享的阈值
     * @return m个用户的秘密数组
     */
    public static BigInteger[] share(BigInteger secret, int m, int t) {
        //储存t - 1次多项系系数
        BigInteger[] coefficients = new BigInteger[t];
        coefficients[0] = secret;
        for (int i = 1; i < t; i++) {
            coefficients[i] = generateRandomBigInteger();
        }

        BigInteger[] userShares = new BigInteger[m];
        //进行秘密分享
        for (int i = 0; i < m; i++) {
            userShares[i] = computeShare(coefficients, (i + 1));
        }

        return userShares;
    }

    /**
     * 为指定用户计算秘密份额
     *
     * @param coefficients 系数向量
     * @param userIndex    用户索引,即对于用户的x值
     *                     这里计算f(x)时x取值为 (下标 + 1)
     *                     如果直接从下标开始不加1会 直接暴露出 f(0)即秘密
     * @return
     */
    public static BigInteger computeShare(BigInteger[] coefficients, int userIndex) {
        BigInteger index = new BigInteger(String.valueOf(userIndex));
        int len = coefficients.length;
        BigInteger temp = BigInteger.ONE;
        BigInteger result = BigInteger.ZERO;
        for (int i = 0; i < len; i++) {
            BigInteger cur = coefficients[i].multiply(temp);
            temp = temp.multiply(index);
            result = result.add(cur).mod(p);
        }
        return result.mod(p);
    }

    /**
     * 生成小于p的随机数
     *
     * @return
     */
    public static BigInteger generateRandomBigInteger() {
        BigInteger result;
        do {
            result = new BigInteger(p.bitLength(), random);
        } while ((result.compareTo(p) >= 0) && (result.compareTo(BigInteger.ZERO) != 0));
        return result;
    }

    /**
     * 初始化方法,指定模数的bit长度
     * @param bitLen
     */
    public static void init(int bitLen) {
        random = new Random();
        p = BigInteger.probablePrime(bitLen,random);
    }

    /**
     * 秘密重建算法
     *
     * @param shares 用户输入的秘密
     * @param t      可以恢复秘密的阈值
     * @return
     */
    public static BigInteger reconstruction(BigInteger[] shares, int t) throws Exception {
        int n = shares.length;
        if (t > n) {
            throw new Exception("你当前收集的秘密份额不足以恢复秘密");
        }
        BigInteger result = new BigInteger("0");
        for (int i = 0; i < t; i++) {
            result = result.add(interpolation(shares, i + 1, t));
        }

        return result.mod(p);
    }

    /**
     * 求第i号用户(xK = i + 1)的了拉格朗日插值
     *
     * @param values
     * @param t
     * @return
     */
    public static BigInteger interpolation(BigInteger[] values, int xK, int t) {
        BigInteger result;
        //常量0,计算f(0)
        BigInteger zero = BigInteger.ZERO;
        BigInteger x_k = new BigInteger(String.valueOf(xK));
        //拉格朗日多项式
        BigInteger up = BigInteger.ONE;
        BigInteger down = BigInteger.ONE;
        //i代表第i个用户的份额
        for (int i = 0; i < t; i++) {
            BigInteger x_i = new BigInteger(String.valueOf((i + 1)));
            if (x_i.equals(x_k)) {
                continue;
            }
            up = up.multiply(zero.subtract(x_i));
            down = down.multiply(x_k.subtract(x_i));
        }
        result = up.multiply(down.modInverse(p));
        result = result.multiply(values[xK - 1]);
        return result;
    }

    public static void main(String[] args) throws Exception {
        init(1024);
        int times = 1000;
        System.out.println("测试开始.....");
        for (int i = 0;i < times;i++){
            //生成小于p的随机秘密
            BigInteger secret = generateRandomBigInteger();
            int m = (int) (Math.random() * 100 ) + 5;
            int t = (int) (Math.random() * 50 ) + 1;
            //阈值必须小于总用户数
            while (t > m){
                t = (int) (Math.random() * 50 ) + 1;
            }

            BigInteger[] shares = share(secret, m, t);
            BigInteger reconstruction = reconstruction(shares, t);
            if (reconstruction.compareTo(secret) != 0){
                System.out.println("秘密值恢复错误");
            }
        }
        System.out.println("测试结束.....");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HenrySmale

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值