JAVA FIBE

 public static void setup(String pairingParametersFileName, int U, int d, String pkFileName, String mskFileName) {
        Pairing bp = PairingFactory.getPairing(pairingParametersFileName);
        Element g = bp.getG1().newRandomElement().getImmutable();

        Properties mskProp = new Properties();
        Properties pkProp = new Properties();
        //属性表示为1,2,3,...,U
        //对每个属性i,选取一个随机数ti作为该属性对应的主密钥,并计算相应公钥g^ti
        for (int i = 1; i <= U; i++){
            Element t = bp.getZr().newRandomElement().getImmutable();
            Element T = g.powZn(t).getImmutable();
            mskProp.setProperty("t"+i, Base64.getEncoder().withoutPadding().encodeToString(t.toBytes()));
            pkProp.setProperty("T"+i, Base64.getEncoder().withoutPadding().encodeToString(T.toBytes()));
        }
        //另外选取一个随机数y,计算e(g,g)^y
        Element y = bp.getZr().newRandomElement().getImmutable();
        Element egg_y = bp.pairing(g, g).powZn(y).getImmutable();
        mskProp.setProperty("y", Base64.getEncoder().withoutPadding().encodeToString(y.toBytes()));
        pkProp.setProperty("egg_y", Base64.getEncoder().withoutPadding().encodeToString(egg_y.toBytes()));
        pkProp.setProperty("g", Base64.getEncoder().withoutPadding().encodeToString(g.toBytes()));
        //注意区分数据类型。上面写的数据类型群元素,因此使用了Base64编码。
        //d在实际应用中定义为一个int类型,直接用Integer.toString方法转字符串
        pkProp.setProperty("d", Integer.toString(d));

        storePropToFile(mskProp, mskFileName);
        storePropToFile(pkProp, pkFileName);
    }

    public static void keygen(String pairingParametersFileName, int[] userAttList, String pkFileName, String mskFileName, String skFileName) throws NoSuchAlgorithmException {
        Pairing bp = PairingFactory.getPairing(pairingParametersFileName);

        Properties pkProp = loadPropFromFile(pkFileName);
        String gString = pkProp.getProperty("g");
        Element g = bp.getG1().newElementFromBytes(Base64.getDecoder().decode(gString)).getImmutable();
        String dString = pkProp.getProperty("d");
        int d = Integer.parseInt(dString);

        Properties mskProp = loadPropFromFile(mskFileName);
        String yString = mskProp.getProperty("y");
        Element y = bp.getZr().newElementFromBytes(Base64.getDecoder().decode(yString)).getImmutable();

        //d-1次多项式表示为q(x)=coef[0] + coef[1]*x^1 + coef[2]*x^2 + coef[d-1]*x^(d-1)
        //多项式的系数的数据类型为Zr Element,从而是的后续相关计算全部在Zr群上进行
        //通过随机选取coef参数,来构造d-1次多项式q(x)。约束条件为q(0)=y。
        Element[] coef = new Element[d];
        coef[0] = y;
        for (int i = 1; i < d; i++){
            coef[i] = bp.getZr().newRandomElement().getImmutable();
        }

        Properties skProp = new Properties();
        //计算每个属性对应的私钥g^(q/t),q是多项式在该属性位置的值,t是属性对应的主密钥
        for (int att : userAttList) {
            String tString = mskProp.getProperty("t"+att);
            Element t = bp.getZr().newElementFromBytes(Base64.getDecoder().decode(tString)).getImmutable();
            Element q = qx(bp.getZr().newElement(att), coef, bp.getZr()).getImmutable();
            Element D = g.powZn(q.div(t)).getImmutable();

            skProp.setProperty("D"+att, Base64.getEncoder().withoutPadding().encodeToString(D.toBytes()));
        }
        //将用户属性列表也添加在私钥中
        skProp.setProperty("userAttList", Arrays.toString(userAttList));
        storePropToFile(skProp, skFileName);
    }

    public static void encrypt(String pairingParametersFileName, Element message, int[] messageAttList, String pkFileName, String ctFileName) {
        Pairing bp = PairingFactory.getPairing(pairingParametersFileName);

        Properties pkProp = loadPropFromFile(pkFileName);
        String eggString = pkProp.getProperty("egg_y");
        Element egg_y = bp.getGT().newElementFromBytes(Base64.getDecoder().decode(eggString)).getImmutable();
        //计算密文组件 EP=Me(g,g)^(ys)
        Element s = bp.getZr().newRandomElement().getImmutable();
        Element EP = message.duplicate().mul(egg_y.powZn(s)).getImmutable();

        Properties ctProp = new Properties();
        //针对每个密文属性,计算密文组件 E=T^s
        for (int att : messageAttList) {
            String TString = pkProp.getProperty("T"+att);
            Element T = bp.getG1().newElementFromBytes(Base64.getDecoder().decode(TString)).getImmutable();
            Element E = T.powZn(s).getImmutable();

            ctProp.setProperty("E"+att, Base64.getEncoder().withoutPadding().encodeToString(E.toBytes()));
        }
        ctProp.setProperty("EP", Base64.getEncoder().withoutPadding().encodeToString(EP.toBytes()));
        //密文属性列表也添加至密文中
        ctProp.setProperty("messageAttList", Arrays.toString(messageAttList));
        storePropToFile(ctProp, ctFileName);
    }

    public static Element decrypt(String pairingParametersFileName, String pkFileName, String ctFileName, String skFileName) {
        Pairing bp = PairingFactory.getPairing(pairingParametersFileName);

        Properties pkProp = loadPropFromFile(pkFileName);
        String dString = pkProp.getProperty("d");
        int d = Integer.parseInt(dString);

        Properties ctProp = loadPropFromFile(ctFileName);
        String messageAttListString = ctProp.getProperty("messageAttList");
        //恢复明文消息的属性列表 int[]类型
        int[] messageAttList = Arrays.stream(messageAttListString.substring(1, messageAttListString.length()-1).split(",")).map(String::trim).mapToInt(Integer::parseInt).toArray();

        Properties skProp = loadPropFromFile(skFileName);
        String userAttListString = skProp.getProperty("userAttList");
        //恢复用户属性列表 int[]类型
        int[] userAttList = Arrays.stream(userAttListString.substring(1, userAttListString.length()-1).split(",")).map(String::trim).mapToInt(Integer::parseInt).toArray();

        //判断两个列表重合个数是否小于d
        int[] intersectionAttList = intersection(messageAttList, userAttList);
        System.out.println("重合属性列表:" + Arrays.toString(intersectionAttList));
        System.out.println("重合属性个数为:" + intersectionAttList.length);
        if (intersectionAttList.length < d) {
            System.out.println("不满足解密门限,无法解密!");
            return null;
        }
        //从两个列表中的重合项中取前d项,构成解密属性列表
        int[] decAttList = Arrays.copyOfRange(intersectionAttList, 0, d);
        System.out.println("解密所用属性列表:" + Arrays.toString(decAttList));

        Element denominator = bp.getGT().newOneElement().getImmutable();
        //针对解密属性列表中的每个属性,计算e(D,E)^delta,并将结果连乘
        for (int att : decAttList){
            String EString = ctProp.getProperty("E"+att);
            Element E = bp.getG1().newElementFromBytes(Base64.getDecoder().decode(EString)).getImmutable();

            String DString = skProp.getProperty("D"+att);
            Element D = bp.getG1().newElementFromBytes(Base64.getDecoder().decode(DString)).getImmutable();

            //计算属性对应的拉格朗日因子,作为指数。目标值x为0。
            Element delta = lagrange(att, decAttList, 0, bp.getZr()).getImmutable();
            denominator = denominator.mul(bp.pairing(E,D).powZn(delta));
        }

        String EPString = ctProp.getProperty("EP");
        Element EP = bp.getGT().newElementFromBytes(Base64.getDecoder().decode(EPString)).getImmutable();
        //恢复M=EP除以上述连乘结果
        Element res = EP.div(denominator);
        return res;
    }

 

