:SetVar Procedure "TMP:PrepareUserPassword"
:r $(DropProcedureScript_AUX)
create procedure [$(Procedure)]
   @Password         $(dt_UserPassword_Str),
   @MaskedPassword   $(dt_UserPassword) out
AS
/*==================================================================================================
# BookRegistry app. | Author: Sergei Y.Kitáev
----------------------------------------------------------------------------------------------------
#
# DATA PREPARATION FOR USER PASSWORD SAVING (MASKING) — TEMPORARY SP:
#
# === Usage: ===
# exec [TMP:PrepareUserPassword] N'<Password>', @<MaskedPasswordVariable> out
#
# *** CAUTION! ***
# PASSWORD MASKING IS FOR TEST PURPOSE ONLY!
# IN REAL APPLICATION HASH ALGORITHM OR STRONG ENCRYPTION IS NEEDED INSTEAD!
#
==================================================================================================*/
$(BEGIN_AUX)
----------------------------------------------------------------------------------------------------
set @MaskedPassword = null
----------------------------------------------------------------------------------------------------
if @Password is null
   exec [AUX:RaiseIncorrectProcedureCall] N'$(Procedure)'
----------------------------------------------------------------------------------------------------
declare @ErrorMessage $(dt_Message_AUX)
----------------------------------------------------------------------------------------------------
if LEN( @Password ) > $(num_UserPasswordMaxLength)
   raiserror ('User password is too long.',11,1)
----------------------------------------------------------------------------------------------------
declare @PasswordMask $(dt_UserPassword)
set @PasswordMask = $(bin_UserPasswordMask)
if DATALENGTH( @PasswordMask ) <> $(num_UserPasswordMaxLength) * 2
   raiserror ('User password mask has incorrect size.',11,1)
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
declare @PasswordData $(dt_UserPassword), @PasswordLen int, @idx int

select
   @PasswordData = SUBSTRING(0x0,1,0),
   @PasswordLen = LEN( @Password ),
   @idx = 0
while @idx < @PasswordLen
begin
   declare @highByte int, @lowByte int, @word int, @bin binary(2)
   set @bin = CONVERT( binary(2), SUBSTRING( @Password, @idx+1, 1 ))
   select
      @highByte = CONVERT( int, CONVERT( binary(1), SUBSTRING(@bin,2,1))) * 256,
      @lowByte  = CONVERT( int, CONVERT( binary(1), SUBSTRING(@bin,1,1)))
   set @word = @highByte | @lowByte
   select
      @highByte = CONVERT( int, SUBSTRING( @PasswordMask, @idx*2+1, 1 )) * 256,
      @lowByte  = CONVERT( int, SUBSTRING( @PasswordMask, @idx*2+2, 1 ))
   set @bin = CONVERT( binary(2), @word ^ @highByte ^ @lowByte )
   set @PasswordData = @PasswordData + @bin
   set @idx = @idx + 1
end

set @MaskedPassword = @PasswordData
----------------------------------------------------------------------------------------------------
$(END_AUX)
/*================================================================================================*/
GO
/*
declare @MaskedPassword varbinary(60)
exec [TMP:PrepareUserPassword] 'abcdefg', @MaskedPassword out
select @MaskedPassword 'Masked password'
*/
