More .NET components

XTS-AES Stream

Transparent read/write stream decryption/encryption #

XtsStream is a .NET stream that implements XTS-AES, a standard algorithm for protection of stored data defined by IEEE P1619.

An instance XtsStream wrapped around a Stream object transparently adds encryption and decryption capabilities to your application:

CSharp

// open a file stream
var fs = File.Open("data.xts", FileMode.OpenOrCreate);

// create an XTS-AES stream on top of the file stream to add encryption/decryption
var xts = new XtsStream(fs, "secret password");

// use the XTS-AES stream just like you would use the file stream
SaveDataToStream(xts);

VisualBasic

' open a file stream
Dim fs = File.Open("data.xts", FileMode.OpenOrCreate)

' create an XTS-AES stream on top of the file stream to add encryption/decryption
Dim xts = New XtsStream(fs, "secret password")

' use the XTS-AES stream just like you would use the file stream
SaveDataToStream(xts)

xts.Close()

Unlike .NET's CryptoStream, XtsStream is seekable and both readable/writable. This makes it possible to do this, for example:

CSharp

// saving or loading?
if (saving)
{
    // trim the stream to zero length
    xts.SetLength(0);

    // save some data to the stream
    SaveDataToStream(xts);
}
else
{
    // seek to the beginning of the stream
    xts.Position = 0;

    // load some data from the stream
    LoadDataFromStream(xts);
}

xts.Close();

VisualBasic

' saving or loading?
If saving Then
    ' trim the stream to zero length
    xts.SetLength(0)

    ' save some data to the stream
    SaveDataToStream(xts)
Else
    ' seek to the beginning of the stream
    xts.Position = 0

    ' load some data from the stream
    LoadDataFromStream(xts)
End If

xts.Close()

See Seeking and random access for more information on seeking, reading and writing.

RSA public/private key cryptography #

In addition to password-based encryption, XtsStream supports asymmetric cryptography as well. This makes it possible to encrypt a file using an public key and decrypt it using the corresponding private key.

Generating public/private key pairs:

CSharp

// generate an RSA private key and save it
var privateKey = PrivateKeyInfo.Generate(KeyAlgorithm.RSA, 2048);
privateKey.Save("key.pri", "key password", PrivateKeyFormat.Base64Pkcs8);

// get the corresponding public key and save it
var publicKey = privateKey.GetPublicKey();
publicKey.Save("key.pub"); // no password because it's public

VisualBasic

' generate an RSA private key and save it
Dim privateKey As PrivateKeyInfo = PrivateKeyInfo.Generate(KeyAlgorithm.RSA, 2048)
privateKey.Save("key.pri", "key password", PrivateKeyFormat.Base64Pkcs8)

' get the corresponding public key and save it
Dim publicKey As PublicKeyInfo = privateKey.GetPublicKey()
publicKey.Save("key.pub") ' no password because it's public

Encrypting data using a public key:

CSharp

// load the public key
var publicKey = new PublicKeyInfo();
publicKey.Load("key.pub");

// save text into a file ecnrypted using the public key
using (var writer = new StreamWriter(new XtsStream(File.Create("data.xts"), publicKey)))
{
    writer.WriteLine("This file has been encrypted using an RSA public key.");
    writer.WriteLine("More data...");
}

VisualBasic

' load the public key
Dim publicKey As New PublicKeyInfo()
publicKey.Load("key.pub")

' save text into a file ecnrypted using the public key
Using writer As New StreamWriter(New XtsStream(File.Create("data.xts"), publicKey))
    writer.WriteLine("This file has been encrypted using an RSA public key.")
    writer.WriteLine("More data...")
End Using

Decrypting data using a private key:

CSharp

// load the private key
var privateKey = new PrivateKeyInfo();
privateKey.Load("key.pri", "key password");

// read text from a file decrypted using a private key
using (var reader = new StreamReader(new XtsStream(File.OpenRead("data.xts"), privateKey)))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        Console.WriteLine(line);
    }
}

VisualBasic

' load the private key
Dim privateKey As New PrivateKeyInfo()
privateKey.Load("key.pri", "key password")

' read text from a file decrypted using a private key
Using reader As New StreamReader(New XtsStream(File.OpenRead("data.xts"), privateKey))
    While True
        Dim line As String = reader.ReadLine()
        If line = Nothing Then Exit While
        Console.WriteLine(line)
    End While
