Reputation: 532
I'm trying to decrypt some data that I am receiving via a TCP socket. This is being done using RijndaelManaged
class in CFB mode. My problem is that I'm not sure how I'm supposed to decrypt the data since I'm only dealing with a few bytes (8 to 20 depending on the message). When I call TransformFinalBlock
with a 10 byte byte[]
I get an exception with the message: "The length of the data to decrypt is invalid." If I call TransformBlock
with those 10 bytes I get: "Value was invalid." So here are my questions:
I've also tried using a CryptoStream
to have it read directly from my NetworkStream
. However, any read calls on it seem to block indefinitely. I have a feeling it is expecting more data to be sent (probably a full block size worth of bytes).
I don't have access to the other node that is sending this data on the network so I can't change the protocol to include unencrypted bytes in the beginning that indicate the length or anything. Also, supposedly there are other people communicating with this successfully so it must be possible.
Upvotes: 2
Views: 1509
Reputation: 532
I was able to partially solve this (my #2 question) by using the BouncyCastle library instead of the built-in .NET AES class.
I first attempted to manually pad the encrypted data using PKCS7 (I believe this is the only padding scheme supported by AES). Using the RijndaelManaged
class on this manually padded data resulted in a "Padding is not valid and cannot be removed" exception. So I then tried to use the BouncyCastle library:
CfbBLockCipher cipher = new CfbBlockCipher(new AesEngine(), 128);
cipher.Init(false, new ParametersWithIV(new KeyParameters(key), iv));
cipher.DecryptBlock(encrypted, 0, decrypted, 0);
And it worked perfectly. I don't know if this is a bug in .NET or what but hopefully this will help anyone else that runs into this.
Now, if only I can figure out how to decrypt those first four bytes so I know how long the message will be... (my #1 question)
Edit:
If I use BouncyCastle's PaddedBufferBlockCipher
I get a "pad block corrupted" error when decrypting. There is something strange with this data that I can only decrypt manually in a single block and only with BouncyCastle (.NET's TransformBlock
just gives me zero bytes for the decrypted value).
Upvotes: 1
Reputation: 4768
when you are dealing with TCP streams, you usually have to buffer your data in some form if you are using length prefixing, you have a phase "Reading Length" when that is read you switch to "Reading data" when that length is met, you pass out the bytes that have been read and switch back to "Reading Length" ...
Rememeber you may not receive everything you send in a single read, or you may receive more than a single send in 1 read.
Is the Length Also encrypted? could it be that the length is prepending in an unencrypted fashion, and then the payload is encrypted? ... it's going to be harder knowing how much to read if you don't know how much to read until you've decrypted the data.
Suggest: 4bytes (there are other method) for Length of Encrypted Payload
Read Bytes until length just read have been received.
(Decrypt payload)
4bytes ...
N Bytes ...
(Decrypt)
Repeat while stream is connected.
If you have control over the encrypting end.
Function Receives Input bytes Encrypt returns Encypted bytes
Send Encrypted bytes Length (4bytes) Send Encrypted bytes
Repeat for each input block.
Upvotes: 0
Reputation: 81189
When using a cryptosystem of a particular block size N, every bit in the output depends upon the state of at least N bits in the input. In the case of many modern systems like AES, the block size is going to be either 128 or 256 bits (i.e. 16 or 32 bytes). Although there are schemes to encrypt files whose length is not a multiple of the block size without requiring padding (if e.g. a file is some multiple of 256 bits, plus an extra 32 bits, a common scheme would be to end the encryption by encrypting a block consisting of the last 224 encrypted bits and the remaining 32 unencrypted bits) it is not in general possible to encrypt anything smaller than a block.
You will either have to encrypt the first 16/32 bytes of your file, use the length, and then regard the "extra" 12 or 28 bytes you read as part of the first data item, or else require that data items have a minimum length of 16 or 32 bytes and encrypt them separately, leaving the lengths unencrypted.
Upvotes: 1