Dennis
Dennis

Reputation: 532

Decrypting a small number of bytes using AES

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:

  1. The message I'm receiving has the length of the rest of the message in the first 4 bytes. How could I decrypt just those bytes to determine the length to continue reading?
  2. Even if I temporarily hard code the number of bytes to read to 10 (for this particular message) and read those from the network, how can I decrypt those 10 bytes?

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

Answers (3)

Dennis
Dennis

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

Paul Farry
Paul Farry

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

supercat
supercat

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

Related Questions