//计算由coef为系数确定的多项式qx在点x处的值,注意多项式计算在群Zr上进行
    public static Element qx(Element x, Element[] coef, Field Zr){
        Element res = coef[0];
        for (int i = 1; i < coef.length; i++){
            Element exp = Zr.newElement(i).getImmutable();
            //x一定要使用duplicate复制使用,因为x在每一次循环中都要使用,如果不加duplicte,x的值会发生变化
            res = res.add(coef[i].mul(x.duplicate().powZn(exp)));
        }
        return res;
    }

    //求两个数组的交集
    public static int[] intersection(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int length1 = nums1.length, length2 = nums2.length;
        int[] intersection = new int[length1 + length2];
        int index = 0, index1 = 0, index2 = 0;
        while (index1 < length1 && index2 < length2) {
            int num1 = nums1[index1], num2 = nums2[index2];
            if (num1 == num2) {
                // 保证加入元素的唯一性
                if (index == 0 || num1 != intersection[index - 1]) {
                    intersection[index++] = num1;
                }
                index1++;
                index2++;
            } else if (num1 < num2) {
                index1++;
            } else {
                index2++;
            }
        }
        return Arrays.copyOfRange(intersection, 0, index);
    }

    //拉格朗日因子计算 i是集合S中的某个元素,x是目标点的值
    public static Element lagrange(int i, int[] S, int x, Field Zr) {
        Element res = Zr.newOneElement().getImmutable();
        Element iElement = Zr.newElement(i).getImmutable();
        Element xElement = Zr.newElement(x).getImmutable();
        for (int j : S) {
            if (i != j) {
                //注意:在循环中重复使用的项一定要用duplicate复制出来使用
                //这儿xElement和iElement重复使用,但因为前面已经getImmutable所以可以不用duplicate
                Element numerator = xElement.sub(Zr.newElement(j));
                Element denominator = iElement.sub(Zr.newElement(j));
                res = res.mul(numerator.div(denominator));
            }
        }
        return res;
    }

    public static void storePropToFile(Properties prop, String fileName){
        try(FileOutputStream out = new FileOutputStream(fileName)){
            prop.store(out, null);
        }
        catch (IOException e) {
            e.printStackTrace();
            System.out.println(fileName + " save failed!");
            System.exit(-1);
        }
    }

    public static Properties loadPropFromFile(String fileName) {
        Properties prop = new Properties();
        try (FileInputStream in = new FileInputStream(fileName)){
            prop.load(in);
        }
        catch (IOException e){
            e.printStackTrace();
            System.out.println(fileName + " load failed!");
            System.exit(-1);
        }
        return prop;
    }

 public static void main(String[] args) throws Exception {
        int U = 20;
        int d = 5;
        System.out.println("系统解密门限为:" + d);

        int[] userAttList = {1, 5, 3, 6, 10, 11};
        int[] messageAttList = {1,  3,  5,  7, 9, 10, 11};

        String dir = "data/";
        String pairingParametersFileName = "a.properties";
        String pkFileName = dir + "pk.properties";
        String mskFileName = dir + "msk.properties";
        String skFileName = dir + "sk.properties";
        String ctFileName = dir + "ct.properties";

        setup(pairingParametersFileName, U, d, pkFileName, mskFileName);

        keygen(pairingParametersFileName, userAttList, pkFileName, mskFileName, skFileName);

        Element message = PairingFactory.getPairing(pairingParametersFileName).getGT().newRandomElement().getImmutable();
        System.out.println("明文消息:" + message);
        encrypt(pairingParametersFileName, message, messageAttList, pkFileName, ctFileName);

        Element res = decrypt(pairingParametersFileName, pkFileName, ctFileName, skFileName);
        System.out.println("解密结果:" + res);
        if (message.isEqual(res)) {
            System.out.println("成功解密!");
        }
    }

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值