-
-
Notifications
You must be signed in to change notification settings - Fork 3
Compressed SecretStream Example
This class is a subclass of the SecretStream class that compresses or decompresses the encrypted data stream with GZip. This class uses the zlib
module from the RB-zlib project to perform compression and decompression, so be sure to have imported it into your project before attempting to use this class.
Download the source file for this class here. See farther down the page for a demonstration of this class.
Combining compression and encryption can potentially leak information if an attacker can control the input. The SecretStream
class already mitigates this attack vector by applying padding before encrypting, but for maximum security do not use compression if the input is untrusted.
Class CompressedSecretStream
Inherits libsodium.SKI.SecretStream
Private Property mCompressor As zlib.Deflater
Private Property mDecompressor As zlib.Inflater
Sub Close()
If mCompressor <> Nil Then
Dim data As String = mCompressor.Deflate("", zlib.Z_FINISH)
mWriteBuffer = mWriteBuffer + data
End If
Super.Close()
End Sub
Protected Sub Constructor(InputStream As Readable, Key As MemoryBlock, Header As MemoryBlock)
mDecompressor = New zlib.Inflater(zlib.GZIP_ENCODING)
// Calling the overridden superclass constructor.
// Constructor(InputStream As Readable, Key As MemoryBlock, Header As MemoryBlock) -- From SecretStream
Super.Constructor(InputStream, Key, Header)
End Sub
Protected Sub Constructor(OutputStream As Writeable, Key As MemoryBlock)
mCompressor = New zlib.Deflater(zlib.Z_DEFAULT_COMPRESSION, zlib.Z_DEFAULT_STRATEGY, zlib.GZIP_ENCODING)
// Calling the overridden superclass constructor.
// Constructor(OutputStream As Writeable, Key As MemoryBlock) -- From SecretStream
Super.Constructor(OutputStream, Key)
End Sub
Shared Function Create(Key As libsodium.SKI.KeyContainer, OutputStream As Writeable) As CompressedSecretStream
If Key IsA libsodium.Password Then Raise New libsodium.SodiumException(libsodium.ERR_KEYTYPE_MISMATCH)
Return New CompressedSecretStream(OutputStream, Key.Value)
End Function
Shared Function Open(Key As libsodium.SKI.KeyContainer, InputStream As Readable, DecryptHeader As FolderItem, HeaderPassword As libsodium.Password = Nil) As CompressedSecretStream
If Key IsA libsodium.Password Then Raise New libsodium.SodiumException(libsodium.ERR_KEYTYPE_MISMATCH)
Dim bs As BinaryStream = BinaryStream.Open(DecryptHeader)
Dim metadata As Dictionary
Dim header As MemoryBlock = bs.Read(bs.Length)
If header.StringValue(0, 5) = "-----" Then header = libsodium.Exporting.Import(header, metadata, HeaderPassword)
Return New CompressedSecretStream(InputStream, Key.Value, header)
End Function
Shared Function Open(Key As libsodium.SKI.KeyContainer, InputStream As Readable, DecryptHeader As MemoryBlock, HeaderPassword As libsodium.Password = Nil) As CompressedSecretStream
If Key IsA libsodium.Password Then Raise New libsodium.SodiumException(libsodium.ERR_KEYTYPE_MISMATCH)
Dim metadata As Dictionary
If DecryptHeader.StringValue(0, 5) = "-----" Then DecryptHeader = libsodium.Exporting.Import(DecryptHeader, metadata, HeaderPassword)
Return New CompressedSecretStream(InputStream, Key.Value, DecryptHeader)
End Function
Function Read(Count As Integer, encoding As TextEncoding = Nil) As String
Dim data As String = Super.Read(Count, encoding)
If mDecompressor <> Nil Then data = mDecompressor.Inflate(data)
Return DefineEncoding(data, encoding)
End Function
Sub Write(text As String)
If mCompressor <> Nil Then text = mCompressor.Deflate(text, zlib.Z_NO_FLUSH)
Super.Write(text)
End Sub
End Class
This class can be used exactly the same way a plain SecretStream
is used. Just replace libsodium.SKI.SecretStream
with CompressedSecretStream
when creating or opening the stream.
This example encrypts and compresses a file and saves the decryption header/initialization vector to another file:
Dim mykey As libsodium.SKI.SecretKey
mykey = mykey.Generate ' random key for example
Dim src As FolderItem = GetOpenFolderItem("")
Dim state As FolderItem = src.Parent.Child(src.Name + ".state")
Dim dst As FolderItem = src.Parent.Child(src.Name + ".crypt")
Dim bsin As BinaryStream = BinaryStream.Open(src)
Dim bsout As BinaryStream = BinaryStream.Create(dst)
Dim stream As CompressedSecretStream = CompressedSecretStream.Create(mykey, bsout)
Do Until bsin.EOF
stream.Write(bsin.Read(1024 * 64))
Loop
Call stream.ExportDecryptionHeader(state)
stream.Close
bsout.Close
bsin.Close
This example decrypts and decompresses the file from the previous example:
' continuing from above
bsin = BinaryStream.Open(dst)
bsout = BinaryStream.Create(src.Parent.Child(src.Name + ".decrypted"))
stream = CompressedSecretStream.Open(mykey, bsin, state)
Do Until stream.EOF Or stream.ReadError
bsout.Write(stream.Read(1024 * 64))
Loop
stream.Close
bsout.Close
bsin.Close
Wiki home | Project page | Bugs | Become a sponsor
Text and code examples are Copyright ©2016-24 Andrew Lambert, offered under the CC BY-SA 3.0 License.