how to encode int with base32 in sql server 2008 - sql-server

i am looking to encode an INT to BASE32 string in SQL Server 2008.
Any suggestions of built-in function or perhaps a custom function?
Thanks

Pretty sure this will need some debugging but should be close. I translated from a c# function I found that converts base10 to base32.
CREATE FUNCTION dbo.Base10toBase32 (#pInput int)
RETURNS varchar(100)
AS
BEGIN
Declare #pSet char(32)
Declare #pRslt varchar(100)
Declare #pRmdr int
Declare #pPos int
SET #pSet = '0123456789ABCDEFGHIJKLMNOPQRSTUV'
SET #pPos = #pInput
WHILE #pPos > 0
BEGIN
SET #pRmdr = #pPos % 32
SET #pPos = #pPos / 32
SET #pRslt = SubString(#pSet,#pRmdr+1,1) + #pRslt
END
RETURN #pRslt
END

If you're looking for human-readable base32, check out Crockford's: http://www.crockford.com/wrmg/base32.html
Looks like a Dell service tag -- avoids confusion between 1 0 I L etc...

Here are a few implementations:
http://dpatrickcaldwell.blogspot.com/2009/05/converting-decimal-to-hexadecimal-with.html
http://snippets.dzone.com/posts/show/707
http://geekswithblogs.net/bbiales/archive/2009/05/04/131732.aspx

Related

SignByCert returning signature of length 264 for 2048 bit keys

We have recently migrated to SQL Server 2017 (64 bit - version: 14.0.1000.169 - Host OS: Windows Server 2016 Datacenter). I created the test certificate in database and used it to sign sample text. The SQL method SignByCert returned signature of length 264 bytes.
Ideally I expect the signature size should be length of mod length which is 2048 bits (256 bytes) in my case. I am wondering why the SignByCert returned signature of length 264.
Below is sample code.....
Create certificate MyTestCertificate
with Subject='MyTestCertificate',
EXPIRY_DATE = '20231010' ;
DECLARE #ClearText as varchar(8000);
DECLARE #Signature as varbinary(max);
DECLARE #Signature_len as int;
DECLARE #RESULT as int;
SET #ClearText = 'This is some clear text to encrypt';
SET #Signature = SignByCert(Cert_ID('MyTestCertificate'), #ClearText);
SET #Signature_len = datalength(#Signature) ;
SET #RESULT = VerifySignedByCert(Cert_ID('MyTestCertificate'), #ClearText, #Signature);
select #Signature_len, #RESULT

Replace Unicode apostrophe in SQL Server

I am trying to replace Modified Letter Apostrophes - nchar(700) with an empty character for a legacy system that cannot handle uniocde, but my replace is not working.
I am doing this in SQL Server Express 2019.
I have been using a function to do the replaces, but to make sure it wasn't just the function (which is working for other replaces of unicode characters), I used the following code fragment:
print replace('canʼt',nchar(700),'X')
and the result I am getting is: can't (which interestingly enough is the ASCII ' not the Unicode Modified Letter Apostrophe).
I have confirmed that the string has the modified apostrophe looking at the string in a hex editor feature of Notepad++ (the value is CA BC).
Any ideas why this isn't working in SQL?
Thanks,
David
WORKAROUND:
I got the replace to work with the following code, but this is not very "pretty":
DECLARE #ReplaceString nvarchar(100)
DECLARE #position INT, #nstring NCHAR(12);
SET #ReplaceString = N'canʼt'
SET #position = 1;
WHILE #position <= LEN(#Replacestring)
BEGIN
IF UNICODE(SUBSTRING(#ReplaceString,#position,1)) = 700
IF #position < len(#ReplaceString)
SET #ReplaceString = SUBSTRING(#ReplaceString,1,#position - 1) +
SUBSTRING(#ReplaceString,#position + 1,len(#ReplaceString))
ELSE
SET #ReplaceString = SUBSTRING(#ReplaceString,1,#position - 1)
SET #position = #position + 1;
END

How do i format a sql numeric type with commas on Sybase SQLAnywhere?

I came across the following solution but it does not work on Sybase
SELECT CONVERT(varchar, CAST(987654321 AS money), 1)
I have read the Convert Sybase information but still i receive the same number without the commas.
Have you tried giving a varchar (20) for example instead ? something like :
SELECT CONVERT(varchar(20), CAST(987654321 AS money), 1)
In SqlAnywhere money datatype is a domain, implemented as NUMERIC(19,4).
in CAST function , If you do not indicate a length for character string types, the database server chooses an appropriate length. If neither precision nor scale is specified for a DECIMAL conversion, the database server selects appropriate values.
So maybe this is what's causing the issue, what do you get as output ? do you get 987654321.00 , or just 987654321 ?
Update:
My last suggestion would be using insertstr() function and loop through the char value of your number to insert comma every 3 digits .. this is not the cleanest/easiest way but apparently SQLAnywhere deal with money datatype as normal NUMERIC datatype ...
insertstr() documentation is here.
I would give you a code sample but I don't have SQLAnywhere installed to test it ...
Here is the SP i created based on F Karam suggestion.
CREATE FUNCTION "DBA"."formattednumber"( in #number numeric)
returns char(60)
begin
declare #returnnumber char(60);
declare #workingnumber char(60);
declare #n_ind char(1);
declare #decimalnumber char(10);
declare #tempnumber char(60);
declare #decimalpos integer;
if isnull(#number,'') = '' then
return null
end if;
if #number < 0 then set #n_ind = 'Y'
else set #n_ind = 'N'
end if;
set #workingnumber = convert(char(60),ABS(#number));
set #decimalpos = patindex('%.%',#workingnumber);
if #decimalpos > 0 then
set #decimalnumber = substr(#workingnumber,#decimalpos);
set #decimalnumber = "left"(#decimalnumber,3+1);
set #workingnumber = "left"(#workingnumber,#decimalpos-1)
end if end if;
set #returnnumber = '';
while length(#workingnumber) > 3 loop
set #tempnumber = "right"(#workingnumber,3);
set #returnnumber = insertstr(0,#returnnumber,#tempnumber);
set #workingnumber = "left"(#workingnumber,length(#workingnumber)-3);
if length(#workingnumber) > 0 then
set #returnnumber = insertstr(0,#returnnumber,',')
end if
end loop;
if length(#workingnumber) > 0 then
set #returnnumber = insertstr(0,#returnnumber,#workingnumber)
end if;
if length(#decimalnumber) > 0 then
set #returnnumber = #returnnumber+#decimalnumber
end if;
if #n_ind = 'Y' then set #returnnumber = '-' || #returnnumber
end if;
return(#returnnumber)
end;
You need to distinguish between server-side and client-side formatting. When you use the 'isql' client for example (the TDS client), then the result will be this:
1> select convert(money, 9876543210)
2> go
9876543210
------------------------
9,876,543,210.00
(1 row affected)
But this is purely because the client application happens to format 'money' values this way. Also, this is actually not specific for SQLA, since isql is originally the client tool for ASE (a different Sybase database).
When you run the same conversion at the SQLA server (i.e. as part of an expression in a SQL statement), those commas will not be there since SQLA doesn't have such a built-in formatting style.
If you want this, you should write a SQL function that formats the number as you desire.

how to encrypt the password column

I have user table in SQL Server 2008 r2. Nothing there is encrypted yet but I would like to at the least encrypt the passwords until the app is ready that will handle this better. Can i do this and how? to manually make the passwords encrypted.
You can encrypt columns using SQL Server, ( see: http://msdn.microsoft.com/en-us/library/ms179331.aspx for a walk-through).
You can also use a key given out from the server itself.
The risk of using this is if you had to do data recovery and move the DB to a different server it would be impossible to decrypt the column (reset passwords would be required).
Note: password hashing is not meant for 2-way encryption (where a rogue dba can decrypt it). It is meant for hashing it in a way that allows validation without trivially showing the password to anyone. A low or even moderate level of collisions is in some ways desirable so that it allows the password through (and unfortunately other variants) but with collisions you can never tell what the real password actually was.
A simple implementation would be to run HashBytes over the password. You compare the (hash of) password provided to the hash stored. Unless someone has a rainbow table ready, they will not be able to find the original password.
INSERT INTO <tbl> (..., passwd) values (...., HashBytes('SHA1', #password))
When validating passwords, you take the hash of the password
SELECT HashBytes('SHA1', #password);
And compare it against the input.
You actually don't want to encrypt it, but rather use a hash function on it. Unless there is an strong requirement to gain access to the unencrypted password.
We can Create some simple sql function to encrypt and decrypt the Password column in your web page:
Code:Encryption
`CREATE FUNCTION [dbo].[ENCRYPT]
(
#DB_ROLE_PASSWORD VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE
#STR_LEN NUMERIC(10),
#ENCRYPTED_PASSWORD VARCHAR(100),
#TRIAL_CHARACTER VARCHAR(1),
#TRIAL_NUMBER NUMERIC(4)
SET #ENCRYPTED_PASSWORD = NULL
SET #STR_LEN =LEN(#DB_ROLE_PASSWORD)
DECLARE
#I INT
SET #I = 1
DECLARE
#LOOP$BOUND INT
SET #LOOP$BOUND = #STR_LEN
WHILE #I <= #LOOP$BOUND
BEGIN
/* * SSMA WARNING MESSAGES: * O2SS0273: ORACLE SUBSTR FUNCTION AND SQL SERVER SUBSTRING FUNCTION MAY GIVE DIFFERENT RESULTS. */
SET #TRIAL_CHARACTER = SUBSTRING(#DB_ROLE_PASSWORD, #I, 1)
SET #TRIAL_NUMBER = ASCII(#TRIAL_CHARACTER)
IF (#TRIAL_NUMBER % 2) = 0
SET #TRIAL_NUMBER = #TRIAL_NUMBER - 6
ELSE
SET #TRIAL_NUMBER = #TRIAL_NUMBER - 8
SET #TRIAL_CHARACTER = CHAR(CAST(#TRIAL_NUMBER + #I AS INT))
SET #ENCRYPTED_PASSWORD = ISNULL(#ENCRYPTED_PASSWORD, '') + ISNULL(#TRIAL_CHARACTER, '')
SET #I = #I + 1
END
RETURN #ENCRYPTED_PASSWORD
END`
Code:Decryption
`CREATE FUNCTION [dbo].[DECRYPT]
(
#DB_ROLE_PASSWORD VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE
#STR_LEN NUMERIC(10),
#DECRYPTED_PASSWORD VARCHAR(100),
#TRIAL_CHARACTER VARCHAR(1),
#TRIAL_NUMBER NUMERIC(4),
#CHECK_CHARACTER VARCHAR(1),
#V_DB_ROLE_PASSWORD VARCHAR(100)
SET #V_DB_ROLE_PASSWORD = #DB_ROLE_PASSWORD
SET #DECRYPTED_PASSWORD = NULL
SET #STR_LEN = LEN(#V_DB_ROLE_PASSWORD)
DECLARE
#I INT
SET #I = 1
DECLARE
#LOOP$BOUND INT
SET #LOOP$BOUND = #STR_LEN
WHILE #I <= #LOOP$BOUND
BEGIN
/*
* SSMA WARNING MESSAGES:
* O2SS0273: ORACLE SUBSTR FUNCTION AND SQL SERVER SUBSTRING FUNCTION MAY GIVE DIFFERENT RESULTS.
*/
SET #TRIAL_CHARACTER = SUBSTRING(#V_DB_ROLE_PASSWORD, #I, 1)
SET #TRIAL_NUMBER = ASCII(#TRIAL_CHARACTER) - #I
IF (#TRIAL_NUMBER % 2) = 0
SET #TRIAL_NUMBER = #TRIAL_NUMBER + 6
/*-IE EVEN*/
ELSE
SET #TRIAL_NUMBER = #TRIAL_NUMBER + 8
/*-IE ODD*/
SET #DECRYPTED_PASSWORD = ISNULL(#DECRYPTED_PASSWORD,'') + ISNULL(CHAR(CAST(#TRIAL_NUMBER AS INT)), '')
SET #I = #I + 1
END
RETURN #DECRYPTED_PASSWORD
END`
Encryption & Decryption examples can be found here:
http://msdn.microsoft.com/en-us/library/ms179331.aspx
Hashing example can be found here:
http://msdn.microsoft.com/en-us/library/ms174415.aspx
You should not encrypt passwords if your only task is to verify that the password the user entered is correct. You should hash them instead. You could use any algorithm to hash them, but I recommend using MD5 because it is very secure.1 :)
for example:
public string EncodePassword(string originalPassword)
{
//Declarations
Byte[] originalBytes;
Byte[] encodedBytes;
MD5 md5;
//Instantiate MD5CryptoServiceProvider, get bytes for original password and compute hash (encoded password)
md5 = new MD5CryptoServiceProvider();
originalBytes = ASCIIEncoding.Default.GetBytes(originalPassword);
encodedBytes = md5.ComputeHash(originalBytes);
//Convert encoded bytes back to a 'readable' string
return BitConverter.ToString(encodedBytes);
}
1 Edit (not original answer author): MD5 for passwords is considered insecure and more robust algorithms should be used. You should do research into the contemporary algorithms at the point of reading this. This post might be a good starting point.

stored procedure returns varchar in LINQ

I would like to know if in SQL is it possible to return a varchar value from a stored procedure, most of the examples I have seen the return value is an int
Example within a proc
declare #ErrorMessage varchar(255) if #TestFlag = 0 set #ErrorMessage = 'Test'
return #ErrorMessage
calling on asp.net
Updated:
Error:
Conversion failed when converting the varchar value 'Development' to data type int.
using (DataContextDataContext dc = conn.GetContext())
{
string serverName = ""
var result = dc.spGetServerName(ref serverName);
return result.ToString();
}
No, you can't return anything but an int using the RETURN statement.
You'd need to use OUTPUT parameters instead. They are more flexible.
e.g.
CREATE PROCEDURE dbo.ExampleSproc
#OutParam VARCHAR(10) OUTPUT
AS
SET #OutParam = 'Test'
...
GO
Update:
For an example on how to retrieve the output param, see this article.
No. Please see: http://msdn.microsoft.com/en-us/library/ms174998.aspx

Resources