You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby解密Java AES-GCM加密内容时遇OpenSSL::Cipher::CipherError问题

问题描述

对接第三方服务商时,对方采用AES/GCM/NoPadding加密方式,用Ruby解密时抛出OpenSSL::Cipher::CipherError错误。发现Java端使用16字节全零数组作为IV,但自己误以为Ruby仅支持12字节IV,不清楚问题根源。

对方Java加密代码:

SecretKey sessionKey = getSessionKey();
byte[] IV = new byte[16];
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(sessionKey.getEncoded(), "AES");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(16 * 8, IV);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec);
byte[] encryptedText = cipher.doFinal(plaintext);
responseMap.put("data", Base64.getEncoder().encodeToString(encryptedText));

自己的Ruby解密代码:

decrypted_key = "AES KEY"
decode_data = Base64.strict_decode64(params["data"])
cipher_text_with_auth_tag = decode_data.unpack("C*")
auth_tag = cipher_text_with_auth_tag.last(16).pack("C*")
cipher_text = cipher_text_with_auth_tag[0..-17].pack("c*")
decipher = OpenSSL::Cipher.new('AES-256-GCM')
decipher.decrypt
decipher.padding = 0
decipher.key = decrypted_key
decipher.iv =  "\x00" * 12
decipher.auth_data = ''
decipher.auth_tag = auth_tag
decrypted_data = decipher.update(cipher_text) + decipher.final
问题分析与解决

核心问题:IV不匹配

GCM模式允许12字节(推荐)或其他长度(如16字节)的IV,Ruby的OpenSSL库完全支持16字节IV,你之前的误解是错误的。Java端用的是16字节全零IV,而Ruby代码里用了12字节,这是导致解密失败的直接原因。

其他潜在问题

  1. 密钥处理错误:代码中decrypted_key是字符串形式,若服务商提供的密钥是Base64编码的,需要先解码为二进制数据,否则密钥长度或格式不符会导致解密失败。
  2. 认证标签拆分逻辑:Java的GCM加密默认不会自动将认证标签附加到密文后,若对方代码未手动拼接密文和标签,你当前拆分最后16字节作为标签的逻辑就是错误的,需确认对方的data格式是否为「密文+16字节认证标签」。

修正后的Ruby解密代码

# 假设密钥是Base64编码,需先解码;若为原始二进制可跳过此步
decrypted_key = Base64.strict_decode64("服务商提供的AES密钥")
decode_data = Base64.strict_decode64(params["data"])

# 拆分密文和认证标签(确认对方data是密文+16字节标签的格式)
cipher_text = decode_data[0...-16]
auth_tag = decode_data[-16..-1]

decipher = OpenSSL::Cipher.new('AES-256-GCM')
decipher.decrypt
decipher.key = decrypted_key
# 使用和Java一致的16字节全零IV
decipher.iv = "\x00" * 16
decipher.auth_data = '' # 和加密端保持一致,若加密时有AAD需同步设置
decipher.auth_tag = auth_tag

decrypted_data = decipher.update(cipher_text) + decipher.final

内容的提问来源于stack exchange,提问作者Catch Me HuntEr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 03:27:47