简体   繁体   English

AES java编码,ruby解码

[英]AES java encoding, ruby decoding

I'm trying to AES encode data in java, send it over the network and decode it in ruby. 我正在尝试对java中的数据进行AES编码,通过网络发送并在ruby中对其进行解码。

Works fine with basic strings, but once the string's length is 16 bytes or more, I have garbage at the encode of the decoded ruby string. 使用基本字符串可以正常工作,但是一旦字符串的长度为16个字节或更多,我就会在解码的ruby字符串的编码中产生垃圾。 I guess it has to do with padding (not sure though since it affects even strings with the exact size of 16) 我想它与填充有关(不确定,因为它影响甚至大小为16的字符串)

I tried using PKCS or just adding white space at the end of my string to match the exact length with no luck 我尝试使用PKCS或只是在我的字符串末尾添加空格以匹配确切的长度而没有运气

Also can anyone explain why I have to do a "aes-256-cbc" in ruby knowing that my java code uses aes 128? 也有人可以解释为什么我必须在ruby中做一个“aes-256-cbc”知道我的java代码使用aes 128? trying aes-128-cbc in ruby does not work for any string 在ruby中尝试aes-128-cbc对任何字符串都不起作用

Any help is greatly appreciated 任何帮助是极大的赞赏

Here's my basic code 这是我的基本代码

Java 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

There is padding and there is chaining . 衬垫 ,有链接 You should first get the chaining right. 你应该首先得到正确的链接。

AES encrypts blocks of 16 bytes, no more and no less. AES加密16字节的块,不多也不少。 When you want to encrypt a message which is potentially longer than 16 bytes, then you have to decide how data is split into blocks and reassembled afterwards. 如果要加密可能长于16个字节的消息,则必须决定如何将数据拆分为块并在之后重新组装。 The basic splitting algorithm is called ECB : this is "just a split" into blocks encrypted individually. 基本的分裂算法称为ECB :这只是“分裂”成单独加密的块。 ECB is known to be weak with real-world data because it leaks information about which plaintext blocks are equal to each other (they will be encrypted identically) and such redundancy often happens in "normal" data. 众所周知,ECB对现实世界的数据很脆弱,因为它泄漏了有关哪些明文块彼此相等的信息(它们将被加密相同),并且这种冗余经常发生在“正常”数据中。

Thus it is needed to "randomize" the data blocks in some way, so that data redundancy is hidden. 因此,需要以某种方式“随机化”数据块,以便隐藏数据冗余。 The CBC mode performs that through "chaining": the processing of a block depends on the result of the encryption of the previous block. CBC模式通过“链接”执行该操作:块的处理取决于前一个块的加密结果。 Namely, the to-encrypt plaintext block is combined (with bitwise XOR) with the output of the previous block encryption. 即,将加密的明文块与先前的块加密的输出(按位XOR)组合。

The important point here is that the first block to encrypt (the first 16 bytes of data) has no "previous block" so there is nothing to XOR with. 这里重要的一点是,第一个加密块(前16个字节的数据)没有“前一个块”,因此没有任何与XOR相关的内容。 This is solved by choosing a "random IV", ie a sequence of 16 random bytes, which will be used as "block -1" for the XORing step. 这可以通过选择“随机IV”,即16个随机字节的序列来解决,它将用作异常步骤的“块-1”。 The IV must be known to the decrypting party (otherwise it will not know what to XOR the decrypted block with, and the first 16 bytes of data will not be intelligible). 解密方必须知道IV(否则它将不知道解密块的XOR是什么,并且前16个字节的数据将是不可理解的)。 The bright side is that the IV needs not be secret; 光明的一面是IV不需要保密; it MUST be selected uniformly (it cannot be a counter incremented for each message), but it can be transmitted "in the clear", usually along the encrypted message itself. 它必须统一选择(它不能是每个消息增加的计数器),但它可以“明确地”传输,通常沿着加密的消息本身传输。

So you have to worry a bit about the IV, and I see nothing about it in either the Java or Ruby code. 所以你不得不担心IV,我在Java或Ruby代码中都没有看到它。 Usually, Java defaults to ECB (hence no IV at all). 通常,Java默认为ECB(因此根本没有IV)。 If Ruby defaults to an "all-zero IV" in CBC (which is, conceptually, insecure), then it is normal that you can decrypt the first block (write it down, it "just works"), but it is equally normal that it does not work for subsequent blocks. 如果Ruby在CBC中默认为“全零IV”(在概念上是不安全的),那么你可以解密第一个块(写下来,它“只是工作”)是正常的,但它同样正常它不适用于后续块。

