How to hash a UTF-8 string in Classic ASP

2020-03-30 03:55发布

问题:

I've been looking for a Classic ASP script that allows me to hash a string using the MD5 algorithm. I need to match this hashed string against the same string in an ASP.NET Page, hashed using .NET's MD5 hashing algorithms.

Even though I have found several scripts for Classic ASP that generate the hash, I haven't found one that generates the correct hash using non-English characters (like ñ, for example).

Do you know some Classic ASP script that works in this particular case?

Note:

I have tried these scripts:

http://userpages.umbc.edu/~mabzug1/cs/md5/md5.asp

http://forums.aspfree.com/code-bank-54/asp-classic-md5-hash-82164.html

Examples:

String:

muñeca

Correct MD5 Hash:

ea07bec1f37f4b56ebe368355d1c058f

Generated Hash:

298e60cb1179df15d5772726a3975132

回答1:

The first part of hashing any string is getting a byte array of the string's characters. The byte array created depends on the encoding type used for the string. .Net strings are encoded in UTF-16. I don't recall vbscript's encoding type off the type of my head, but it's probably just ascii or at best UTF-8.

Therefore, to fix your problem, the first thing you need to do is get vbscript to give you a byte array that represents the UTF-16 characters in your string. Then go look for an md5 hash function that expects a byte array directly, instead of a string type.

Unfortunately, even this may not be enough. It's possible that vbscript's lack of native UTF-16 could result in what is normally a minor loss of fidelity in the string input from the user, such that the string in your Classic ASP code is no longer exactly the same characters as the string in your ASP.Net code. If this is the case, the only solution is to change your ASP.Net code to match the Classic ASP encoding, rather than vice versa. This may be the much easier solution anyway. For this to work, you will need to know exactly what character encoding your vbscript code is using. Again, I don't have that information in my head anymore, so you can google it as well as I.



回答2:

The hash computation itself is not your problem. You're using UTF-8 in .net, and ANSI/Latin1 in asp classic.

A hash algorithm operates on a sequence of bytes, not on a string. Thus you first need to convert the string to a sequence of bytes first, a process called encoding. Common choices are ANSI(The locale dependent legacy encoding on windows), UTF-8 and UTF-16 LE.

First choose an encoding, and use that consistently on both platforms. I recommend UTF-8, which on .net is accessed via Encoding.UTF.GetBytes(). You'll need to search for UTF-8+asp classic to figure out how to use from there. Since UTF-8 encoding is a common problem, I'm sure you'll find something.

I suspect your asp classic code uses ANSI, but I strongly recommend not using it, since it only supports a small subset of possible characters, and is locale dependent.



回答3:

If you are using UTF-8 on both .Net and Classic ASP you should be able to borrow the .Net implementation.

Something like this;

<%
Dim asc, enc, bytes, instr, outstr, pos

instr = "muñeca"

Set asc = CreateObject("System.Text.UTF8Encoding")
Set enc = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider")

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

Response.Write outstr
%>

Output:

ea07bec1f37f4b56ebe368355d1c058f

This is the only valid method I've found for Classic ASP because all other implementations assume ANSI encoding and you end up with an incorrect hash.

Credit to: Replicating PHP’s sha1() in VBScript for helping me finally find a solution.



回答4:

You could wrap the .NET MD5 hashing code in a COM-visible assembly. Then you can deploy and use the same exact MD5 hashing code on your ASP.NET and classic ASP sites.



回答5:

With this function you can hash the plain text into:
SHA1, SHA256, SHA384, SHA512, MD5, RIPEMD160
If you need more you can find it in: System.Security.Cryptography Namespace

Function Hash(HashType, PlainText)
    On Error Resume Next

    With CreateObject("ADODB.Stream")
        .Open
        .CharSet = "Windows-1252"
        .WriteText PlainText
        .Position = 0
        .CharSet = "UTF-8"
        PlainText = .ReadText
        .Close
    End With

    Set UTF8Encoding = CreateObject("System.Text.UTF8Encoding")
    Dim PlainTextToBytes, BytesToHashedBytes, HashedBytesToHex

    PlainTextToBytes = UTF8Encoding.GetBytes_4(PlainText)

    Select Case HashType
        Case "sha1": Set Cryptography = CreateObject("System.Security.Cryptography.SHA1Managed")
        Case "sha256": Set Cryptography = CreateObject("System.Security.Cryptography.SHA256Managed")
        Case "sha384": Set Cryptography = CreateObject("System.Security.Cryptography.SHA384Managed")
        Case "sha512": Set Cryptography = CreateObject("System.Security.Cryptography.SHA512Managed")
        Case "md5": Set Cryptography = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider")
        Case "ripemd160": Set Cryptography = CreateObject("System.Security.Cryptography.RIPEMD160Managed")
    End Select

    Cryptography.Initialize()
    BytesToHashedBytes = Cryptography.ComputeHash_2((PlainTextToBytes))

    For x = 1 To LenB(BytesToHashedBytes)
        HashedBytesToHex = HashedBytesToHex & Right("0" & Hex(AscB(MidB(BytesToHashedBytes, x, 1))), 2)
    Next

    Hash = LCase(HashedBytesToHex)

    If Err.Number <> 0 Then Response.Write(Err.Description)

    On Error GoTo 0
End Function

These can be used as follows:

Hash("sha512", "Hello World")

Produces:
2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b

Hash("sha256", "Hello World")

Produces:
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e

Hash("md5", "muñeca")

Produces:
ea07bec1f37f4b56ebe368355d1c058f



回答6:

If you want exactly what .Net does , You can decompile ComputeHash method from HashAlgorithm class(also consider MD5CryptoServiceProvider class) from .Net assembly mscorlib.dll (from the path like this in your computer :C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\mscorlib.dll) and then convert the codes to ASP-Classic. Some good (free)Decompilers are:

1- http://www.reflector.net/

2- http://www.telerik.com/products/decompiler.aspx