pailler算法加密后如何进行密文计算-java

1. 背景

工作中需要用到密文计算,涉及密文求和sum、平均avg以及加权平均wavg 。特此分享,供参考。

2. 代码

2.1 分数类MyFraction

涉及小数运算,但是密文目前只能存整数,所以考虑用分数来处理。用分数对象来存储分子和分母,分子是密文,分母是明文,通分时正好可以利用密文的标量乘。

public class MyFraction {
    // cipher son
    private BigInteger fson = new BigInteger("0");
    // mon
    private BigInteger fmon = new BigInteger("1");
    // 密文计算器
    private CipherCompute cc = null;

    //
    public MyFraction(BigInteger fson, BigInteger fmon, CipherCompute cc) {
        this.fson = fson;
        this.fmon = fmon;
        this.cc = cc;
    }

    public MyFraction(BigInteger fson, CipherCompute cc) {
        this.fson = fson;
        this.cc = cc;
    }

    public MyFraction(BigInteger fson) {
        this.fson = fson;
    }

    public MyFraction() {
    }

    // 通分后加
    public MyFraction add(MyFraction mf) {
        if (null == mf) return new MyFraction();

        // 求分母最小公倍数
        BigInteger lcm = fmon.multiply(mf.getFmon()).divide(fmon.gcd(mf.getFmon()));
        // 分别要乘的系数
        BigInteger son_m = lcm.divide(fmon);
        BigInteger son_n = lcm.divide(mf.getFmon());

        // 计算分子,分母
        BigInteger mid1 = cc.cipher_multiply(fson, son_m);
        BigInteger mid2 = cc.cipher_multiply(mf.getFson(), son_n);
        BigInteger res_son = cc.cipher_add(mid1, mid2);
        BigInteger res_mon = lcm;
        MyFraction res = new MyFraction(res_son, res_mon, cc);
        return res;

    }

    // 对数组中每一个MyFraction累加
    public MyFraction sum(MyFraction[] mfarr) {
        if (null == mfarr) return new MyFraction(BigInteger.ZERO, BigInteger.ONE, cc);

        int len = mfarr.length;
        if (0 == len) return new MyFraction(BigInteger.ZERO, BigInteger.ONE, cc);
        if (1 == len) return mfarr[0];

        MyFraction res = mfarr[0];
        for (int i=1; i < len; i++) {
            res = res.add(mfarr[i]);
        }
        return res;
    }

    // 只能标量乘,注意先后顺序,否则解密有问题、
    // 也就是只能乘明文
    public MyFraction multiply(MyFraction mf) {
        BigInteger res_son = cc.cipher_multiply(fson, mf.getFson());
        BigInteger res_mon = fmon.multiply(mf.getFmon());
        MyFraction res = new MyFraction(res_son, res_mon, cc);
        return res;
    }

    // 取平均
    public MyFraction avg(MyFraction[] mfarr) {
        int len = mfarr.length;
        if (0 == len) return new MyFraction();

        BigInteger blen = new BigInteger(String.valueOf(len));
        MyFraction[] brr = new MyFraction[len];
        for (int i =0; i < len; i++) {
            brr[i] = new MyFraction(mfarr[i].getFson(), mfarr[i].getFmon().multiply(blen), cc);
        }
        return sum(brr);
    }

    // 加权计算,注意这里mfa2数组,权重分数都是明文,不支持密文。
    public MyFraction wavg(MyFraction[] mfa1, MyFraction[] mfa2) {
        if (mfa1.length != mfa2.length) {
            System.out.println("param error, the length of two arrays not equal.");
            return new MyFraction();
        }
        MyFraction[] mfa3 = new MyFraction[mfa1.length];
        for (int i=0; i < mfa1.length; i++) {
            mfa3[i] = mfa1[i].multiply(mfa2[i]);
        }
        return sum(mfa3);
    }

    // String数组转 MyFraction数组
    public MyFraction[] parseStringArray(String[] srr) {
        int len = srr.length;
        if (0 == len) return new MyFraction[0];
        MyFraction[] mfarr = new MyFraction[len];
        for (int i=0; i < len; i++ ) {
            mfarr[i] = new MyFraction(new BigInteger(srr[i]), BigInteger.ONE, cc);
        }
        return mfarr;
    }

    @Override
    public String toString() {
        return "MyFraction{" +
                "fson=" + fson +
                ", fmon=" + fmon +
                ", cc=" + cc +
                '}';
    }

    public BigInteger getFson() {
        return fson;
    }

    public void setFson(BigInteger fson) {
        this.fson = fson;
    }

    public BigInteger getFmon() {
        return fmon;
    }

    public void setFmon(BigInteger fmon) {
        this.fmon = fmon;
    }

    public CipherCompute getCc() {
        return cc;
    }

    public void setCc(CipherCompute cc) {
        this.cc = cc;
    }
}

2.2 密文计算类CipherCompute

public class CipherCompute {

private BigInteger nsquare;

public CipherCompute(BigInteger nsquare) {
    this.nsquare = nsquare;
}

public BigInteger cipher_add(BigInteger em1, BigInteger em2) {
    return em1.multiply(em2).mod(nsquare);
}

public BigInteger cipher_multiply(BigInteger em1, BigInteger m2) {
    return em1.modPow(m2, nsquare);
}

}

3. 欢迎讨论

posted @ 2022-11-13 20:34  钱塘江畔  阅读(72)  评论(0)    收藏  举报