Using Salts in Hashing - sql

Say I have a table like this:
create table [User] (ID int identity not null,EmailAddress varchar(50), [Password] nvarchar(128),primary key (ID))
My reading is telling me that I should add a salt to the table:
alter table [user] add salt nvarchar(128)
If a user creates an account in the application then I believe the SQL should be as follows:
declare #RandomNumber as varchar(32)
set #RandomNumber=rand();
insert into [user] (emailaddress,[password],salt) values ('test#hotmail.co.uk',hashbytes('sha2_256','passwordvalue' + #RandomNumber),#RandomNumber)
Then lets say the user wants to authenticate. The SQL would be like this:
select * from [user] where [password] = hashbytes('sha2_256','passwordvalue' + salt)
The last SQL statement returns nothing, which proves it is incorrect.

Use varchar and not nvarchar, there convertion probleme or declare #RandomNumber as nvarchar(32) like this:
declare #RandomNumber as nvarchar(32)
set #RandomNumber=rand();
insert into [user] (emailaddress,[password],salt) values ('test#hotmail.co.uk',hashbytes('sha2_256','passwordvalue' + #RandomNumber),#RandomNumber)

Related

Cannot return a user table type form a function

I just wrote this coe example to return a user type from a function:
CREATE TYPE dbo.ScheduledActivity_TVP AS TABLE
(
Id uniqueidentifier NOT NULL primary key,
AdditionalDataTypeSignature nvarchar(100) not null,
AdditionalDataId uniqueidentifier NOT NULL,
AdmissionId uniqueidentifier NOT NULL
)
GO
CREATE OR ALTER function [dbo].[Fun_GetFollowUpBymonth](#admissionId uniqueidentifier)
returns ScheduledActivity_TVP as
begin
declare #q ScheduledActivity_TVP
insert into #q
select Id,
AdditionalDataTypeSignature,
AdditionalDataId,
AdmissionId
from ScheduledActivities
where #admissionId = ScheduledActivities.AdmissionId;
return #q
GO
And Sql Server tells me that I must declare the scalar variable #q.
What is wrong in the code above?
I don't see why you are using a multi-line table value function here; they are notoriously slow.
Use an inline table value function, which doesn't even need a TYPE:
CREATE OR ALTER FUNCTION [dbo].[Fun_GetFollowUpBymonth] (#admissionId uniqueidentifier)
RETURNS table
AS RETURN
SELECT Id,
AdditionalDataTypeSignature,
AdditionalDataId,
AdmissionId
FROM dbo.ScheduledActivities
WHERE #admissionId = ScheduledActivities.AdmissionId;

SQL Server - How to insert a hashed password to a table?

Sorry for my ignorance, but I want to store hashed password in my database,
How can use the HASHBYTES method to store hashed password in Users table ?
CREATE TABLE [Users](
EmailAddress NVARCHAR(320) UNIQUE,
UserID INT IDENTITY(1,1) PRIMARY KEY,
UserPassword NVARCHAR(32), -- I Edited the length
FirstName VARCHAR(256) not null,
LastName VARCHAR(256) not null,
MobileNumber BIGINT,
)
--I checked and found this is how to hash a password
declare #afterhash varbinary(256) = HASHBYTES('SHA2_256', 'P#ssw0rd')
But how do I combine them both ?
As mentioned, I don't understand the problem here. Just use HASHBYTES in your parametrised INSERT:
INSERT INTO dbo.Users (EmailAddress, UserPassword, FirstName, LastName, MobileNumber)
VALUES(#EmailAddress, HASHBYTES('SHA2_256',#Password), #FirstName, #LastName, #MobileNumber);
Side Note: As I mentioned in my other answer, bigint isn't the right choice for a telephone number. Phone Numbers can start with a 0 and contain other characters from digits. A value like '01234567890' would be changed to 1234567890, a number like '+441234567890' would be changed to 441234567890, and a number like '(01234) 567890' would fail to INSERT completely
declare #Users table (passwordColumn NVARCHAR(32));
insert #Users values (HASHBYTES('SHA2_256','Password#1234.'));
select HASHBYTES('SHA2_256', passwordColumn) from #Users;

To Find and Eliminate the Duplicates

I use this code to update one of my table by calling a function which generates a random ID each item. I started with around 1000 rows but now the size is growing and i find that there are duplicate ID's in the table. Is there any way to can modify the code i am using, so that it look for ID's that are already generated in the table so that it will generate a new code if there is a similar one. I also noticed
Your code shows you setting the field password, but the results show that UniqueID is the duplicated field. (Maybe it's password renamed?)
Assuming userId is unique: (if not, ADD an actual identity column NOW, "ALTER TABLE dbo.Users ADD ID INT NOT NULL IDENTITY(1, 1)" should do the trick) and assuming password is the field to change, use the following:
DECLARE #FN VARCHAR(20);
DECLARE #LN VARCHAR(20);
DECLARE #PW VARCHAR(20);
DECLARE #ID INT;
SELECT TOP 1
#FN = FirstName,
#LN = LastName,
#ID = userID
FROM dbo.Users
WHERE Password IS NULL;
WHILE ##ROWCOUNT = 1
BEGIN
SET #PW = dbo.GenerateID(FirstName, LastName);
WHILE EXIST (SELECT TOP 1 Password FROM dbo.Users WHERE Password = #PW)
SET #PW = dbo.GenerateID(FirstName, LastName);
UPDATE dbo.Users SET Password = #PW WHERE userId = #ID;
SELECT TOP 1
#FN = FirstName,
#LN = LastName,
#ID = userID
FROM dbo.Users
WHERE Password IS NULL;
END
This should look for a blank password. If none is found the outer loop is skipped. If one is found, we generate passwords until we find one not in the table. Next we look for another row with a blank password before the end of the outer loop.
Sounds like your new to this. Don't worry, TSQL is pretty easy to learn. First thing first, I suggest that you create a unique non-clustered index on the UniqueID column--this will prevent duplicates values from being inserted into your table. If someone does try to insert a duplicate value into the table it will throw an exception. Before you can use this though you'll need to remove all the duplicate 'UniqueID' values from your table.
CREATE UNIQUE NONCLUSTERED INDEX [IDX_UniqueID] ON [dbo].[Users]
(
[UniqueID] ASC
) ON [PRIMARY]
You can learn more about non-clustered indexes here: https://learn.microsoft.com/en-us/sql/relational-databases/indexes/clustered-and-nonclustered-indexes-described
I also suggest that you consider changing the underlying type of your UniqueID field to a 'uniqueidentifier.' Here's an example of a table schema that uses a 'uniqueidentifier' column type for the UniqueID column:
CREATE TABLE [dbo].[Users](
[personId] [int] IDENTITY(1,1) NOT NULL,
[firstName] [nvarchar](50) NOT NULL,
[lastName] [nvarchar](50) NOT NULL,
[UniqueID] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
[personId] ASC
) ON [PRIMARY]
) ON [PRIMARY]
A 'uniqueidentifier' column type in SQL Serever holds a Global Unique Identifier (aka a GUID or UUID). It's easy to generate a GUID in most languages. To generate a GUID in TSQL you just new to invoke the NEWID() function.
SELECT NEWID() -- output: D100FC00-B482-4580-A161-199BE264C1D1
You can learn more about GUIDs here: https://en.wikipedia.org/wiki/Universally_unique_identifier
Hope this helps. Best of luck on your project. :)

Inserting record from one column to another column in the same scope or statement

I have a Stored Procedure that populates a table: This table as indicated in the code below has an identity column which is also the primary key column.
I would like to append the primary key to contain leading letters: Example: ABC123.
Obviously this is not possible because the Primary key column is INT datatype.
So I created an additional column so that I can insert the appended primary key. This works except I have to make the new column Null and I am using an UPDATE statement.
Something tells me there is a better way.
Is there a way I can do this without using UPDATE after the initial Insert and have the new column CategoryID as Not Null?
Table Code:
CREATE TABLE [dbo].[Registration] (
[SystemID] INT IDENTITY (100035891, 1) NOT NULL,
[CategoryID] CHAR (13) NULL,
[FName] VARCHAR (30) NOT NULL,
[LName] VARCHAR (30) NOT NULL,
[MInit] CHAR (1) NULL,
PRIMARY KEY CLUSTERED ([SystemID] ASC)
);
Stored Procedure:
CREATE PROCEDURE [dbo].[uspInsertRegistration]
#FName VARCHAR(30),
#LName VARCHAR(30),
#MInit CHAR(1),
#CategoryID CHAR(13),
#SystemID int OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE #ErrCode int
INSERT INTO [dbo].[Registration] ([FName],[LName],[MInit])
VALUES (#FName, #LName, #MInit)
SELECT #ErrCode = ##ERROR, #SystemID = SCOPE_IDENTITY()
UPDATE [dbo].[Registration]
SET CategoryID = 'ABC'+ CAST(SystemID AS CHAR)
SET NOCOUNT OFF
RETURN #ErrCode
END
Finally this is what the table looks like with the data:
Thanks for being contagious with your knowledge. :)
Guy
My suggestion is to use a computed column, as what you're trying to do introduces redundancy. See below:
http://msdn.microsoft.com/en-us/library/ms191250%28v=sql.105%29.aspx
Alternately, make it big enough to contain a GUID, put a GUID into the column on the insert, then update it afterwards.

SQL INSERT stored procedure not working

Create Proc CrearNuevoAnuncio
#Titulo varchar(250),
#Precio int,
#Descripcion varchar(250),
#IDCategoria int,
#IDImagen int,
#Login varchar(200)
AS
INSERT INTO Anuncio VALUES(
#Titulo,
#Precio,
#Descripcion,
#IDCategoria,
#IDImagen,
#Login
)
The error is because the table anuncio has 1 more attribute: "idAnuncio". It's the primary key, and it's the indentity (autoincrement).
So, how can I handle this is the missing thing is an Identity. I don't want to pass that parameter from my front-end.
You need to specify the explicit list of columns in your insert statement:
INSERT INTO
Anuncio(Titulo, Precio, Descripcion, IDCategoria, IDImagen, Login)
VALUES
(#Titulo, #Precio, #Descripcion, #IDCategoria, #IDImagen, #Login)
Otherwise, SQL Server will try to insert values for ALL columns which fails here. It cannot insert a value into an IDENTITY column - that column will be set automatically by SQL Server upon inserting a new row, and is guaranteed to be unique.
Is the ID field of type "INT IDENTITY" ? In that case, you could access the value of the newly inserted ID like this:
DECLARE #NewID INT
SET #NewID = SCOPE_IDENTITY()
and possibly return it from the stored proc:
RETURN #NewID
Marc
You need to specify which value goes to which field.
INSERT INTO Anuncio (field1, field2, ...) VALUES (#Titulo, ...)