So I suggest that you explicitly use CBC (in Java, use "AES/CBC/PKCS5Padding" as algorithm name, not "AES" ) and manage the IV (which must then be transmitted; you could take the convention to concatenate the IV right before the encrypted message). 所以我建议您明确使用CBC(在Java中,使用"AES/CBC/PKCS5Padding"作为算法名称,而不是"AES" )并管理IV(必须传输;您可以采用约定将IV连接起来在加密消息之前)。

A few other notes: 其他几点说明:

  • Padding is about adding some data to the plaintext so that you have an appropriate input length. 填充是关于向明文添加一些数据,以便您具有适当的输入长度。 CBC requires that the input length has a length multiple of the block size (16 bytes). CBC要求输入长度具有块大小的长度倍数(16字节)。 The PKCS#5 padding is a popular method, by which you add at least 1 byte, at most 16 bytes, such that all of them have value n where n is the number of added bytes. PKCS#5填充是一种流行的方法,通过它您可以添加至少1个字节,最多16个字节,这样所有它们都具有值n ,其中n是添加的字节数。 The receiver can then know (unambiguously) how many bytes were added, and remove them. 接收器然后可以(明确地)知道添加了多少字节,并将其删除。 Java can add the padding for you, and I suppose Ruby can also process the padding automatically if nicely asked. Java可以为你添加填充,我想如果很好的话,Ruby也可以自动处理填充。

  • In the Java code, you use key.getBytes() . 在Java代码中,您使用key.getBytes() I suppose that key is a String . 我想这个key是一个String Know that getBytes() encodes the string according to the platform default character set, which is not always the same worldwide. 知道getBytes()根据平台默认字符集对字符串进行编码,这在全球范围内并不总是相同。 You will save some worry by specifying an explicit charset. 通过指定显式字符集,您将节省一些担心。 Also, since you want to use a 128-bit key but you get something on the Ruby side only with "AES-256", then I assume that you are actually using a 256-bit key on the Java side. 另外,既然你想使用128位密钥,但是你只在Ruby端获得了“AES-256”,那么我假设你实际上在Java端使用了256位密钥。 My guess is that your key string is the hexadecimal representation of your key, as 32 characters. 我的猜测是你的key字符串是你的key十六进制表示,为32个字符。 key.getBytes() does not interpret hexadecimal digits; key.getBytes()不解释十六进制数字; it encodes the characters themselves, yielding a 32-byte array -- and 32 bytes, that's 256 bits, not 128. 它对字符本身进行编码,产生一个32字节的数组 - 和32字节,即256位,而不是128位。

I agree with your suspicion about padding. 我同意你对填充的怀疑。 PKCS#5 padding will "round up" your plaintext to the next whole block boundary; PKCS#5填充将“汇总”您的明文到下一个整个块边界; if you give it a whole number of blocks, it will add one whole block of padding. 如果你给它一个整数块,它将添加一整块填充。

If I were you I'd be looking to see exactly what you're getting when you ask JCE for AES - I suspect you're getting AES/CBC/PKCS5Padding, but it might make more sense to explicitly request what you want. 如果我是你,我会看到当你向JCE询问AES时你到底得到了什么 - 我怀疑你正在获得AES / CBC / PKCS5Padding,但明确要求你想要的东西可能更有意义。 Similarly, you need to look up exactly what you're getting at the Ruby end - might the "garbage" at the end of the decrypt be the padding bytes? 类似地,您需要准确查找您在Ruby端获得的内容 - 解密结尾处的“垃圾”可能是填充字节吗? Go read the PKCS#5 spec and compare it with what you're getting. 去阅读PKCS#5规范并将其与你得到的相比较。

I'm slightly worried by you saying you're using AES-128 on the java side but (apparently) AES-256 on the Ruby/OpenSSL side. 我有点担心你说你在java端使用AES-128但是(显然)在Ruby / OpenSSL端使用AES-256。 That sort of mismatch is pretty much guaranteed to not work - yet you say that the crypto is working, at least for short messages. 这种不匹配几乎可以保证不起作用 - 但是你说加密是有效的,至少对于短消息是这样。 It's possible that you're actually getting AES-256 from java (again, if you ask it for "AES", what do you actually get?) or there's something odd going on on the ruby side which is detecting that you're using a 128 bit key and doing what it considers to be the Right Thing. 有可能你实际上从java获得了AES-256(再次,如果你问它为“AES”,你实际得到了什么?)或者红宝石方面有一些奇怪的事情发现你正在使用它一个128位密钥,并做它认为是正确的事情。

Aside: Have you considered whether your ciphertexts need integrity protection? 旁白:您是否考虑过您的密文是否需要完整性保护? Confidentiality is all very well, but a successful decryption is no guarantee that the ciphertext hasn't been tampered with in transit. 机密性非常好,但成功的解密并不能保证密文在传输过程中没有被篡改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM