Java转Ruby的AES加密代码输出不一致,求Ruby代码修正方案
AES加密Java转Ruby输出不一致的修复方案
用户尝试将Java AES加密代码转换为Ruby实现,但两者加密输出始终不一致。以下是双方代码核心逻辑梳理、Ruby代码错误点及修正方案:
Java代码核心逻辑梳理
Java代码的关键加密规则如下:
// 密钥生成:将原始密钥转为UTF-8字节数组,经Base64编码后再解码得到密钥字节 public static SecretKey secretKeyGeneration(String requestor, String key, String algo, Integer size) { NAPISecretKey napiSecretKey = new NAPISecretKey(); napiSecretKey.setAlgorithm(algo); napiSecretKey.setKey(StringUtil.fromByteArrayToBase64((key).getBytes())); napiSecretKey.setSize(size); return decodeSecretKey(napiSecretKey.getKey(), napiSecretKey.getAlgorithm()); } // 加密规则:AES/CBC/PKCS5Padding模式,使用全0的16字节IV public static byte[] encrypt(SecretKey secretKey, byte[] plaintext) throws Exception { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(new byte[16])); return cipher.doFinal(plaintext); }
Ruby代码的错误点及修正
错误1:密钥生成逻辑完全偏离
Ruby中错误地将密钥的每个字节数值拼接成字符串再做Base64编码,而Java是直接对密钥的UTF-8字节数组进行Base64编码。
错误2:加密模式不匹配
Java使用AES/CBC/PKCS5Padding模式,Ruby却误用了AES-256-ECB模式(ECB不支持IV,且加密逻辑与CBC完全不同)。
错误3:明文处理冗余且错误
Ruby中多余地将明文的字节数值拼接成字符串,Java是直接使用明文的UTF-8字节数组进行加密。
错误4:IV设置无效
ECB模式下设置IV无意义,切换到CBC模式后需正确设置全0的16字节IV。
修正后的Ruby代码
def encrypt_data encryption_key = "12345678" requestor_id = "IN000000" encrypted_data = params[:orderReqDtls] || request.headers[:orderReqDtls] encrypted_data = @order_data if caller_locations.any? { |loc| loc.label == 'generate_json_order_data' } secret_key = secret_key_generation(requestor_id, encryption_key, "AES", 256) encrypted_string = encrypt(secret_key, encrypted_data) encrypted_data = Base64.strict_encode64(encrypted_string) render json: { data: encrypted_data } end def secret_key_generation(requestor, key, algo, size) napi_secret_key = NAPISecretKey.new napi_secret_key.algorithm = algo # 修正:直接对密钥的UTF-8字节数组做Base64编码,与Java逻辑对齐 base64_encoded_key = Base64.strict_encode64(key.encode('UTF-8')) napi_secret_key.key = base64_encoded_key napi_secret_key.size = size decode_secret_key(napi_secret_key.key, napi_secret_key.algorithm) end def decode_secret_key(key, algo) if algo == "AES" # 解码Base64得到原始密钥字节数组 Base64.decode64(key) else raise "#{algo} is not supported" end end def encrypt(secret_key, plaintext) # 修正:使用CBC模式,对应Java的AES/CBC/PKCS5Padding cipher = OpenSSL::Cipher.new('AES-256-CBC') cipher.encrypt # 设置密钥 cipher.key = secret_key # 修正:设置全0的16字节IV,与Java一致 cipher.iv = "\x00" * 16 # 修正:直接使用明文的UTF-8字节,无需额外处理 encrypted_data = cipher.update(plaintext.encode('UTF-8')) + cipher.final end
额外注意事项
- AES-256要求密钥长度为32字节(256位),若你的
encryption_key长度不足,Java会抛出InvalidKeyException,请确保密钥符合长度要求。 - 确认Ruby和Java使用的Base64编码标准一致(均为标准Base64,无URL安全或换行差异)。
内容的提问来源于stack exchange,提问作者shaik praveen
相关产品推荐
相关产品推荐

