views:

493

answers:

2

My problem is a bit hairy, and I may be asking the wrong questions, so please bear with me...

I have a legacy MySQL database which stores the user passwords & salts for a membership system. Both of these values have been hashed using the Ruby framework - roughly like this:

hashedsalt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--")

hashedpassword = Digest::SHA1.hexdigest("#{hashedsalt}:#{password}")

So both values are stored as 40-character strings (varchar(40)) in MySQL.

Now I need to import all of these users into the ASP.NET membership framework for a new web site, which uses a SQL Server database. It is my understanding that the the way I have ASP.NET membership configured, the user passwords and salts are also stored in the membership database (in table aspnet_Membership) as SHA1 hashes, which are then Base64 encoded (see here for details) and stored as nvarchar(128) data.

But from the length of the Base64 encoded strings that are stored (28 characters) it seems that the SHA1 hashes that ASP.NET membership generates are only 20 characters long, rather than 40. From some other reading I have been doing I am thinking this has to do with the number of bits per character/character set/encoding or something related.

So is there some way to convert the 40-character SHA1 hashes to 20-character hashes which I can then transfer to the new ASP.NET membership data table? I'm pretty familiar with ASP.NET membership by now but I feel like I'm just missing this one piece. However, it may also be known that SHA1 in Ruby and SHA1 in .NET are incompatible, so I'm fighting a losing battle...

Thanks in advance for any insight.

A: 

Ruby uses SHA2, and ASP.NET uses SHA1, and no, you can't 'convert' between those versions. For that you'd need to recalculate the hashes from the plaintext.

Edit: SHA is standarlized, so you can search in the internet for a SHA2 library to use in ASP.NET.

MeDiCS
.net has a SHA1 class: http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha1.aspx
Taylor Leese
+1  A: 

The varchar representation in your Ruby app appears to be 'hex as string', something like this: 01AB02EF...23EF. that is, each byte is represented as a pair of characters that are the hex value of the byte, from 00 to FF. Therefore the SHA hash (20 bytes) is represented as 40 characters. IF the hash is the values (0, 1, 2, ...) the string will be 000102. The ASP base64 is the base64 encoding of the actual bytes. So all you need to do is take the MySQL characters and obtain the corresponding bytes, then encode them as base64.

You can actually do the transformation in SQL itself:

declare @x varchar(40);
set @x = '000102030405060708090A0B0C0D0E0F10111213';

declare @sql nvarchar(max);
set @sql = N'set @out=0x' + @x;

declare @out varbinary(20);
exec sp_executesql @sql, N'@out varbinary(20) output', @out output;
select @out for xml path('');

But to coerce your ASP.Net membership provider to use the salted hash your Ruby code created, irrelevant of the encoding used to store the hash digest, that's a whole different topic. You'll likely have to rewrite your own membership provider, at which point the storage encoding becomes irrelevant, since you can store them as you wish.

Remus Rusanu
Very interesting, I'm going to try this tomorrow. Thank you so much.
ewitch