{"id":16874588,"url":"https://github.com/joway/jpbc_optimize_ibe","last_synced_at":"2025-04-11T11:32:01.385Z","repository":{"id":75055760,"uuid":"55274982","full_name":"joway/JPBC_Optimize_IBE","owner":"joway","description":"JPBC_Optimize_IBE by JPBC","archived":false,"fork":false,"pushed_at":"2019-04-09T10:29:12.000Z","size":23071,"stargazers_count":22,"open_issues_count":2,"forks_count":9,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-25T07:51:12.721Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joway.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-04-02T03:05:16.000Z","updated_at":"2024-11-13T01:52:45.000Z","dependencies_parsed_at":"2023-02-24T03:30:24.510Z","dependency_job_id":null,"html_url":"https://github.com/joway/JPBC_Optimize_IBE","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joway%2FJPBC_Optimize_IBE","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joway%2FJPBC_Optimize_IBE/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joway%2FJPBC_Optimize_IBE/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joway%2FJPBC_Optimize_IBE/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joway","download_url":"https://codeload.github.com/joway/JPBC_Optimize_IBE/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248383886,"owners_count":21094624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T15:33:22.650Z","updated_at":"2025-04-11T11:32:01.365Z","avatar_url":"https://github.com/joway.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"### 前言\n\n这段时间由于竞赛需要学习了JPBC库的使用， 不得不说，虽然此库极其强大，然而由于毕竟这块没有像那些大规模商用的东西那样流行，所以网上无论是英文还是中文的资料都极为稀少，官方文档也语焉不详。折腾了快半个月才把它大致搞懂，所以想把过程写下来，方便他人学习使用，如有错误，望指出。\n\n\n### 背景知识:\n\n#### 双线性群初始化:\n\n- 质数阶双线性群（Prime-Order Bilinear Groups）；\n- 合数阶双线性群（Composite-Order Bilinear Groups）；\n\n#### 双线性群运算 :\n\n- 指数群 Zr的加法和乘法\n- 双线性群$G_1$,$G_2$的乘法和指数幂\n- 目标群$G_T$乘法和指数幂\n- 双线性群$G_1$,$G_2$映射到目标群$G_T$的对（Pairing）运算；\n\n\n#### 质数阶双线性群（Prime-Order Bilinear Groups）\n\n给定一个大质数p，$G_1$,$G_2$,$G_T$ 均是阶为p的乘法循环群，e 为双线性映射 e : $G_1$ x $G_2$ -\u003e $G_T$\n\n对称双线性映射: $G_1$ = $G_2$ 即 e : $G_1$ x $G_1$ -\u003e $G_T$\n\n更多知识，请查阅相关文献和维基百科。\n\n#### JPBC中的双线性\n在JPBC中， G1,G2是乘法循环群。\n\n且G1,G2的元素都是一个个点坐标(基于椭圆曲线)，而$G_T$是$Z_p$中的一个数。\n\n### JPBC 使用\n\n#### 初始化\n\n在所有操作之前， 都必须有对双线性群进行初始化。[官方文档](http://gas.dia.unisa.it/projects/jpbc/docs/pairing.html#.Vv8hsi594p8)对各个参数进行了详细说明。这里我使用A群， 建立 jpbc.properties 文件， 内容如下:\n\n\ttype=a\n\tq 8780710799663312522437781984754049815806883199414208211028653399266475630880222957078625179422662221423155858769582317459277713367317481324925129998224791\n\th 12016012264891146079388821366740534204802954401251311822919615131047207289359704531102844802183906537786776\n\tr 730750818665451621361119245571504901405976559617\n\texp2 159\n\texp1 107\n\tsign1 1\n\tsign0 1\n\t\n参数说明:\n\t- type : 指定椭圆曲线的种类\n\t- q : G群的阶数的比特长度\n\n\t\n#### 产生随机数:\n\n``` java\n\t//随机产生一个Z_p群的元素\n\tElement Z_p = pairing.getZr().newRandomElement().getImmutable();\n\t//随机产生一个G_1群的元素\n\tElement G_1 = pairing.getG1().newRandomElement().getImmutable();\n\t//随机产生一个G_2群的元素\n\tElement G_2 = pairing.getG2().newRandomElement().getImmutable();\n\t//随机产生一个G_T群的元素\n\tElement G_T = pairing.getGT().newRandomElement().getImmutable();\n\t\n```\n\n#### 将指定的元素哈希到双线性群中 :\n\n``` java\n//将byte[] byteArray_Z_p哈希到Z_p群\nElement hash_Z_p = pairing.getZr().newElement().setFromHash(byteArray_Z_p, 0, byteArray_Z_p.length);\n//将byte[] byteArray_G_1哈希到G_1群\nElement hash_G_1 = pairing.getG1().newElement().setFromHash(byteArray_G_1, 0, byteArray_G_1.length);\n//将byte[] byteArray_G_2哈希到G_2群\nElement hash_G_2 = pairing.getG2().newElement().setFromHash(byteArray_G_2, 0, byteArray_G_2.length);\n//将byte[] byteArray_G_T哈希到G_T群\nElement hash_G_T = pairing.getGT().newElement().setFromHash(byteArray_G_T, 0, byteArray_G_T.length);\n```\n\n#### 双线性群的运算\n\n``` java\n//初始化相关参数\nElement G_1 = pairing.getG1().newRandomElement().getImmutable();\nElement G_2 = pairing.getG2().newRandomElement().getImmutable();\nElement Z = pairing.getZr().newRandomElement().getImmutable();\nElement G_T = pairing.getGT().newRandomElement().getImmutable();\n\t\nElement G_1_p = pairing.getG1().newRandomElement().getImmutable();\nElement G_2_p = pairing.getG2().newRandomElement().getImmutable();\nElement Z_p = pairing.getZr().newRandomElement().getImmutable();\nElement G_T_p = pairing.getGT().newRandomElement().getImmutable();\n\t\n//G_1的相关运算\n//G_1 multiply G_1\nElement G_1_m_G_1 = G_1.mul(G_1_p);\n//G_1 power Z\nElement G_1_e_Z = G_1.powZn(Z);\n\t\n//G_2的相关运算\n//G_2 multiply G_2\nElement G_2_m_G_2 = G_2.mul(G_2_p);\n//G_2 power Z\nElement G_2_e_Z = G_2.powZn(Z);\n\t\n//G_T的相关运算\n//G_T multiply G_T\nElement G_T_m_G_T = G_T.mul(G_T_p);\n//G_T power Z\nElement G_T_e_Z = G_T.powZn(Z);\n\t\n//Z的相关运算\n//Z add Z\nElement Z_a_Z = Z.add(Z_p);\n//Z multiply Z\nElement Z_m_Z = Z.mul(Z_p);\n\t\n//Pairing运算\nElement G_p_G = pairing.pairing(G_1, G_2); \n```\n\n### 使用JPBC中，可能会需要用到的其它函数:\n\n由于JPBC并不是一个完整的密码学库，仅仅实现了双线性映射相关的部分。在实现一些密码学算法的时候，需要用到一些其它函数，而这些函数的参数与JPBC的基本参数类型Element又不是匹配的，一开始并不知道直接调用toBytes()就行了，所以纠结了好久。\n\n我用一个Utils类封装了一些常用函数，以便后续调用:\n\n``` java\npublic class Utils {\n\t\n    /**\n     * 标准sha256加密\n     *\n     * @param data\n     * @return hash\n     */\n    public static byte[] sha256(byte[] data) {\n        //Create a sha 256 of the message\n        SHA256Digest dgst = new SHA256Digest();\n        dgst.reset();\n        dgst.update(data, 0, data.length);\n        int digestSize = dgst.getDigestSize();\n        byte[] hash = new byte[digestSize];\n        dgst.doFinal(hash, 0);\n        return hash;\n    }\n\t\n\t\n    public static String bytesToHex(byte[] bytes) {\n        return org.apache.commons.codec.binary.Hex.encodeHexString(bytes);\n    }\n\t\n    public static byte[] hexToBytes(String s) {\n        int len = s.length();\n        byte[] data = new byte[len / 2];\n        for (int i = 0; i \u003c len; i += 2) {\n            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) \u003c\u003c 4)\n                    + Character.digit(s.charAt(i + 1), 16));\n        }\n        return data;\n    }\n\t\n    public static byte[] xor(byte[] a, byte[] b) {\n        byte[] result = new byte[Math.min(a.length, b.length)];\n        for (int i = 0; i \u003c result.length; i++) {\n            result[i] = (byte) (((int) a[i]) ^ ((int) b[i]));\n        }\n        return result;\n    }\n\t\n    // 把一个byte[] 分拆成每段256字节的数组List\n    public static ArrayList\u003cbyte[]\u003e slice(byte[] msg) {\n\t\n        ArrayList\u003cbyte[]\u003e list = new ArrayList\u003cbyte[]\u003e();\n\t\n        // 待优化\n        // boxCount 表示分组数目\n        int boxCount = ((msg.length % SystemParameter.SIZE) == 0)\n                ? (msg.length / SystemParameter.SIZE) :\n                ((msg.length / SystemParameter.SIZE) + 1);\n\t\n        for (int i = 0; i \u003c boxCount - 1; ++i) {\n            list.add(Arrays.copyOfRange(msg,\n                    i * SystemParameter.SIZE, (i + 1) * SystemParameter.SIZE));\n        }\n        list.add(Arrays.copyOfRange(msg,\n                (boxCount - 1) * SystemParameter.SIZE, msg.length));\n        return list;\n    }\n\t\n    // 数组list组装成单个的byte[]\n    public static byte[] splice(ArrayList\u003cbyte[]\u003e byteMessage) {\n\t\n        int boxCount = byteMessage.size();\n\t\n        // byteSum 表示总字节数大小\n        int byteSum = (SystemParameter.SIZE * (boxCount - 1)) +\n                byteMessage.get(boxCount - 1).length;\n        byte[] temp = new byte[byteSum];\n\t\n        for (int i = 0; i \u003c boxCount - 1; ++i) {\n            for (int t = 0; t \u003c SystemParameter.SIZE; ++t) {\n                temp[i * SystemParameter.SIZE + t] = byteMessage.get(i)[t];\n            }\n        }\n        for (int i = 0; i \u003c byteMessage.get(boxCount - 1).length; ++i) {\n            temp[SystemParameter.SIZE * (boxCount - 1) + i] =\n                    byteMessage.get(boxCount - 1)[i];\n        }\n        return temp;\n    }\n\t\n\t\n    public static String toString(ArrayList\u003cbyte[]\u003e byteMessage) {\n        return new String(splice(byteMessage));\n    }\n\t\n}\n\n```\n\n上面包含了哈希和异或函数，以及一个把明文密文分拆给一个List以及组装回去的函数。\n\n### 注意点\n\n1. Java的运算结果都是产生一个新的Element来存储，所以我们需要把运算结果赋值给一个新的Element；\n2. Java在进行相关运算时，参与运算的Element值可能会改变。所以，如果需要在运算过程中保留参与运算的Element值，\n   在存储的时候一定要调用getImmutable()\n3. 为了保险起见，防止Element在运算的过程中修改了Element原本的数值，可以使用Element.duplicate()方法。\n   这个方法将返回一个与Element数值完全一样的Element，但是是个新的Element对象。\n\n\n\n### 参考资料\n\n[Java密码学原型算法实现——第三部分：双线性对](http://blog.csdn.net/liuweiran900217/article/details/45080653)\n\n[JPBC DOC](http://gas.dia.unisa.it/projects/jpbc/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoway%2Fjpbc_optimize_ibe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoway%2Fjpbc_optimize_ibe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoway%2Fjpbc_optimize_ibe/lists"}