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.

Tags: , ,

About The Angry Technician

The Angry Technician is an experienced IT professional in the UK education sector. Normally found in various states of annoyance on his blog. All views are those of his imaginary pet dog, Howard.

10 responses to “Replicating PHP’s sha1() in VBScript”

  1. Kevin Ferguson says :

    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!

  2. Dirk Kuiperbak says :

    …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

  3. Inspired says :

    “enc.ComputeHash_2((bytes))” requires double parentheses – why?

  4. Omar Elsherif says :

    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();
    }

  5. rlunaro says :

    thanks technician!!! you have saved my day!!!

  6. Graham says :

    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

    • The Angry Technician says :

      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.

      • Graham says :

        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