/********************************
VERY SIMPLE ASCII ENCRYPTION
*********************************/
/*
This is a very simple ASCII encryption which takes a string and transposes the characters onto the unicode set using an increment number.
This isn't a strong encryption regime, but it can be better than storing sensitive information as plain text.
Unicode has characters which are listed in a certain order. This code takes the ASCII character and adds the increment number to it, resulting
in a unicode character that is farther down the list. To slightly strengthen the encryption, the index number of the string is added so that repeated
characters do not always return the same unicode character. For example, a 'T' in the first position[0] with an increment of 120 will be moved down the
list by 120 + 0, and a 'T' in the second position[1] will be moved down by 120 + 1, resulting in a different unicode character, and a 'T'in the third
position[2] will be 120 + 2, resulting in a third unicode character, etc.
The list of unicode characters looks like this, and can be found at https://en.wikipedia.org/wiki/List_of_Unicode_characters.
Code Glyph Decimal Description #
U+0061 a 97 Latin Small Letter A 0066
U+0062 b 98 Latin Small Letter B 0067
U+0063 c 99 Latin Small Letter C 0068
U+0064 d 100 Latin Small Letter D 0069
U+0065 e 101 Latin Small Letter E 0070
...
U+00D0 Ð 0208 Latin Capital letter Eth 0144
U+00D1 Ñ 0209 Latin Capital letter N with tilde 0145
U+00D2 Ò 0210 Latin Capital letter O with grave 0146
U+00D3 Ó 0211 Latin Capital letter O with acute 0147
U+00D4 Ô 0212 Latin Capital letter O with circumflex 0148
For example, saying you're encyrpting the following string (with the index positions counted below), and say the increment is 128:
This is the string to be encrypted.
01234567890123456789012345678901234 -- count single digits
0 1 2 3 -- count tens
- For the first character 'T', this is unicode decimal 84 and it's the first position, so the calculation is 84 + 0 + 128, which is decimal 212 (Ô)
- For the next character 'h', this is unicode decimal 104 and it's the second position, so the calculation is 104 + 1 + 128, which is decimal 233 (é)
- For the next character 'i', this is unicode decimal 105 and it's the third position, so the calculation is 105 + 2 + 128, which is decimal 235 (ë)
- For the next character 's', this is unicode decimal 115 and it's the fourth position, so the calculation is 115 + 3 + 128, which is decimal 246 (ö)
- For the next character ' ', this is unicode decimal 32 and it's the fifth position, so the calculation is 32 + 4 + 128, which is decimal 164 (¤)
The resulting encrypted string is Ôéëö¤îù§üñï«ÿāĀøþø²ćăµøü¸þĈþĎĖĎēąąÐ
This string can then be put through the decryption code to decrypt it.
If you're encasing the encryption algorithm in a function, a hacker could in theory view how you're encrypting the values to be able to decrypt the values and view
the original clear strings. A second level of security is that you can use WITH ENCRYPTION when creating the fuction - this will make it so the function
definition is not visible to anyone (including admins) after creation.
*/
DECLARE @parameter_clear_string_to_be_encrypted VARCHAR(100) = 'This is the string to be encrypted.'
DECLARE @vEncryptedString NVARCHAR(100) -- variable to hold the encrypted string
DECLARE @vCounter INT -- variable to hold increment counter
DECLARE @vBaseIncrement INT -- variable to hold the increment
SET @vCounter = 1 -- set counter to 1
SET @vBaseIncrement = 128 -- set increment to 128
SET @vEncryptedString = ''
WHILE @vCounter <= LEN(@parameter_clear_string_to_be_encrypted) -- while counter is less than or equal to length of string to be encrypted
BEGIN
SET @vEncryptedString = @vEncryptedString +
NCHAR(ASCII(SUBSTRING(@parameter_clear_string_to_be_encrypted, @vCounter, 1)) +
@vBaseIncrement + @vCounter - 1)
SET @vCounter = @vCounter + 1
END
-- view the results
SELECT @vEncryptedString AS 'Encrypted String'
-- DECRYPT THE ENCRYPTED STRING
DECLARE @vClearString VARCHAR(100)
SET @vCounter = 1 -- set counter to 1
SET @vBaseIncrement = 128 -- set increment to 128
SET @vClearString = ''
WHILE @vCounter <= LEN(@vEncryptedString) -- while counter is less than or equal to length of string to be decrypted
BEGIN
SET @vClearString = @vClearString +
CHAR(UNICODE(SUBSTRING(@vEncryptedString, @vCounter, 1)) -
@vBaseIncrement - @vCounter + 1)
SET @vCounter = @vCounter + 1
END
-- view the results
select @vClearString AS 'Decrypted String'
-- EXAMPLE OF ENCRYPTION CODE AND DECRYPTION CODE AS FUNCTIONS USING 'WITH ENCRYPTION' THAT WILL HIDE THE ENCRYPTION ALGORITHM FROM ATTACKERS
-- ENCRYPTION
CREATE FUNCTION [dbo].[ufn_EncryptString] ( @pClearString VARCHAR(100) )
RETURNS NVARCHAR(100) WITH ENCRYPTION AS
BEGIN
DECLARE @vEncryptedString NVARCHAR(100)
DECLARE @vIdx INT
DECLARE @vBaseIncrement INT
SET @vIdx = 1
SET @vBaseIncrement = 128
SET @vEncryptedString = ''
WHILE @vIdx <= LEN(@pClearString)
BEGIN
SET @vEncryptedString = @vEncryptedString +
NCHAR(ASCII(SUBSTRING(@pClearString, @vIdx, 1)) +
@vBaseIncrement + @vIdx - 1)
SET @vIdx = @vIdx + 1
END
RETURN @vEncryptedString
END
GO
-- DECRYPTION
CREATE FUNCTION [dbo].[ufn_DecryptString] ( @pEncryptedString NVARCHAR(100) )
RETURNS VARCHAR(100) WITH ENCRYPTION AS
BEGIN
DECLARE @vClearString VARCHAR(100)
DECLARE @vIdx INT
DECLARE @vBaseIncrement INT
SET @vIdx = 1
SET @vBaseIncrement = 128
SET @vClearString = ''
WHILE @vIdx <= LEN(@pEncryptedString)
BEGIN
SET @vClearString = @vClearString +
CHAR(UNICODE(SUBSTRING(@pEncryptedString, @vIdx, 1)) -
@vBaseIncrement - @vIdx + 1)
SET @vIdx = @vIdx + 1
END
RETURN @vClearString
END
GO
/* Illustration of how WITH ENCRYPTION WORKS.
Normally when you create a function, you can view the function definition by right-clicking the function in Object Explorer and
selecting Modify or Script Function As, or you can run the following script:
-- Get the function name, definition, and relevant properties
SELECT sm.object_id,
OBJECT_NAME(sm.object_id) AS object_name,
o.type,
o.type_desc,
sm.definition,
sm.uses_ansi_nulls,
sm.uses_quoted_identifier,
sm.is_schema_bound,
sm.execute_as_principal_id
-- using the two system tables sys.sql_modules and sys.objects
FROM sys.sql_modules AS sm
JOIN sys.objects AS o ON sm.object_id = o.object_id
-- from the function 'dbo.ufnGetProductDealerPrice'
WHERE sm.object_id = OBJECT_ID('dbo.ufnGetProductDealerPrice')
ORDER BY o.type;
GO
However, if you use WITH ENCRYPTION when defining the function, if you right-click and Modify/Script in Object Explorer, you
will get an error saying the text is encrypted. If you use the SQL script method, it'll show up with a NULL value in the
definition column.
*/