End Using

Integrates easily with existing applications #

XtsStream is a .NET Stream that transparently adds encryption/decryption support to other Stream objects, which makes it simple to integrate it with existing applications and .NET objects that use streams.

For example, if your application loads and saves XML documents using .NET's XmlDocument, adding XtsStream is all you need to store the XML files securely. The following code saves (encrypts) an XML document into an encrypted file:

CSharp

// open a file stream
Stream output = File.Create("list.xts");

// create an XTS-AES stream on top of the file stream to add encryption/decryption
output = new XtsStream(output, "secret password");

// construct a XML document
var xml = new XmlDocument();
var list = xml.CreateElement("list");
xml.AppendChild(list);
XmlElement item;
item = xml.CreateElement("item"); item.InnerText = "Rebex Security"; list.AppendChild(item);
item = xml.CreateElement("item"); item.InnerText = "Rebex SFTP"; list.AppendChild(item);
item = xml.CreateElement("item"); item.InnerText = "Rebex FTP/SSL"; list.AppendChild(item);

// save the XML document into an encrypted stream
xml.Save(output);

// close the streams
output.Close();

VisualBasic

' open a file stream
Dim output As Stream = File.Create("list.xts")

' create an XTS-AES stream on top of the file stream to add encryption/decryption
output = New XtsStream(output, "secret password")

' construct a XML document
Dim xml = New XmlDocument()
Dim list = xml.CreateElement("list")
xml.AppendChild(list)
Dim item As XmlElement
item = xml.CreateElement("item")
item.InnerText = "Rebex Security"
list.AppendChild(item)
item = xml.CreateElement("item")
item.InnerText = "Rebex SFTP"
list.AppendChild(item)
item = xml.CreateElement("item")
item.InnerText = "Rebex FTP/SSL"
list.AppendChild(item)

' save the XML document into an encrypted stream
xml.Save(output)

' close the streams
output.Close()

As you can see, adding a single line of code (the one with XtsStream constructor) was the only change needed to add encryption support!

Loading (decrypting) the encrypted XML document is just as simple:

CSharp

// open a file stream
Stream input = File.OpenRead("list.xts");

// create an XTS-AES stream on top of the file stream to add encryption/decryption
input = new XtsStream(input, "secret password");

// load a XML document from the encrypted stream
var xml = new XmlDocument();
xml.Load(input);

// display the XML document
Console.WriteLine(xml.InnerXml);

// close the stream
input.Close();

VisualBasic

' open a file stream
Dim input As Stream = File.OpenRead("list.xts")

' create an XTS-AES stream on top of the file stream to add encryption/decryption
input = New XtsStream(input, "secret password")

' load a XML document from the encrypted stream
Dim xml = New XmlDocument()
xml.Load(input)

' display the XML document
Console.WriteLine(xml.InnerXml)

' close the stream
input.Close()

Again, adding a single line of code was the only change needed.

To convert existing unencrypted files or streams to a format supported by XtsStream, use FileEncryption object with EncryptionAlgorithm set to AesXts.

Writing to an encrypted stream #

XtsStream makes it possible to easily add strong encryption support to existing applications that are already stream-based - just wrap an instance of XtsStream around your stream.

The following code demonstrates this by creating an encrypted log file:

CSharp

// open a file stream
var fs = File.Open("log.xts", FileMode.OpenOrCreate);

// create an XTS-AES stream on top of the file stream to add encryption/decryption
var xts = new XtsStream(fs, "secret password");

// seek to an end of the stream (we will append data to its end)
xts.Seek(0, SeekOrigin.End);

// create a stream writer on top of the encrypted stream
var writer = new StreamWriter(xts, Encoding.UTF8);

// log some messages
writer.WriteLine("Encrypted log file is accessible now.");
writer.WriteLine("Machine name: {0}", Environment.MachineName);
writer.WriteLine("Current time is: {0}", DateTime.Now);
writer.WriteLine(message);

// flush the writer to make sure all changes were saved
// (or use writer.AutoFlush if preferred)
writer.Flush();

// close the writer and underlying streams
writer.Close();

VisualBasic

' open a file stream
Dim fs = File.Open("log.xts", FileMode.OpenOrCreate)

' create an XTS-AES stream on top of the file stream to add encryption/decryption
Dim xts = New XtsStream(fs, "secret password")

