-
-
Notifications
You must be signed in to change notification settings - Fork 3
Examples
Andrew Lambert edited this page Nov 26, 2022
·
13 revisions
- Secure memory
- Password hashing
- Generic hashing
- Encrypting streams or files
- PKI
- Encryption
- Digital signatures
- SKI
- Encryption
- Message authentication
This example is a BinaryStream workalike class that encrypts or decrypts a single file with a password. The initialization vector for the cipher and the salt for the password-based key generator are randomly generated and stored alongside the encrypted stream in a Xojo VirtualVolume. Download the source file here. See farther down the page for a demonstration of this class.
Public Class PasswordProtectedFile
Implements Readable,Writeable
Private Property mFileSys As VirtualVolume
Private Property mReadable As Boolean
Private Property mStream As libsodium.SKI.SecretStream
Protected Sub Constructor(Key As libsodium.SKI.SecretKey, FileSys As VirtualVolume)
' This protected constructor is called by the Create() and Open() shared methods.
' Any kind of SecretKey could be used here, not just ones derived from passwords.
' A SharedSecret key could also be used if the Key parameter's datatype were changed
' accordingly.
mFileSys = FileSys
If mFileSys.Root.Child("_iv").Exists Then
' decrypt mode
mReadable = True
Dim payloadstream As BinaryStream = BinaryStream.Open(mFileSys.Root.Child("_payload"))
Dim bs As BinaryStream = BinaryStream.Open(mFileSys.Root.Child("_iv"))
Dim iv As MemoryBlock = bs.Read(bs.Length)
bs.Close
mStream = mStream.Open(Key, payloadstream, iv)
Else
' encrypt mode
mReadable = False
Dim payloadstream As BinaryStream = BinaryStream.Create(mFileSys.Root.Child("_payload"))
mStream = mStream.Create(Key, payloadstream)
Dim bs As BinaryStream = BinaryStream.Create(mFileSys.Root.Child("_iv"))
bs.Write(mStream.DecryptionHeader)
bs.Close
End If
End Sub
Shared Function Create(Destination As FolderItem, Passwd As libsodium.Password) As PasswordProtectedFile
' This method derives a key from the password plus a random salt and then
' returns a PasswordProtectedFile in encrypt/write-only mode.
Dim filesys As VirtualVolume = Destination.CreateVirtualVolume()
Dim key As New libsodium.SKI.SecretKey(Passwd)
Dim bs As BinaryStream = BinaryStream.Create(filesys.Root.Child("_salt"))
bs.Write(key.Salt)
bs.Close
Return New PasswordProtectedFile(key, filesys)
End Function
Sub Write(text As String)
// Part of the Writeable interface.
If Not mReadable And mStream <> Nil Then mStream.Write(text)
End Sub
Shared Function Open(Source As FolderItem, Passwd As libsodium.Password) As PasswordProtectedFile
' This method derives the key from the password plus the salt stored in the
' file and then returns a PasswordProtectedFile in decrypt/read-only mode.
Dim filesys As VirtualVolume = Source.OpenAsVirtualVolume()
If filesys = Nil Or Not filesys.Root.Child("_salt").Exists Then Raise New IOException ' not a PasswordProtectedFile!
Dim bs As BinaryStream = BinaryStream.Open(filesys.Root.Child("_salt"))
Dim salt As MemoryBlock = bs.Read(bs.Length)
bs.Close
Dim key As New libsodium.SKI.SecretKey(Passwd, salt)
Return New PasswordProtectedFile(key, filesys)
End Function
Function Read(Count As Integer, encoding As TextEncoding = Nil) As String
// Part of the Readable interface.
If mReadable And mStream <> Nil Then Return mStream.Read(Count, encoding)
End Function
Sub Close()
If mStream <> Nil Then mStream.Close
If mFileSys <> Nil Then mFileSys.Flush()
mStream = Nil
mFileSys = Nil
End Sub
Private Sub Destructor()
Me.Close()
End Sub
Function EOF() As Boolean
// Part of the Readable interface.
Return mReadable And (mStream <> Nil And mStream.EOF)
End Function
Sub Flush()
// Part of the Writeable interface.
If Not mReadable And mStream <> Nil Then mStream.Flush()
End Sub
Function ReadError() As Boolean
// Part of the Readable interface.
Return mReadable And (mStream <> Nil And mStream.ReadError)
End Function
Function WriteError() As Boolean
// Part of the Writeable interface.
Return Not mReadable And (mStream <> Nil And mStream.WriteError)
End Function
End Class
This example uses the PasswordProtectedFile
class to encrypt a file:
Dim passwd As libsodium.Password = "seekrit"
Dim src As FolderItem = GetOpenFolderItem("") ' the file to be protected
Dim dst As FolderItem = GetSaveFolderItem("", src.Name + ".encrypted") ' the output file
Dim srcstream As BinaryStream = BinaryStream.Open(src)
Dim dststream As PasswordProtectedFile = PasswordProtectedFile.Create(dst, passwd)
Do Until srcstream.EOF
dststream.Write(srcstream.Read(1024 * 1024 * 32))
Loop
srcstream.Close()
dststream.Close()
This example uses the PasswordProtectedFile
class to decrypt the file from the previous example:
Dim passwd As libsodium.Password = "seekrit"
Dim src As FolderItem = GetOpenFolderItem("") ' the file to be decrypted
Dim dst As FolderItem = GetSaveFolderItem("", Replace(src.Name,".encrypted", "")) ' the output file
Dim srcstream As PasswordProtectedFile = PasswordProtectedFile.Open(src, passwd)
Dim dststream As BinaryStream = BinaryStream.Create(dst)
Do Until srcstream.EOF
dststream.Write(srcstream.Read(1024 * 1024 * 32))
Loop
srcstream.Close()
dststream.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.