CryptoStream Třída
Definice
Důležité
Některé informace platí pro předběžně vydaný produkt, který se může zásadně změnit, než ho výrobce nebo autor vydá. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Definuje datový proud, který propojuje datové proudy s kryptografickými transformacemi.
public ref class CryptoStream : System::IO::Stream
public class CryptoStream : System.IO.Stream
[System.Runtime.InteropServices.ComVisible(true)]
public class CryptoStream : System.IO.Stream
type CryptoStream = class
inherit Stream
interface IDisposable
[<System.Runtime.InteropServices.ComVisible(true)>]
type CryptoStream = class
inherit Stream
interface IDisposable
Public Class CryptoStream
Inherits Stream
- Dědičnost
- Dědičnost
- Atributy
- Implementuje
Příklady
Následující příklad ukazuje, jak použít CryptoStream k šifrování řetězce. Tato metoda používá třídu Aes se zadaným Key a inicializačním vektorem (IV).
using System;
using System.IO;
using System.Security.Cryptography;
class AesExample
{
public static void Main()
{
try
{
string original = "Here is some data to encrypt!";
// Create a new instance of the Aes class.
// This generates a new key and initialization vector (IV).
using (Aes myAes = Aes.Create())
{
// Encrypt the string to an array of bytes.
byte[] encrypted = EncryptStringToBytes(original, myAes.Key, myAes.IV);
// Decrypt the bytes to a string.
string roundtrip = DecryptStringFromBytes(encrypted, myAes.Key, myAes.IV);
// Display the original data and the decrypted data.
Console.WriteLine("Original: {0}", original);
Console.WriteLine("Round trip: {0}", roundtrip);
}
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e.Message);
}
}
static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException(nameof(plainText));
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException(nameof(Key));
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException(nameof(IV));
byte[] encrypted;
// Create a Aes object with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new())
{
using (CryptoStream csEncrypt = new(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new(csEncrypt))
{
// Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException(nameof(cipherText));
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException(nameof(Key));
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException(nameof(IV));
// Declare the string used to hold the decrypted text.
string plaintext = null;
// Create a Aes object with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new(cipherText))
{
using (CryptoStream csDecrypt = new(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
}
Imports System.IO
Imports System.Security.Cryptography
Class AesExample
Public Shared Sub Main()
Try
Dim original As String = "Here is some data to encrypt!"
' Create a new instance of the Aes class.
' This generates a new key and initialization vector (IV).
Using myAes = Aes.Create()
' Encrypt the string to an array of bytes.
Dim encrypted As Byte() = EncryptStringToBytes(original, myAes.Key, myAes.IV)
' Decrypt the bytes to a string.
Dim roundtrip As String = DecryptStringFromBytes(encrypted, myAes.Key, myAes.IV)
'Display the original data and the decrypted data.
Console.WriteLine("Original: {0}", original)
Console.WriteLine("Round Trip: {0}", roundtrip)
End Using
Catch e As Exception
Console.WriteLine("Error: {0}", e.Message)
End Try
End Sub
Shared Function EncryptStringToBytes(ByVal plainText As String, ByVal Key() As Byte, ByVal IV() As Byte) As Byte()
' Check arguments.
If plainText Is Nothing OrElse plainText.Length <= 0 Then
Throw New ArgumentNullException(NameOf(plainText))
End If
If Key Is Nothing OrElse Key.Length <= 0 Then
Throw New ArgumentNullException(NameOf(Key))
End If
If IV Is Nothing OrElse IV.Length <= 0 Then
Throw New ArgumentNullException(NameOf(IV))
End If
Dim encrypted() As Byte
' Create an Aes object with the specified key and IV.
Using aesAlg = Aes.Create()
aesAlg.Key = Key
aesAlg.IV = IV
' Create an encryptor to perform the stream transform.
Dim encryptor As ICryptoTransform = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV)
' Create the streams used for encryption.
Using msEncrypt As New MemoryStream()
Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
Using swEncrypt As New StreamWriter(csEncrypt)
' Write all data to the stream.
swEncrypt.Write(plainText)
End Using
encrypted = msEncrypt.ToArray()
End Using
End Using
End Using
' Return the encrypted bytes from the memory stream.
Return encrypted
End Function 'EncryptStringToBytes
Shared Function DecryptStringFromBytes(
ByVal cipherText() As Byte,
ByVal Key() As Byte,
ByVal IV() As Byte) As String
' Check arguments.
If cipherText Is Nothing OrElse cipherText.Length <= 0 Then
Throw New ArgumentNullException(NameOf(cipherText))
End If
If Key Is Nothing OrElse Key.Length <= 0 Then
Throw New ArgumentNullException(NameOf(Key))
End If
If IV Is Nothing OrElse IV.Length <= 0 Then
Throw New ArgumentNullException(NameOf(IV))
End If
' Declare the string used to hold the decrypted text.
Dim plaintext As String = Nothing
' Create an Aes object with the specified key and IV.
Using aesAlg = Aes.Create()
aesAlg.Key = Key
aesAlg.IV = IV
' Create a decryptor to perform the stream transform.
Dim decryptor As ICryptoTransform = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV)
' Create the streams used for decryption.
Using msDecrypt As New MemoryStream(cipherText)
Using csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)
Using srDecrypt As New StreamReader(csDecrypt)
' Read the decrypted bytes from the decrypting stream
' and place them in a string.
plaintext = srDecrypt.ReadToEnd()
End Using
End Using
End Using
End Using
Return plaintext
End Function 'DecryptStringFromBytes
End Class
Poznámky
Modul CLR (Common Language Runtime) používá pro kryptografii návrh orientovaný na datový proud. Jádrem tohoto návrhu je CryptoStream. Všechny kryptografické objekty, které implementují CryptoStream, mohou být zřetězený společně s libovolnými objekty, které implementují Stream, takže streamovaný výstup z jednoho objektu může být předán do vstupu jiného objektu. Průběžný výsledek (výstup z prvního objektu) nemusí být uložen samostatně.
Důležitý
V .NET 6 a novějších verzích se při volání Stream.Read
nebo Stream.ReadAsync
s vyrovnávací pamětí délky N
, operace se dokončí, když se z datového proudu načte alespoň 1 bajt, nebo podkladový datový proud, který zabalí 0 z volání Read
, což znamená, že nejsou k dispozici žádná další data. Před rozhraním .NET 6 se Stream.Read
a Stream.ReadAsync
nevracely, dokud se všechny N
bajty nepřečtou z datového proudu nebo ze základního datového proudu vrátily hodnotu 0 z volání Read
. Pokud váš kód předpokládá, že metody Read
se nevrátí, dokud nebudou přečteny všechny N
bajty, nebude možné přečíst veškerý obsah. Další informace naleznete v tématu částečné a nulové bajty čtení v datových proudech.
Jakmile ho budete používat, měli byste vždy explicitně zavřít objekt CryptoStream voláním metody Clear. Tím se vyprázdní základní datový proud a všechny zbývající bloky dat se zpracují CryptoStream objektem. Pokud však dojde k výjimce před voláním Close metoda, CryptoStream objekt nemusí být uzavřen. Pokud chcete zajistit, aby se metoda Close vždy volala, umístěte volání metody Clear do finally
bloku příkazu try
/catch
.
Tento typ implementuje rozhraní IDisposable. Jakmile použijete typ, měli byste ho odstranit buď přímo nebo nepřímo voláním jeho Clear metody, která pak volá jeho IDisposable implementaci. Chcete-li typ odstranit přímo, zavolejte jeho Clear metodu v bloku try
/catch
. Pokud ho chcete zlikvidovat nepřímo, použijte konstruktor jazyka, jako je using
(v jazyce C#) nebo Using
(v jazyce Visual Basic).
Konstruktory
CryptoStream(Stream, ICryptoTransform, CryptoStreamMode) |
Inicializuje novou instanci třídy CryptoStream s cílovým datovým proudem, transformací, která se má použít, a režim streamu. |
CryptoStream(Stream, ICryptoTransform, CryptoStreamMode, Boolean) |
Inicializuje novou instanci CryptoStream třídy. |
Vlastnosti
CanRead |
Získá hodnotu určující, zda aktuální CryptoStream je čitelný. |
CanSeek |
Získá hodnotu určující, zda lze vyhledat v aktuálním CryptoStream. |
CanTimeout |
Získá hodnotu, která určuje, zda aktuální datový proud může vypršení časového limitu. (Zděděno od Stream) |
CanWrite |
Získá hodnotu určující, zda aktuální CryptoStream je zapisovatelný. |
HasFlushedFinalBlock |
Získá hodnotu určující, zda konečný blok vyrovnávací paměti byl zapsán do podkladového datového proudu. |
Length |
Získá délku v bajtech datového proudu. |
Position |
Získá nebo nastaví pozici v aktuálním datovém proudu. |
ReadTimeout |
Získá nebo nastaví hodnotu v milisekundách, která určuje, jak dlouho se datový proud pokusí přečíst před uplynutím časového limitu. (Zděděno od Stream) |
WriteTimeout |
Získá nebo nastaví hodnotu v milisekundách, která určuje, jak dlouho se datový proud pokusí zapsat před uplynutím časového limitu. (Zděděno od Stream) |
Metody
BeginRead(Byte[], Int32, Int32, AsyncCallback, Object) |
Zahájí asynchronní operaci čtení. (Zvažte místo toho použití ReadAsync.) |
BeginRead(Byte[], Int32, Int32, AsyncCallback, Object) |
Zahájí asynchronní operaci čtení. (Zvažte místo toho použití ReadAsync(Byte[], Int32, Int32).) (Zděděno od Stream) |
BeginWrite(Byte[], Int32, Int32, AsyncCallback, Object) |
Zahájí asynchronní operaci zápisu. (Zvažte místo toho použití WriteAsync.) |
BeginWrite(Byte[], Int32, Int32, AsyncCallback, Object) |
Zahájí asynchronní operaci zápisu. (Zvažte místo toho použití WriteAsync(Byte[], Int32, Int32).) (Zděděno od Stream) |
Clear() |
Uvolní všechny prostředky používané CryptoStream. |
Close() |
Zavře aktuální datový proud a uvolní všechny prostředky (například sokety a popisovače souborů) přidružené k aktuálnímu datovému proudu. |
Close() |
Zavře aktuální datový proud a uvolní všechny prostředky (například sokety a popisovače souborů) přidružené k aktuálnímu datovému proudu. Místo volání této metody se ujistěte, že je datový proud správně uvolněn. (Zděděno od Stream) |
CopyTo(Stream) |
Přečte bajty z aktuálního datového proudu a zapíše je do jiného datového proudu. Obě pozice datových proudů jsou rozšířeny počtem bajtů zkopírovaných. (Zděděno od Stream) |
CopyTo(Stream, Int32) |
Přečte bajty z podkladového datového proudu, použije relevantní kryptografické transformace a zapíše výsledek do cílového datového proudu. |
CopyTo(Stream, Int32) |
Načte bajty z aktuálního datového proudu a zapíše je do jiného datového proudu pomocí zadané velikosti vyrovnávací paměti. Obě pozice datových proudů jsou rozšířeny počtem bajtů zkopírovaných. (Zděděno od Stream) |
CopyToAsync(Stream) |
Asynchronně čte bajty z aktuálního datového proudu a zapisuje je do jiného datového proudu. Obě pozice datových proudů jsou rozšířeny počtem bajtů zkopírovaných. (Zděděno od Stream) |
CopyToAsync(Stream, CancellationToken) |
Asynchronně čte bajty z aktuálního datového proudu a zapisuje je do jiného datového proudu pomocí zadaného tokenu zrušení. Obě pozice datových proudů jsou rozšířeny počtem bajtů zkopírovaných. (Zděděno od Stream) |
CopyToAsync(Stream, Int32) |
Asynchronně čte bajty z aktuálního datového proudu a zapisuje je do jiného datového proudu pomocí zadané velikosti vyrovnávací paměti. Obě pozice datových proudů jsou rozšířeny počtem bajtů zkopírovaných. (Zděděno od Stream) |
CopyToAsync(Stream, Int32, CancellationToken) |
Asynchronně čte bajty z podkladového datového proudu, použije relevantní kryptografické transformace a zapíše výsledek do cílového datového proudu. |
CopyToAsync(Stream, Int32, CancellationToken) |
Asynchronně čte bajty z aktuálního datového proudu a zapisuje je do jiného datového proudu pomocí zadané velikosti vyrovnávací paměti a tokenu zrušení. Obě pozice datových proudů jsou rozšířeny počtem bajtů zkopírovaných. (Zděděno od Stream) |
CreateObjRef(Type) |
Vytvoří objekt, který obsahuje všechny relevantní informace potřebné k vygenerování proxy serveru sloužícího ke komunikaci se vzdáleným objektem. (Zděděno od MarshalByRefObject) |
CreateWaitHandle() |
Zastaralé.
Zastaralé.
Zastaralé.
Přidělí objekt WaitHandle. (Zděděno od Stream) |
Dispose() |
Uvolní všechny prostředky používané Stream. (Zděděno od Stream) |
Dispose(Boolean) |
Uvolní nespravované prostředky používané CryptoStream a volitelně uvolní spravované prostředky. |
DisposeAsync() |
Asynchronně uvolní nespravované prostředky používané CryptoStream. |
DisposeAsync() |
Asynchronně uvolní nespravované prostředky používané Stream. (Zděděno od Stream) |
EndRead(IAsyncResult) |
Čeká na dokončení čekajícího asynchronního čtení. (Zvažte místo toho použití ReadAsync.) |
EndRead(IAsyncResult) |
Čeká na dokončení čekajícího asynchronního čtení. (Zvažte místo toho použití ReadAsync(Byte[], Int32, Int32).) (Zděděno od Stream) |
EndWrite(IAsyncResult) |
Ukončí asynchronní operaci zápisu. (Zvažte místo toho použití WriteAsync.) |
EndWrite(IAsyncResult) |
Ukončí asynchronní operaci zápisu. (Zvažte místo toho použití WriteAsync(Byte[], Int32, Int32).) (Zděděno od Stream) |
Equals(Object) |
Určuje, zda je zadaný objekt roven aktuálnímu objektu. (Zděděno od Object) |
Finalize() |
Umožňuje objektu pokusit se uvolnit prostředky a provést další operace čištění před uvolněním paměti. |
Flush() |
Vymaže všechny vyrovnávací paměti pro aktuální datový proud a způsobí zápis všech uložených dat do vyrovnávací paměti do podkladového zařízení. |
FlushAsync() |
Asynchronně vymaže všechny vyrovnávací paměti pro tento datový proud a způsobí zápis všech dat uložených do vyrovnávací paměti do podkladového zařízení. (Zděděno od Stream) |
FlushAsync(CancellationToken) |
Vymaže všechny vyrovnávací paměti pro aktuální datový proud asynchronně, způsobí zápis všech dat uložených do vyrovnávací paměti do základního zařízení a monitoruje žádosti o zrušení. |
FlushAsync(CancellationToken) |
Asynchronně vymaže všechny vyrovnávací paměti pro tento datový proud, způsobí zápis všech dat uložených do vyrovnávací paměti do podkladového zařízení a monitoruje žádosti o zrušení. (Zděděno od Stream) |
FlushFinalBlock() |
Aktualizuje podkladový zdroj dat nebo úložiště aktuálním stavem vyrovnávací paměti a pak vyrovnávací paměť vymaže. |
FlushFinalBlockAsync(CancellationToken) |
Asynchronně aktualizuje podkladový zdroj dat nebo úložiště aktuálním stavem vyrovnávací paměti a pak vyrovnávací paměť vymaže. |
GetHashCode() |
Slouží jako výchozí funkce hash. (Zděděno od Object) |
GetLifetimeService() |
Zastaralé.
Načte objekt služby aktuální životnosti, který řídí zásady životnosti pro tuto instanci. (Zděděno od MarshalByRefObject) |
GetType() |
Získá Type aktuální instance. (Zděděno od Object) |
InitializeLifetimeService() |
Zastaralé.
Získá objekt služby životnosti pro řízení zásad životnosti pro tuto instanci. (Zděděno od MarshalByRefObject) |
MemberwiseClone() |
Vytvoří mělkou kopii aktuálního Object. (Zděděno od Object) |
MemberwiseClone(Boolean) |
Vytvoří mělkou kopii aktuálního objektu MarshalByRefObject. (Zděděno od MarshalByRefObject) |
ObjectInvariant() |
Zastaralé.
Poskytuje podporu pro Contract. (Zděděno od Stream) |
Read(Byte[], Int32, Int32) |
Přečte posloupnost bajtů z aktuálního datového proudu a posune pozici v datovém proudu o počet přečtených bajtů. |
Read(Span<Byte>) |
Při přepsání v odvozené třídě přečte posloupnost bajtů z aktuálního datového proudu a posune pozici v datovém proudu o počet přečtených bajtů. (Zděděno od Stream) |
ReadAsync(Byte[], Int32, Int32) |
Asynchronně čte posloupnost bajtů z aktuálního datového proudu a posune pozici v datovém proudu o počet přečtených bajtů. (Zděděno od Stream) |
ReadAsync(Byte[], Int32, Int32, CancellationToken) |
Přečte posloupnost bajtů z aktuálního datového proudu asynchronně, posune pozici v datovém proudu o počet přečtených bajtů a monitoruje žádosti o zrušení. |
ReadAsync(Byte[], Int32, Int32, CancellationToken) |
Asynchronně přečte posloupnost bajtů z aktuálního datového proudu, posune pozici v datovém proudu o počet přečtených bajtů a monitoruje žádosti o zrušení. (Zděděno od Stream) |
ReadAsync(Memory<Byte>, CancellationToken) |
Asynchronně přečte posloupnost bajtů z aktuálního datového proudu, posune pozici v datovém proudu o počet přečtených bajtů a monitoruje žádosti o zrušení. |
ReadAsync(Memory<Byte>, CancellationToken) |
Asynchronně přečte posloupnost bajtů z aktuálního datového proudu, posune pozici v datovém proudu o počet přečtených bajtů a monitoruje žádosti o zrušení. (Zděděno od Stream) |
ReadAtLeast(Span<Byte>, Int32, Boolean) |
Čte alespoň minimální počet bajtů z aktuálního datového proudu a posune pozici v datovém proudu o počet přečtených bajtů. (Zděděno od Stream) |
ReadAtLeastAsync(Memory<Byte>, Int32, Boolean, CancellationToken) |
Asynchronně čte alespoň minimální počet bajtů z aktuálního datového proudu, posune pozici v rámci datového proudu o počet přečtených bajtů a monitoruje žádosti o zrušení. (Zděděno od Stream) |
ReadByte() |
Přečte bajt ze streamu a posune pozici v rámci datového proudu o jeden bajt nebo vrátí -1, pokud je na konci datového proudu. |
ReadByte() |
Přečte bajt ze streamu a posune pozici v rámci datového proudu o jeden bajt nebo vrátí -1, pokud je na konci datového proudu. (Zděděno od Stream) |
ReadExactly(Byte[], Int32, Int32) |
Přečte |
ReadExactly(Span<Byte>) |
Přečte bajty z aktuálního datového proudu a posune pozici v rámci datového proudu, dokud se |
ReadExactlyAsync(Byte[], Int32, Int32, CancellationToken) |
Asynchronně čte |
ReadExactlyAsync(Memory<Byte>, CancellationToken) |
Asynchronně čte bajty z aktuálního datového proudu, posune pozici v rámci datového proudu, dokud se |
Seek(Int64, SeekOrigin) |
Nastaví pozici v aktuálním datovém proudu. |
SetLength(Int64) |
Nastaví délku aktuálního datového proudu. |
ToString() |
Vrátí řetězec, který představuje aktuální objekt. (Zděděno od Object) |
Write(Byte[], Int32, Int32) |
Zapíše posloupnost bajtů do aktuálního CryptoStream a posune aktuální pozici v rámci datového proudu o počet zapsaných bajtů. |
Write(ReadOnlySpan<Byte>) |
Při přepsání v odvozené třídě zapíše posloupnost bajtů do aktuálního datového proudu a posune aktuální pozici v tomto datovém proudu počtem zapsaných bajtů. (Zděděno od Stream) |
WriteAsync(Byte[], Int32, Int32) |
Asynchronně zapíše posloupnost bajtů do aktuálního datového proudu a posune aktuální pozici v tomto datovém proudu o počet zapsaných bajtů. (Zděděno od Stream) |
WriteAsync(Byte[], Int32, Int32, CancellationToken) |
Zapíše posloupnost bajtů do aktuálního datového proudu asynchronně, posune aktuální pozici v rámci datového proudu o počet zapsaných bajtů a monitoruje žádosti o zrušení. |
WriteAsync(Byte[], Int32, Int32, CancellationToken) |
Asynchronně zapíše posloupnost bajtů do aktuálního datového proudu, posune aktuální pozici v tomto datovém proudu o počet zapsaných bajtů a monitoruje žádosti o zrušení. (Zděděno od Stream) |
WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) |
Asynchronně zapíše posloupnost bajtů do aktuálního datového proudu, posune aktuální pozici v tomto datovém proudu o počet zapsaných bajtů a monitoruje žádosti o zrušení. |
WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) |
Asynchronně zapíše posloupnost bajtů do aktuálního datového proudu, posune aktuální pozici v tomto datovém proudu o počet zapsaných bajtů a monitoruje žádosti o zrušení. (Zděděno od Stream) |
WriteByte(Byte) |
Zapíše bajt na aktuální pozici v datovém proudu a posune pozici v rámci datového proudu o jeden bajt. |
WriteByte(Byte) |
Zapíše bajt na aktuální pozici v datovém proudu a posune pozici v rámci datového proudu o jeden bajt. (Zděděno od Stream) |
Explicitní implementace rozhraní
IDisposable.Dispose() |
Toto rozhraní API podporuje produktovou infrastrukturu a není určené k použití přímo z uživatelského kódu. Uvolní prostředky používané aktuální instancí třídy CryptoStream. |
Metody rozšíření
CopyToAsync(Stream, PipeWriter, CancellationToken) |
Asynchronně čte bajty z Stream a zapisuje je do zadané PipeWriterpomocí tokenu zrušení. |
ConfigureAwait(IAsyncDisposable, Boolean) |
Konfiguruje, jak čekají na úlohy vrácené z asynchronního jednorázového použití. |
Platí pro
Viz také
- kryptografických služeb
- částečná a nulová bajtová čtení v deflateStream, GZipStream a CryptoStream