' seek to an end of the stream (we will append data to its end)
xts.Seek(0, SeekOrigin.[End])

' create a stream writer on top of the encrypted stream
Dim writer = New StreamWriter(xts, Encoding.UTF8)

' log some messages
writer.WriteLine("Encrypted log file is accessible now.")
writer.WriteLine("Machine name: {0}", Environment.MachineName)
writer.WriteLine("Current time is: {0}", DateTime.Now)
writer.WriteLine(message)

' flush the writer to make sure all changes were saved
' (or use writer.AutoFlush if preferred)
writer.Flush()

' close the writer and underlying streams
writer.Close()

To decrypt the log, simply read from the XtsStream.

To convert existing unencrypted files or streams to a format supported by XtsStream, use FileEncryption object with EncryptionAlgorithm set to AesXts.

Reading from an encrypted stream #

Reading data from an encrypted XtsStream is simple:

CSharp

// open a file stream
var fs = File.Open("log.xts", FileMode.OpenOrCreate);

// create an XTS-AES stream on top of the file stream to add encryption/decryption
var xts = new XtsStream(fs, "secret password");

// create a stream reader on top of the encrypted stream
var reader = new StreamReader(xts, Encoding.UTF8);

for (; ; )
{
    // read a line from the encrypted log
    string line = reader.ReadLine();

    // exit the loop when end-of-file reached
    if (line == null)
        break;

    // display the line otherwise
    Console.WriteLine(line);
}

// close the reader and underlying streams
reader.Close();

VisualBasic

' open a file stream
Dim fs = File.Open("log.xts", FileMode.OpenOrCreate)

' create an XTS-AES stream on top of the file stream to add encryption/decryption
Dim xts = New XtsStream(fs, "secret password")

' create a stream reader on top of the encrypted stream
Dim reader = New StreamReader(xts, Encoding.UTF8)

While True
    ' read a line from the encrypted log
    Dim line As String = reader.ReadLine()

    ' exit the loop when end-of-file reached
    If line Is Nothing Then
        Exit While
    End If

    ' display the line otherwise
    Console.WriteLine(line)
End While

' close the reader and underlying streams
reader.Close()

Alternatively, use FileEncryption object to decrypt the file easily:

CSharp

// create an encryption/decryption object
var encryptor = new FileEncryption();

// specify password
encryptor.SetPassword("secret password");

// decrypt a file
encryptor.Decrypt("log.xts", "log.txt");

VisualBasic

' create an encryption/decryption object
Dim encryptor = New FileEncryption()

' specify password
encryptor.SetPassword("secret password")

' decrypt a file
encryptor.Decrypt("log.xts", "log.txt")

Seeking and random access #

XtsStream is seekable - it support nonsequential, or random, access to a stream's contents. In fact, it works just like a FileStream, but adds transparent encryption/decryption support on top of that. Unlike .NET's CryptoStream, XtsStream supports Seek method, Position property. It also supports both Read and Write.

To access stream data randomly, just seek to a particular location and read from or write to it:

CSharp

// open a file stream
var fs = File.Open("file.xts", FileMode.OpenOrCreate);

// create an XTS-AES stream on top of the file stream to add encryption/decryption
var xts = new XtsStream(fs, "secret password");

// seek anywhere in the file
xts.Seek(100000, SeekOrigin.Begin);

// read data from the current position
xts.Read(buffer, 0, 500);

// write something there
xts.Write(buffer, 0, 300);

// seek somewhere else
xts.Seek(-100, SeekOrigin.End);

// write something there
xts.Write(buffer, 0, 200);

// position works as well
xts.Position = 400;

// read some data
xts.Read(buffer, 0, 100);

// close the stream
xts.Close();

VisualBasic

' open a file stream
fs = File.Open("file.xts", FileMode.OpenOrCreate)

' create an XTS-AES stream on top of the file stream to add encryption/decryption
xts = New XtsStream(fs, "secret password")

' seek anywhere in the file
xts.Seek(100000, SeekOrigin.Begin)

' read data from the current position
xts.Read(buffer, 0, 500)

' write something there
xts.Write(buffer, 0, 300)

' seek somewhere else
xts.Seek(-100, SeekOrigin.[End])

' write something there
xts.Write(buffer, 0, 200)

' position works as well
xts.Position = 400

' read some data
xts.Read(buffer, 0, 100)

' close the stream
xts.Close()