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

Ruby实现DES ECB加密适配Java项目需求遇问题求助

如何在Ruby中实现与Java一致的DES ECB加密

最近我在把一个Java项目里的DES ECB加密功能迁移到Ruby时踩了坑,折腾了好一会儿才解决。这里把我的问题和解决方案分享出来,希望能帮到遇到同样问题的人。

Java 原加密代码

首先先贴出Java侧的实现,这是我们要对齐的基准:

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class DESEncryptor {
    public static String encrypt(String data, String key) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "DES");
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes("UTF-8"));
        return bytesToHex(encryptedBytes);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    public static void main(String[] args) throws Exception {
        // 示例:密钥"12345678",明文"testcontent"
        System.out.println(encrypt("testcontent", "12345678"));
        // 预期输出:b42e3dbfffd4bb5487a27fd702f079e287e6325767bfdd20
    }
}

我的Ruby尝试与报错

一开始我直接用Ruby的openssl库写了代码,以为能直接跑,结果报错了:

require 'openssl'

def des_encrypt(data, key)
  cipher = OpenSSL::Cipher.new('DES-ECB')
  cipher.encrypt
  cipher.key = key.encode('UTF-8')
  encrypted = cipher.update(data.encode('UTF-8')) + cipher.final
  encrypted.unpack('H*').first
end

# 调用测试
puts des_encrypt("testcontent", "12345678")

终端返回的错误是:

OpenSSL::Cipher::CipherError: bad key length
        from (irb):4:in `key='
        from (irb):4:in `des_encrypt'
        from (irb):9

问题分析与解决办法

问题出在哪?

仔细对比Java和Ruby的实现后发现:

  1. 密钥长度要求:DES的密钥必须是8字节(64位),Java的SecretKeySpec会自动截取密钥的前8字节来适配,但Ruby的OpenSSL库不会做这个自动处理,只要密钥长度不对就直接报错。
  2. 填充模式倒是一致的,Java用的PKCS5Padding和Ruby默认的PKCS#5填充是一样的,但为了保险起见最好明确指定。

修正后的Ruby代码

调整后的代码如下,完美匹配Java的加密结果:

require 'openssl'

def des_encrypt(data, key)
  # 和Java对齐:截取密钥的前8字节,确保密钥长度符合DES要求
  key_bytes = key.encode('UTF-8').bytes.take(8).pack('C*')
  
  cipher = OpenSSL::Cipher.new('DES-ECB')
  cipher.encrypt
  cipher.key = key_bytes
  # 明确设置PKCS#5填充(和Java的PKCS5Padding一致)
  cipher.padding = 1
  
  encrypted = cipher.update(data.encode('UTF-8')) + cipher.final
  # 转成十六进制字符串输出
  encrypted.unpack('H*').first
end

# 测试验证
result = des_encrypt("testcontent", "12345678")
puts result
# 输出正好是预期的:b42e3dbfffd4bb5487a27fd702f079e287e6325767bfdd20

几个关键细节

  • 密钥处理:一定要确保密钥是8字节,Java会自动截断,所以Ruby也要做同样的截取操作,不然会触发密钥长度错误。
  • 填充模式:虽然Ruby默认是PKCS#5,但显式设置cipher.padding = 1能避免版本或环境差异带来的问题。
  • ECB模式:ECB不需要IV,所以不用设置初始化向量,这点和Java的实现保持一致。

内容的提问来源于stack exchange,提问作者Vini Gabriel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:28:08