Disposable string enc/dec class

StewartBW 240 Reputation points
2024-03-25T00:04:21.2+00:00

Hey, I've collected a code snippet to encrypt and decrypt a string and found some code to make it a disposable class but not sure if did it properly.

First that _Key and _IV are constant private, possible to remove the Key and IV properties?

And under Dispose If disposing Then what to dispose here?

Friend NotInheritable Class secureDES
    Implements IDisposable
    Private _Key As String
    Private _IV As String
    Private Disposed As Boolean = False
    Sub New() '(ByVal Key As String)
        On Error Resume Next
        _Key = "XXXXXXXXXXXXXXXX"
        _IV = "ZZZZZZZZZZZZZZZZ"
    End Sub
    Private Property Key() As String
        Get
            Return _Key
        End Get
        Set(ByVal Value As String)
            _Key = Value
        End Set
    End Property
    Private Property IV() As String
        Get
            Return _IV
        End Get
        Set(ByVal Value As String)
            _IV = Value
        End Set
    End Property
    Private Function GenerateKey() As String
        Dim Ret As String = String.Empty
        Try
            Using Key As New DESCryptoServiceProvider
                Ret = _ByteArrayToHexString(Key.Key)
            End Using
        Catch Exception As Exception
            Exit Try
        End Try
        Return Ret
    End Function
    Private Function GenerateIV() As String
        Dim Ret As String = String.Empty
        Try
            Using IV As New DESCryptoServiceProvider
                Ret = _ByteArrayToHexString(IV.IV)
            End Using
        Catch Exception As Exception
            Exit Try
        End Try
        Return Ret
    End Function
    Friend Function EncryptString(ByVal Value As String) As String
        Dim Ret As String = String.Empty
        Try
            Using Key As New DESCryptoServiceProvider
                Key.Key = _HexStringToByteArray(_Key)
                Key.IV = _HexStringToByteArray(_IV)
                Ret = _ByteArrayToHexString(_Encrypt(Value, Key))
                Return Ret
            End Using
        Catch Exception As Exception
            Exit Try
        End Try
        Return Ret
    End Function
    Friend Function DecryptString(ByVal Value As String) As String
        Dim Ret As String = String.Empty
        Try
            Using Key As New DESCryptoServiceProvider
                Key.Key = _HexStringToByteArray(_Key)
                Key.IV = _HexStringToByteArray(_IV)
                Ret = _Decrypt(_HexStringToByteArray(Value), Key)
                Return Ret
            End Using
        Catch Exception As Exception
            Exit Try
        End Try
        Return Ret
    End Function
    Private Function _Encrypt(ByVal PlainText As String, ByVal Key As SymmetricAlgorithm) As Byte()
        Dim Ret As Byte() = Nothing
        Try
            Using MyMemoryStream As New MemoryStream
                Using MyCryptoStream As New CryptoStream(MyMemoryStream, Key.CreateEncryptor(), CryptoStreamMode.Write)
                    Using MyStreamWriter As New StreamWriter(MyCryptoStream)
                        MyStreamWriter.WriteLine(PlainText)
                    End Using
                    Ret = MyMemoryStream.ToArray()
                    Return Ret
                End Using
            End Using
        Catch Exception As Exception
            Exit Try
        End Try
        Return Ret
    End Function
    Private Function _Decrypt(ByVal CypherText() As Byte, ByVal Key As SymmetricAlgorithm) As String
        Dim Ret As String = String.Empty
        Try
            Using MyMemoryStream As New MemoryStream(CypherText)
                Using MyCryptoStream As New CryptoStream(MyMemoryStream, Key.CreateDecryptor(), CryptoStreamMode.Read)
                    Using MyStreamReader As New StreamReader(MyCryptoStream)
                        Ret = MyStreamReader.ReadLine()
                    End Using
                End Using
            End Using
        Catch Exception As Exception
            Exit Try
        End Try
        Return Ret
    End Function
    Private Function _HexStringToByteArray(ByVal Value As String) As Byte()
        Dim Ret(Convert.ToInt32((Value.Length / 2) - 1)) As Byte
        Try
            For MyLoop As Integer = 0 To Ret.Length - 1
                Ret(MyLoop) = Byte.Parse(Value.Substring(MyLoop * 2, 2), NumberStyles.HexNumber)
            Next
        Catch Exception As Exception
            Exit Try
        End Try
        Return Ret
    End Function
    Private Function _ByteArrayToHexString(ByVal Value() As Byte) As String
        Dim Ret As New StringBuilder
        Try
            For Each MyByte As Byte In Value
                Ret.Append(MyByte.ToString("x2"))
            Next
        Catch Exception As Exception
            Exit Try
        End Try
        Return Ret.ToString
    End Function
    Friend Sub Dispose() Implements IDisposable.Dispose
        On Error Resume Next
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    Protected Sub Dispose(disposing As Boolean)
        On Error Resume Next
        If Not Disposed Then
            If disposing Then
                'What2Dispose?.Dispose()
                'What2Dispose?.Dispose()
            End If
            Disposed = True
        End If
    End Sub
    Protected Overrides Sub Finalize()
        On Error Resume Next
        Dispose(False)
        MyBase.Finalize()
    End Sub
End Class
VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,555 questions
{count} votes

Accepted answer
  1. Jiachen Li-MSFT 26,096 Reputation points Microsoft Vendor
    2024-03-25T07:23:22.0166667+00:00

    Hi @StewartBW ,

    1. Since you're using constant private fields for _Key and _IV, and they are not meant to be modified after initialization, you can indeed remove the properties Key and IV. You can directly access _Key and _IV within your class.
    2. In the Dispose method, you should dispose of any managed resources your class may have acquired. In this case, since you're using cryptographic providers (DESCryptoServiceProvider), which implement IDisposable, you should dispose of them.
    Friend Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    
    Protected Sub Dispose(disposing As Boolean)
        If Not Disposed Then
            If disposing Then
                ' Dispose managed resources.
                Dim keyProvider As New DESCryptoServiceProvider()
                keyProvider.Dispose()
                Dim ivProvider As New DESCryptoServiceProvider()
                ivProvider.Dispose()
            End If
            ' There are no unmanaged resources to release.
            Disposed = True
        End If
    End Sub
    
    

    Best Regards.

    Jiachen Li


    If the answer is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Michael Taylor 47,461 Reputation points
    2024-03-27T20:51:46.06+00:00

    You do not need to implement IDisposable for this type. It is wasteful and unneeded so remove it. The only time you need to implement IDisposable is if you store an instance of an object that itself implements IDisposable OR you are storing unmanaged resources. I don't see that you're doing either in this type so there is no benefit to implementing the interface.

    The only places I see you working with a disposable object is inside private methods that wrap the code in a using statement. Therefore the disposable objects are cleaned up before the methods return. Hence you don't need the interface.

    Now, creating a crypto provider isn't cheap so you might consider reusing the crypto provider that your methods are creating throughout the lifetime of the owning type instead of each time the method is called. In this case you'd need to promote the provider object to a field of the class. Now, since you are storing a disposable object, you'd need to implement IDisposable to clean up the field(s). If you don't always need the providers then you could lazy initialize them instead. You still need to implement the interface but now you can check to see if the providers were created before cleaning them up. It is important to note that you would need to clean up the providers only if the disposing parameter was true. If it is false then they might have already been cleaned up so you would simply do nothing as Jiachen Li demonstrates.

    1 person found this answer helpful.
    0 comments No comments