AES java编码,ruby解码

我正在尝试对java中的数据进行AES编码,通过网络发送并在ruby中对其进行解码。

使用基本字符串可以正常工作,但是一旦字符串的长度为16个字节或更多,我就会在解码的ruby字符串的编码中产生垃圾。 我想这与填充有关(不确定,因为它甚至影响具有16的确切大小的字符串)

我尝试使用PKCS或只是在我的字符串末尾添加空格以匹配确切的长度而没有运气

也有人可以解释为什么我必须在ruby中做一个“aes-256-cbc”知道我的java代码使用aes 128? 在ruby中尝试aes-128-cbc对任何字符串都不起作用

任何帮助是极大的赞赏

这是我的基本代码

Java的

byte[] raw = key.getBytes(); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(str.getBytes()); return new BASE64Encoder().encode(encrypted); 

ruby

 def aes_decrypt(key, encrypted) decipher =OpenSSL::Cipher::Cipher.new("aes-256-cbc") decipher.decrypt decipher.padding = 0 decipher.key = key d = decipher.update(encrypted) d << decipher.final logger.debug "email #{d.to_s}" return d.to_s end 

衬垫 ,有链接 。 你应该首先得到正确的链接。

AES加密16字节的块,不多也不少。 如果要加密可能长于16个字节的消息,则必须决定如何将数据拆分为块并在之后重新组装。 基本的分裂算法称为ECB :这只是“分裂”成单独加密的块。 众所周知,ECB对实际数据的影响很小,因为它泄漏了有关哪些明文块彼此相等的信息(它们将被加密相同),并且这种冗余通常发生在“正常”数据中。

因此,需要以某种方式“随机化”数据块,以便隐藏数据冗余。 CBC模式通过“链接”执行该操作:块的处理取决于前一块的加密结果。 即,将加密明文块与(按位XOR)与先前块加密的输出组合。

这里重要的一点是,第一个加密块(前16个字节的数据)没有“前一个块”,因此没有任何与XOR相关的内容。 这可以通过选择“随机IV”,即16个随机字节的序列来解决,它将用作exception步骤的“块-1”。 解密方必须知道IV(否则它将不知道解密块的XOR是什么,并且前16个字节的数据将是不可理解的)。 光明的一面是IV不需要保密; 它必须统一选择(它不能是每个消息增加的计数器),但它可以“明确地”传输,通常沿着加密的消息本身传输。

所以你不得不担心IV,我在Java或Ruby代码中都没有看到它。 通常,Java默认为ECB(因此根本没有IV)。 如果Ruby在CBC中默认为“全零IV”(在概念上是不安全的),那么你可以解密第一个块(写下来,它“只是工作”)是正常的,但它同样正常它不适用于后续块。

所以我建议您明确使用CBC(在Java中,使用"AES/CBC/PKCS5Padding"作为算法名称,而不是"AES" )并管理IV(必须传输;您可以采用约定将IV连接起来在加密消息之前)。

其他几点说明:

  • 填充是关于向明文添加一些数据,以便您具有适当的输入长度。 CBC要求输入长度具有块大小的长度倍数(16字节)。 PKCS#5填充是一种流行的方法,通过它可以添加至少1个字节,最多16个字节,这样它们都具有值n ,其中n是添加的字节数。 接收器然后可以(明确地)知道添加了多少字节,并将其删除。 Java可以为你添加填充,我想如果很好的话,Ruby也可以自动处理填充。

  • 在Java代码中,您使用key.getBytes() 。 我想这个key是一个String 。 知道getBytes()根据平台默认字符集对字符串进行编码,这在全球范围内并不总是相同。 通过指定显式字符集,您将节省一些担心。 另外,既然你想使用128位密钥,但是你只在Ruby端获得了“AES-256”,那么我假设你实际上在Java端使用了256位密钥。 我的猜测是你的key字符串是你的keyhex表示,为32个字符。 key.getBytes()不解释hex数字; 它对字符本身进行编码,产生一个32字节的数组 – 和32字节,即256位,而不是128位。

我同意你对填充的怀疑。 PKCS#5填充将“汇总”您的明文到下一个整个块边界; 如果你给它一个整数块,它将添加一整块填充。

如果我是你,那么当你向JCE询问AES时,我会想要确切地看到你得到的东西 – 我怀疑你正在获得AES / CBC / PKCS5Padding,但明确要求你想要什么更有意义。 同样,你需要准确查找你在Ruby端获得的内容 – 解密结尾的“垃圾”可能是填充字节吗? 去阅读PKCS#5规范并将其与您获得的内容进行比较。

我有点担心你说你在java端使用AES-128但是(显然)在Ruby / OpenSSL端使用AES-256。 这种不匹配几乎可以保证不起作用 – 但是你说密码正在起作用,至少对于短消息是这样。 你可能真的从java中获得了AES-256(再次,如果你问它“AES”,你实际得到了什么?)或者ruby方面有一些奇怪的事情发现你正在使用它一个128位密钥并做它认为正确的事情。

旁白:您是否考虑过您的密文是否需要完整性保护? 机密性非常好,但成功的解密并不能保证密文在传输过程中没有被篡改。