I have this query in sql server 2000:
select pwdencrypt('AAAA')
which outputs an encrypted string of 'AAAA':
0x0100CF465B7B12625EF019E157120D58DD46569AC7BF4118455D12625EF019E157120D58DD46569AC7BF4118455D
How can I convert (decrypt) the output from its origin (which is 'AAAA')?
You shouldn't really be de-encrypting passwords.
You should be encrypting the password entered into your application and comparing against the encrypted password from the database.
Edit - and if this is because the password has been forgotten, then setup a mechanism to create a new password.
The SQL Server password hashing algorithm:
For example, to hash the password "correct horse battery staple". First we generate some random salt:
And then hash the password (encoded in UTF-16) along with the salt:
The value stored in the
syslogins
table is the concatenation of:Which you can see in SQL Server:
0100
9A664D79
6EDB2FA35E3B8FAB4DBA2FFB62F5426B67FE54A3
(SHA-1 is 20 bytes; 160 bits)Validation
You validate a password by performing the same hash:
PasswordHash
: 0x9A664D79and perform the hash again:
which will come out to the same hash, and you know the password is correct.
What once was good, but now is weak
The hashing algorithm introduced with SQL Server 7, in 1999, was good for 1999.
But today it is out-dated. It only runs the hash once, where it should run it a few thousand times, in order to thwart brute-force attacks.
In fact, Microsoft's Baseline Security Analyzer will, as part of it's checks, attempt to bruteforce passwords. If it guesses any, it reports the passwords as weak. And it does get some.
Brute Forcing
To help you test some passwords:
SQL Server 2012 and SHA-512
Starting with SQL Server 2012, Microsoft switched to using SHA-2 512-bit:
Changing the version prefix to
0x0200
:0200
(SHA-2 256-bit)6A80BA22
9556EB280AA7818FAF63A0DA8D6B7B120C6760F0EB0CB5BB320A961B04BD0836 0C0E8CC4C326220501147D6A9ABD2A006B33DEC99FCF1A822393FC66226B7D38
This means we hash the UTF-16 encoded password, with the salt suffix:
6A80BA22
)63006f0072007200650063007400200068006f0072007300650020006200610074007400650072007900200073007400610070006c006500
+6A80BA22
)9556EB280AA7818FAF63A0DA8D6B7B120C6760F0EB0CB5BB320A961B04BD0836 0C0E8CC4C326220501147D6A9ABD2A006B33DEC99FCF1A822393FC66226B7D38
You realise that you may be making a rod for your own back for the future. The pwdencrypt() and pwdcompare() are undocumented functions and may not behave the same in future versions of SQL Server.
Why not hash the password using a predictable algorithm such as SHA-2 or better before hitting the DB?
You cannot decrypt this password again but there is another method named "pwdcompare". Here is a example how to use it with SQL syntax:
A quick google indicates that pwdencrypt() is not deterministic, and your statement select pwdencrypt('AAAA') returns a different value on my installation!
See also this article http://www.theregister.co.uk/2002/07/08/cracking_ms_sql_server_passwords/
I believe pwdencrypt is using a hash so you cannot really reverse the hashed string - the algorithm is designed so it's impossible.
If you are verifying the password that a user entered the usual technique is to hash it and then compare it to the hashed version in the database.
This is how you could verify a usered entered table
Replace userEnteredValue with (big surprise) the value that the user entered :)