Replicating PHP’s sha1() in VBScript
The reason I wanted to do this will become obvious at a later date, but for now I wanted to get this little script up on its own because I wasn’t able to find a complete solution when I went looking for it.
The following code replicates the basic functionality of the sha1() function in PHP:
Option Explicit Dim asc, enc, bytes, instr, outstr, pos instr = "test string" 'Borrow some objects from .NET (supported from 1.1 onwards) Set asc = CreateObject("System.Text.UTF8Encoding") Set enc = CreateObject("System.Security.Cryptography.SHA1CryptoServiceProvider") 'Convert the string to a byte array and hash it bytes = asc.GetBytes_4(instr) bytes = enc.ComputeHash_2((bytes)) outstr = "" 'Convert the byte array to a hex string For pos = 1 To Lenb(bytes) outstr = outstr & LCase(Right("0" & Hex(Ascb(Midb(bytes, pos, 1))), 2)) Next WScript.Echo outstr
As you can see from the comments, this essentially cheats by borrowing some COM objects from .NET to do the hard work. These classes are available from .NET 1.0 onwards, so should run on Windows Server 2003 SP2 and later out of the box. I’m not 100% sure about a Server Core install of 2008, but it worked on a Server Core install of 2008 R2.
If you want the raw output instead of the hex string, simply output the bytes variable and omit lines 15-20.
Caveat: This code works for UTF-8 strings. I haven’t tested PHPs sha1() function with Unicode, but in theory you should only have to substitute UTF8Encoding for UnicodeEncoding on line 8.
Bonus: You can replicate the md5() function with the same code, but substitute SHA1CryptoServiceProvider for MD5CryptoServiceProvider on line 9. Unfortunately, the same trick doesn’t work for the newer hash algorithms in .NET such as SHA256 or SHA512.
10 responses to “Replicating PHP’s sha1() in VBScript”
Trackbacks / Pingbacks
- 15th March, 2011 -
Leveraging .NET assemblies in this manner is a cool trick. I wish .NET had been around a few years ago when I had to write an MD5 function in VBScript!
I was certainly very happy the script turned out to be that simple. It’s a neat trick that is almost completely undocumented, and only a subset of .NET objects can be used in this way. Here’s a quick summary of the most useful pages I found while researching this:
…it is also possible to use the .NET library voor de SHA512. In this case use:
“System.Security.Cryptography.SHA512Managed” …
I found this by checking the .NET platform support for the different libraries via MSDN
“enc.ComputeHash_2((bytes))” requires double parentheses – why?
This method in .NET is equivalent to sha1 in php:
string sha1Hash(string password)
{
return string.Join(“”, SHA1CryptoServiceProvider.Create().ComputeHash(Encoding.UTF8.GetBytes(password)).Select(x => x.ToString(“X2”))).ToLower();
}
thanks technician!!! you have saved my day!!!
Hi Technician
I note from your code that you don’t explicitly kill of the objects you create, would this be an issue?
set asc = nothing
set enc = nothing
Cheers
Graham
I’m fairly sure that modern VBScript engines will dispose of an object automatically when it goes out of scope. It might be an issue if this was part of a much larger script, but my scripts are typically fewer than 50 lines long, so it’s never really an issue for me.
Ok many thanks for that. I have used this in a project I design for constantly and so have adapted a class object for it, hope you don’t mind.
I have included it to share with your followers:
class cls_Encrypt
private enc
private asc
private string_to_encode
private encoded_string
private hash_Method
Private Sub Class_Initialize()
‘Borrow some objects from .NET (supported from 1.1 onwards)
Set asc = Server.CreateObject(“System.Text.UTF8Encoding”)
string_to_encode = “my string”
hash_Method = “sha1”
End Sub
‘ Kills all objects created in the class
Private Sub Class_Terminate()
set asc = nothing
set enc = nothing
End Sub
public property Let inputString(s)
string_to_encode = s
end property
public property Let hashMethod(s)
select case s
case “sha1″,”md5”
hash_Method = s
case else
hash_Method = “sha1”
end select
end property
public property get hashedString()
hashedString = encoded_string
end property
public property get hashMethod()
hashMethod = hash_Method
end property
public function hash()
select case hash_Method
case “sha1”
gen_sha1 string_to_encode
case “md5”
gen_md5 string_to_encode
end select
hash = encoded_string
end function
private sub gen_SHA1(s)
Dim bytes, outstr, pos
Set enc = Server.CreateObject(“System.Security.Cryptography.SHA1CryptoServiceProvider”)
‘Convert the string to a byte array and hash it
bytes = asc.GetBytes_4(s)
bytes = enc.ComputeHash_2((bytes))
outstr = “”
‘Convert the byte array to a hex string
For pos = 1 To Lenb(bytes)
outstr = outstr & LCase(Right(“0” & Hex(Ascb(Midb(bytes, pos, 1))), 2))
Next
encoded_string = outstr
end sub
private sub gen_MD5(s)
Dim bytes, outstr, pos
Set enc = Server.CreateObject(“System.Security.Cryptography.MD5CryptoServiceProvider”)
‘Convert the string to a byte array and hash it
bytes = asc.GetBytes_4(s)
bytes = enc.ComputeHash_2((bytes))
outstr = “”
‘Convert the byte array to a hex string
For pos = 1 To Lenb(bytes)
outstr = outstr & LCase(Right(“0” & Hex(Ascb(Midb(bytes, pos, 1))), 2))
Next
encoded_string = outstr
end sub
end class
Many thanks
Graham