文档

以加密的方式接入模型推理功能

更新时间:

在模型推理链路中,当用户需要对请求体中的input字段值进行加密以确保输入的安全性时,可以参考本文档通过加密方式接入模型推理功能。本指导适用于需要自定义密钥的场景。

步骤1:获取RSA的公钥

请参考获取RSA的公钥获取public_key和public_key_id。

步骤2:生成AES密钥

//获取KeyGenerator实例并指定AES算法
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
//通过提供来源强大的随机源的种子来初始化SecureRandom
SecureRandom secureRandom = new SecureRandom();
//初始化KeyGenerator, GCM通常使用128位的块大小,这里指定了256位的AES密钥长度
keyGen.init(256, secureRandom);
//生成密钥
//生成AES密钥
SecretKey secretKey = keyGen.generateKey();
//获取密钥的byte数组
byte[] keyBytes = secretKey.getEncoded();
//对密钥byte数组进行base64编码
String base64Key = Base64.encodeBase64String(keyBytes);

步骤3:从获取的RSA公钥生成PublicKey

public static PublicKey getPublicKeyFromString(String publicKey){
    byte[] keyBytes = Base64.decodeBase64(key);
    X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePublic(spec);
}

步骤4:通过RSA公钥对AES密钥进行加密

public static String encrypt(String base64Key, PublicKey publicKey){
    Cipher cipher = Cipher.getInstance("RSA");
    //1为加密模式
    cipher.init(1, publicKey);
    byte[] encryptedBytes = cipher.doFinal(base64Key.getBytes());
    return Base64.encodeBase64String(encryptedBytes);
}

步骤5:通过AES的GCM模式加密时还需要指定iv,tag

iv默认是MDAwMDAwMDAwMDAw,即12个0经过base64编码后的值。

tag的长度为128。

String iv = "000000000000";
byte[] IV = iv.getBytes();
String base64Iv = Base64.encodeBase64String(IV);
System.out.println("IV:" + base64Iv);

步骤6:AES对输入的input进行加密

input参数说明

//其中plainText为文本类型
byte[] content = plainText.getBytes(StandardCharsets.UTF_8)
//其中plainText为二进制的base64编码结果
byte[] content = Base64.decodeBase64(plainText)

对输入文本 plainText 使用AES-GCM模式加密,并将结果编码为Base64字符串

public static String encrypt(byte[] content, String key, String iv) {
    // 创建密码器
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    // 初始化为加密模式的密码器
    GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, 
    Base64.decodeBase64(iv));
    //1为加密模式
    cipher.init(1, new 
        SecretKeySpec(Base64.decodeBase64(key), "AES"), gcmParameterSpec);
    // 加密
    byte[] result = cipher.doFinal(content);
    //通过Base64转码返回
    return Base64.encodeBase64String(result);
}

步骤7:AES对输出的output进行解密

解密操作示例。

//byte[] content = Base64.decodeBase64(cipherBody)
public static byte[] decrypt(byte[] content, String key, String iv) {
    //实例化
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    //使用密钥初始化,设置为解密模式
    GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, 
        Base64.decodeBase64(iv));
    //2为解密模式
    cipher.init(2, new 
        SecretKeySpec(Base64.decodeBase64(key), "AES"), 
            gcmParameterSpec);
    //执行操作
    return cipher.doFinal(content);
}

解密结果示例。

//解密的结果
//二进制
String plainText = Base64.encodeBase64String(bodyPlainByte);
//文本
String plainText = new String(bodyPlainByte, StandardCharsets.UTF_8);

核心代码示例

以下为核心代码示例,并非完整可运行的代码。

String publicKey = "MIIBIjANBgkq***hDAQAB";  //替换为实际获取的值 
String publicKeyId = "1703591764000";  //替换为实际获取的值
String iv = "MDAwMDAwMDAwMDAw";
//生成AES密钥
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = new SecureRandom();
keyGen.init(256, secureRandom);
SecretKey secretKey = keyGen.generateKey();
byte[] keyBytes = secretKey.getEncoded();
String base64Key = Base64.encodeBase64String(keyBytes);
//使用公钥对AES进行加密
byte[] keyBytes = Base64.decodeBase64(publicKey);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pubKey = kf.generatePublic(spec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(1, pubKey);
byte[] encryptedBytes = cipher.doFinal(base64Key.getBytes());
String encryptAesKey = Base64.encodeBase64String(encryptedBytes);
//对推理链路中请求的body中input字段的值进行加密, 其中palinTest为input字段的值
byte[] content = plainText.getBytes(StandardCharsets.UTF_8);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, 
Base64.decodeBase64(iv));
cipher.init(1, new 
        SecretKeySpec(Base64.decodeBase64(key), "AES"), gcmParameterSpec);
byte[] result = cipher.doFinal(content);
String encryptInput = Base64.encodeBase64String(result);
//请求推理
OkHttpClient okHttpClient = new OkHttpClient().newBuilder().build();
JSONObject jsonBody = new JSONObject();
        jsonObject.put("model", "qwen-max");
        jsonObject.put("input", encryptInput);
RequestBody body = RequestBody.create(
MediaType.parse("application/json"), jsonBody.toJSONString());
JSONObject headerJson = new JSONObject();
headerJson.put("Content-Type", "application/json");
headerJson.put("Accept", "application/json");
headerJson.put("Authorization", "xxx");
String encryptHeaderValue = "{\"public_key_id\": \""+ publicKeyId +"\",}";
encryptHeaderValue = encryptHeaderValue + 
"\"encrypt_key\": \""+ encryptAesKey +"\", \"iv\": \""+ iv +"\"}";
headerJson.put("X-DashScope-EncryptionKey", encryptHeaderValue);
Headers headers = Headers.of(JSONObject.parseObject(headerJson.toString(), Map.class);
String url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation?request_id=test_222_444";
Request request = new Request.Builder()
                .url(url)
                .post(body)
                .headers(headers)
                .build();
String response = okHttpClient.newCall(request).execute().body().string():
JSONObject responseJson = JSONObject.parseObject(reponse, JSONObject.class);
String outputCipher= responseJson.getString("output");
//解密
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding")
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, 
    Base64.decodeBase64(iv))
    cipher.init(2, new 
        SecretKeySpec(Base64.decodeBase64(base64Key), "AES"), 
            gcmParameterSpec);
byte[] outputCipherContent = Base64.decodeBase64(outputCipher)
String plainOutput = Base64.encodeBase64String(cipher.doFinal(outputCipherContent));
System.out.println("输出的内容是:" + plainOutput);