I had to update an older database with "clear" passwords to "hashed" and I wanted to do it with sql - this is what I came up with to make the switch fast and easy.
NOTE: Make a backup first!!
Select * into dbo.aspnet_Membership_BACKUP from [dbo].[aspnet_Membership]
Function to calculate the hashes:
/*
Create compatible hashes for the older style ASP.Net Membership
Credit for Base64 encode/decode: http://stackoverflow.com/questions/5082345/base64-encoding-in-sql-server-2005-t-sql
*/
Create Function dbo.AspNetHashCreate (@clearPass nvarchar(64), @encodedSalt nvarchar(64))
Returns nvarchar(128)
as
begin
declare @binSalt varbinary(128)
declare @binPass varbinary(128)
declare @result nvarchar(64)
Select @binPass = CONVERT(VARBINARY(128), @clearPass)
-- Passed salt is Base64 so decode to bin, then we'll combine/append it with password
Select @binSalt = CAST(N'' as XML).value('xs:base64Binary(sql:column("bin"))','VARBINARY(128)')
from (Select @encodedSalt as bin) as temp;
-- Hash the salt + pass, then convert to Base64 for the output
Select @result = CAST(N'' as XML).value('xs:base64Binary(xs:hexBinary(sql:column("bin")))', 'NVARCHAR(64)')
from (Select HASHBYTES('SHA1', @binSalt + @binPass) as bin) as temp2;
-- Debug, check sizes
--Select DATALENGTH(@binSalt), DATALENGTH(@binPass), DATALENGTH(@binSalt + @binPass)
return @result
end
Call it like this:
Update [dbo].[aspnet_Membership] set PasswordFormat = 1, Password = dbo.AspNetHashCreate(password, PasswordSalt) where PasswordFormat = 0
Even with my database originally set to "clear" passwords, the salt values were created with each record, however, if for some reason you don't have salt values you can create them with this:
/*
Create compatible salts for the older style ASP.Net Membership (just a 16 byte random number in Base64)
Note: Can't use newId() inside function so just call it like so: dbo.AspNetSaltCreate(newId())
Credit for Base64 encode: http://stackoverflow.com/questions/5082345/base64-encoding-in-sql-server-2005-t-sql
*/
Create Function dbo.AspNetSaltCreate (@RndId uniqueidentifier)
Returns nvarchar(24)
as
begin
return
(Select CAST(N'' as XML).value('xs:base64Binary(xs:hexBinary(sql:column("bin")))', 'NVARCHAR(64)')
from (select cast(@RndId as varbinary(16)) as bin) as temp)
end
Then use it like this:
Update [dbo].[aspnet_Membership] set PasswordSalt = dbo.AspNetSaltCreate(newId()) where PasswordSalt = ''
Note that you need to generate the Salts FIRST, then the hashes.
Enjoy!