Before you go and say use Jon Skeet's answer, I can't.
I am using this stream which is great in the beginning, but now, I have run into a small problem. I am now at a point where i do not know the amount of data I expect, so I thought well I'd use the method Jon Skeet provided but unfortunately it waits on packet = mPackets.Take()
when all the packets have been read.
I have no idea how to fix this, the stream does what it's supposed to do (in the beginning) but unfortunately this is an occasion where i do not want it to do what it was made for...
Should I try to rewrite the waitingstream
or is there a different readall
method which would work better in my case?
I have tried returning 0 when there were no more packets available(when I wanted it to read all and not wait) but then it throws an IO end of stream exception
.
I am really at a loss here, I understand I've dug a deep hole for my self...
So far i have not been able to come up with a better solution than subtracting the TLS header and GCM IV and MAC from the total length (like mentioned below) This works fine for the 1 suite i'm using now but does not boast well for future cipher suites.
Some context as to why I'm doing this:
I'm using https://github.com/bcgit/bc-csharp to create a TLS based encryption, however Because of limitations i cannot assign it a TCP stream, all i get is a string from the TCP layer, I cannot provide it with a propper TCP stream.
I am using the mockPskTlsServer and client and I've created it like so:
WaitingStream mStdin = new WaitingStream();
WaitingStream mStdout = new WaitingStream();
CryptoPskTlsClient mServer = new CryptoPskTlsClient(null);
SecureRandom secureRandom = new SecureRandom();
TlsClientProtocol TlsProtocol = new TlsServerProtocol(Stdin, Stdout, secureRandom);
TlsProtocol.Connect(mServer);
This works fine, I've also added an event to the waiting stream which fires when there's output for the stream. This so I could get the multiple handshake messages when they were created.
This all works fine, could have been made better (less.... hacked?) but it does what it's supposed to do.
I do know of ways to get it to work but this is a HACK and i'm looking for a elegant way to do it. Here is a code example for one of those HACKS:
public override string DecryptData(string ciphertext)
{
byte[] ciphertextBuff = ASCIIEncoding.Default.GetBytes(ciphertext);
mStdin.Write(ciphertextBuff, 0, ciphertextBuff.Length);
Stream tlsStream = mServerProtocol.Stream;
byte[] plaintextBuffer = new byte[ciphertextBuff.Length - 29];//filthy HACK 29 bytes bij AES-GCM want TLS packet = 5, GCM IV = 8, GCM-MAC = 16 totaal = 29.
Streams.ReadFully(tlsStream, plaintextBuffer);
string plaintext = ASCIIEncoding.Default.GetString(plaintextBuffer);
return plaintext;
}
or by prepending the plaintext lenght in x reserved bytes to the TLS packet and retrieving these bytes before decrypting.
but as you can clearly see from the code example the buffer in the read fully method must be the length of bytes I want to extract, it can be less than what the stream has but it cannot be more because then it will wait indefinitely.
When i'm talking about methods like ReadAll
and ReadFully
I mean these methods