Imports System.Configuration
Imports System.Security.Cryptography
Imports System.Text
Imports Strata.Configuration.Client.Models.Jazz

Namespace Encryptors

    Public Class UserSaltEncryptionMethod
        Implements IPasswordEncryptionMethod

#Region " Declarations "

        Private Const NUMBER_ITERATIONS As Integer = 100000

#End Region

#Region " Methods "

        Public Function Encode(ByVal username As String, ByVal anOrgPin As String, ByVal aNewPassword As String, ByVal aUserGUID As System.Guid, aSalt As String) As String Implements IPasswordEncryptionMethod.Encode
            If username Is Nothing Then
                Throw New ArgumentNullException(NameOf(username))
            End If

            If anOrgPin Is Nothing Then
                Throw New ArgumentNullException(NameOf(anOrgPin))
            End If

            If aNewPassword Is Nothing Then
                Throw New ArgumentNullException(NameOf(aNewPassword))
            End If

            If aSalt Is Nothing Then
                Throw New ArgumentNullException(NameOf(aSalt))
            End If

            ' Get encryption key from config, throw if not found
            Dim encryptionKey As String = ConfigurationManager.AppSettings(NameOf(StrataJazzOptions.UserSaltEncryptionKey))
            If String.IsNullOrEmpty(encryptionKey) Then
                Throw New ConfigurationErrorsException("UserSaltEncryptionKey not found in configuration")
            End If

            ' Combine salt with encryption key
            Dim saltAndPepper As String = aSalt & encryptionKey

            ' Use UTF8 encoding to properly handle Unicode characters
            Using deriveBytes As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(aNewPassword, Encoding.UTF8.GetBytes(saltAndPepper), NUMBER_ITERATIONS, HashAlgorithmName.SHA256)
                Dim password As Byte() = deriveBytes.GetBytes(24)
                Return Convert.ToBase64String(password)
            End Using
        End Function

#End Region

    End Class

End Namespace
