How can an AES Encrypted StreamWriter Send data before the connection closes?
Given this Reader/Server side code:
$Listener = [System.Net.Sockets.TcpListener]61855
$Listener.Start()
$Client = $Listener.AcceptTcpClient()
$Stream = $Client.GetStream()
[byte[]]$key = (
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
)
$Aes = [System.Security.Cryptography.Aes]::Create()
$Aes.Key = $key
$IV = New-Object byte[] -ArgumentList $Aes.IV.Length
$BytesToRead = $Aes.IV.Length
$Stream.Read($IV,0,$BytesToRead)
$Aes.IV = $IV
$ReadMode = [System.Security.Cryptography.CryptoStreamMode]::Read
$EncryptedStream = New-Object System.Security.Cryptography.CryptoStream -ArgumentList $Stream,
$Aes.CreateDecryptor($key, $IV),
$ReadMode
$EReader = New-Object System.IO.StreamReader($EncryptedStream)
do {
$EReader.Readline()
} while (!$EReader.EndOfStream)
and this Writer/Client side code:
$Connection = New-Object System.Net.Sockets.TcpClient("localhost",61855)
$Stream = $Connection.GetStream()
[byte[]]$key = (
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
)
$Aes = [System.Security.Cryptography.Aes]::Create()
$Aes.Key = $key
$Stream.Write($Aes.IV,0,$Aes.IV.Length)
$WriteMode = [System.Security.Cryptography.CryptoStreamMode]::Write
$EncryptedStream = New-Object System.Security.Cryptography.CryptoStream -ArgumentList $Stream,
$Aes.CreateEncryptor(),
$WriteMode
$EWriter = New-Object System.IO.StreamWriter($EncryptedStream)
for ($count = 0; $count -lt 128; $count ++) {
$EWriter.WriteLine("ab")
$EWriter.Flush()
}
The Reader side never gets any data until the Writer side closes the connection. In my search for an answer I have found that due to using AES encryption the CryptoStream will not send any data when a block is incomplete. So I am using WriteLine with a two character string "ab". This should produce four bytes of data to the CryptoStream, specifically
- 0x61 "a"
- 0x62 "b"
- 0x0d CARRIAGE RETURN
- 0x0a LINE FEED
With four bytes of data being written to the CryptoStream each time I flush the data, that should mean that it reaches the 128 Bit block size after the fourth line, and I should have a total of 32 blocks of 128 Bits sent to the CryptoStream But the data is never sent until I call:
$EWriter.Close()
Then the reader gets all lines of data immediately. I am sending 512 total bytes in this code, so even if I misunderstood the block size of 128 Bits and it should be 128 Bytes I am still sending 4 complete blocks. I have also tried this code with the string "a" to provide an offset if the padding were to confound my calculation of what bytes are being sent.
Additionally if I set the LeaveOpen: $true attribute on the CryptoStream during creation, closing the EWriter does not send the data, I still have to call Close() on the CryptoStream for the data to send. I would like to be able to leave the connection open to have a bit of bidirectional encrypted communication without having to establish new connections each time.