package bce.jni.natives; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; /** * <p>Boneh-Gentry-Waters Broadcast Encryption (BCE) JNI wrapper</p> * <p> * This is the most udnerlying JNI wrapper of libbcejni, all native methods of * libbcejni are defined here. * </p> * <p> * BCE has the standard 4 phases for describing a public key cryptographic system: * <ul> * <li>Setup</li> * <li>KeysGeneration</li> * <li>Encrypt</li> * <li>Decrypt</li> * </ul> * Besides, changeEncryptionProduct and changeDecryptionProduct is BCE specific, and * they implemented the dynamically adding and revoking users in a BCE crypto group * features. * This feature has been described and proved in Boneh-Gentry-Waters BCE scheme. * </p> * @author Yingquan */ public final class BCENative { private BCENative() {} private static final String LIBNAME = "libbcejni"; private static final String CONFNAME = "d201.param"; static { String runtimeDirName = createRuntimeDirectory(); writeConf(runtimeDirName, CONFNAME); String libPath = writeLibrary(runtimeDirName, LIBNAME, getLibSuffix()); System.load(libPath); } /** * Set up the runtime directory, and returns the name of the runtime * native library directory */ private static String createRuntimeDirectory() { File libRuntimeDir = new File("/tmp/libbcejni.run"); // pre-clean if (libRuntimeDir.exists() && libRuntimeDir.isDirectory()) { libRuntimeDir.delete(); } libRuntimeDir.mkdir(); return libRuntimeDir.getAbsolutePath(); } /** * Returns the platform dependent suffix of the native library */ private static String getLibSuffix() { final String osName = System.getProperty("os.name").toLowerCase(); if (osName.contains("mac")) return "jnilib"; else if (osName.contains("linux")) return "so"; else throw new RuntimeException("Unsupported OS type"); } /** * Externalize the d201.param configuration file */ private static void writeConf(String outPath, String confName) { final String confAbsoluteName = String.format("%s/%s", outPath, confName); unpackFromJar(confName, confAbsoluteName); } /** * Externalize the native library file, and returns its absolute path */ private static String writeLibrary(String outPath, String libName, String suffix) { final String libFullName = String.format("%s.%s", libName, suffix); final String libAbsoluteName = String.format("%s/%s", outPath, libFullName); unpackFromJar(libFullName, libAbsoluteName); return libAbsoluteName; } /** * Unpack file 'fileNameInJar' to 'fileNameExtern' */ private static void unpackFromJar(String fileNameInJar, String fileNameExtern) { InputStream in = null; FileOutputStream out = null; try { in = BCENative.class.getResourceAsStream("/" + fileNameInJar); out = new FileOutputStream(new File(fileNameExtern)); byte[] buf = new byte[128]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); out.flush(); } } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("Caught IOException: " + e.getMessage()); } finally { if (in != null) { try { in.close(); } catch (IOException ei) {} } if (out != null) { try { out.close(); } catch (IOException eo) {} } } } /** * Initializes a BCE system, and generates the BCE environment parameters. * This method will load a elliptic curve parameters file, and generates * 2 BCE system parameters files. * * @param curveFileName The absolute name of the curve parameter file * @param numUser The user number of the current BCE system instance, must be times of 8 * @param sysParamsPath 用于指定BCE系统参数的生成绝对路径 * @param globalParamsPath 用于指定BCE全局系统参数的生成绝对路径 * @param sysPrivKey_out 用于返回即将被销毁的用户私钥 * @return 返回0:执行成功;其他整型数:出错参数索引;其中,负值表示JNI层错误码;正值表示业务层错误码。 */ public static native int setup(byte[] curveFileName, int numUser, byte[] sysParamsPath, byte[] globalParamsPath, byte[] sysPrivKey_out); /** * 从广播加密系统参数文件中读取参数,为指定批次用户生成私钥参数 * * @param sysParamsPath BCE系统参数文件绝对路径 * @param sysPrivKey 用户临时私钥,使用后必须销毁 * @param numUser 广播加密系统用户总人数 * @param startIndex 当前批次中第一个用户的索引 * @param length 该批次操作用户批量 * @param userPrivKeys_out 二维byte数组,用于返回当前批次操作后生成的用户私钥参数,字节格式 * @return 返回0:执行成功;其他整型数:出错参数索引;其中,负值表示JNI层错误码;正值表示业务层错误码。 */ public static native int genPrivateKeys(byte[] sysParamsPath, byte[] sysPrivKey, int numUser, int startIndex, int length, byte[][] userPrivKeys_out); /** * 加密函数,“广播”一次密文,为系统中所有合法用户生成一个共享密文块 * * @param sysParamsPath BCE系统参数文件绝对路径 * @param CT_C0_out 用于返回密文块中第一段密文体 * @param CT_C1_out 用于返回密文块中第二段密文体 * @param symmetricKey_out 用于返回广播加密系统生成的对称密钥,即消息加密密钥 * @return 返回0:执行成功;其他整型数:出错参数索引;其中,负值表示JNI层错误码;正值表示业务层错误码。 */ public static native int encrypt(byte[] sysParamsPath, byte[] CT_C0_out, byte[] CT_C1_out, byte[] symmetricKey_out); /** * 解密函数,客户端用户读取自己的系统参数文件(包含椭圆参数),构建解密环境,用其专有的私钥完成解密 * * @param globalParamsPath BCE客户端系统参数文件名(包含椭圆参数),绝对路径 * @param userPrivKey 用户私钥,由私钥文件各字段拼接成的字节块 * @param CT_C0 密文块中第一段密文体 * @param CT_C1 密文快中第二段密文体 * @param symmetricKey_out 用于返回广播加密系统客户端解密出的对称密钥,即消息加密密钥 * @return 返回0:执行成功;其他整型数:出错参数索引;其中,负值表示JNI层错误码;正值表示业务层错误码。 */ public static native int decrypt(byte[] globalParamsPath, byte[] userPrivKey, byte[] CT_C0, byte[] CT_C1, byte[] symmetricKey_out); /** * 根据adds队列与rems队列改变广播加密系统服务器端的加密产品 * * @param sysParamsPath BCE系统参数文件绝对路径 * @param adds 新增用户队列,其长度由nAdds指定 * @param nAdds 指定adds队列长度,注意一定要设为正确的值,建议使用前检查 * @param rems 失效用户队列,起长度由nRems指定 * @param nRems 指定rems队列长度,注意一定要设为正确的值,建议使用前检查 * @return 返回0:执行成功;其他整型数:出错参数索引;其中,负值表示JNI层错误码;正值表示业务层错误码。 */ public static native int changeEncryptionProduct(byte[] sysParamsPath, int[] adds, int nAdds, int[] rems, int nRems); /** * 根据adds队列与rems队列改变广播加密系统中每个用户私钥中的解密产品 * @param globalParamsPath BCE客户端系统参数文件名(包含椭圆参数),绝对路径 * @param offset 用户索引的起始位置,从1开始 * @param length 当次改变解密产品的批量 * @param adds 新增用户队列,其长度由nAdds指定 * @param nAdds 指定adds队列长度,注意一定要设为正确的值,建议使用前检查 * @param rems 失效用户队列,起长度由nRems指定 * @param nRems 指定rems队列长度,注意一定要设为正确的值,建议使用前检查 * @param decrProdBatch 传入本地方法等待处理的批量用户解密产品 * @param decrProdBatch_out 用于输出处理后更新的批量用户解密产品 * @return 返回0:执行成功;其他整型数:出错参数索引;其中,负值表示JNI层错误码;正值表示业务层错误码。 */ public static native int changeDecryptionProduct(byte[] globalParamsPath, int offset, int length, int[] adds, int nAdds, int[] rems, int nRems, byte[] decrProdBatch, byte[] decrProdBatch_out); }