i have been tasked converting c# cryptography method java , stuck. know c# codes works, having trouble getting java code work.
here c# code:
private const int nb = 4; // legal values: 4 = 128-bit blocks public static void decrypt(byte[] input, stream output) { var s1 = new memorystream(input); const int buffersize = 1024; byte[] buffer = new byte[buffersize]; input.read(buffer, 0, 4); int pad = buffer[3]; rijndaelmanaged rijndael = new rijndaelmanaged(); rijndael.blocksize = nb * 32; rijndael.keysize = buffer[1] * 32; rijndael.mode = ciphermode.ecb; rijndael.padding = paddingmode.none; byte[] key = getkey(buffer[1]); icryptotransform decryptor = rijndael.createdecryptor(key, getiv()); int bytes; while ((bytes = input.read(buffer, 0, buffersize)) > 0) { (int = 0; < bytes; += rijndael.blocksize) { decryptor.transformblock(buffer, i, rijndael.blocksize, buffer, i); } output.write(buffer, 0, bytes); } output.setlength(output.length - pad - 4); } and here attempt in java far:
public static string decrypt(byte[] input) throws exception { cipher cipher = cipher.getinstance("aes/ecb/nopadding"); byte[] key = getkey(input[1]); secretkey secretkey = new secretkeyspec(key, 0, key.length, "aes/ecb/nopadding"); cipher.init(cipher.decrypt_mode, secretkey, new ivparameterspec(getiv())); // remove first 4 since c# code reads past byte[] finaldecoded = arrays.copyofrange(input, 4, input.length); byte[] decryptedval = cipher.dofinal(finaldecoded); return new string(decryptedval); } some more information
for
getiv,getkey, can guarantee results in java same (i have compared every byte), not including methods because believe sensitive information. can guarantee input byte[] identical , (redundantly) same length.debugging attempts: current error in java
ecb mode cannot use iv.- when remove code :
new ivparameterspec(getiv())error:wrong algorithm: aes or rijndael required - if change algorithm
aesorrijndaelerror:input length must multiple of 16 when decrypting padded cipher. input length starting424,420after reading past/removing first 4 bytes. have verified input bytes same java , c#.
- when remove code :
where going wrong in java code?
you getting error ecb mode cannot use iv because ecb doesn't perform chaining, iv meaningless. difference java throws error whereas c# ignores iv.
when remove code :
new ivparameterspec(getiv())error:wrong algorithm:aes or rijndaelrequiredif change algorithm aes or rijndael error:
input length must multiple of 16 when decrypting withpadded cipher.
you had right idea, went far. error secretkeyspec, doesn't care mode, algorithm. cipher specify mode. also, rijndael , aes aren't quite same thing.
so start changing first few lines this:
cipher cipher = cipher.getinstance("rijndael/ecb/nopadding"); byte[] key = getkey(input[1]); secretkey secretkey = new secretkeyspec(key, 0, key.length, "rijndael"); cipher.init(cipher.decrypt_mode, secretkey); note since you're using entire key don't need offset , length arguments, can do
secretkey secretkey = new secretkeyspec(key, "rijndael"); the original c# code has not-so-obvious behavior:
while ((bytes = input.read(buffer, 0, buffersize)) > 0) { (int = 0; < bytes; += rijndael.blocksize) { decryptor.transformblock(buffer, i, rijndael.blocksize, buffer, i); } output.write(buffer, 0, bytes); } when loop gets end of input, copy left of buffer. unless last read 1024 bytes, there residue previous loop (or initialization if gets whole input 1 read operation) after end of input.
the inner loop decrypts 1 16-byte block @ time. in case of 420-byte example, last block consist of remaining 4 bytes of input and 12 more bytes of garbage. it's okay because output.write writes bytes number of bytes truncate garbage. have replicate behavior in java code.
side note: absolutely have use ecb? it's not secure...
Comments
Post a Comment