Dealing with a varbinary field in VB.NET

14,698

Your issue is likely that the string->binary conversions are using different encodings. Try using System.Text.Encoding.ASCII instead of Unicode and see if that does the trick for you. My guess is that convert() is considering your string to be a varchar instead of an nvarchar and is using ASCII instead of Unicode for its own string->binary conversion.

Edit

Also, is this string an actual binary equivalent to the hash, or is it a hexadecimal representation?

Edit 2

Then your issue is that you're passing the binary representation of the hexadecimal representation of your binary data. That confusing enough?

You just need to convert the hex string to a byte array before you add it as a value for your parameter. You can do that with the following code, taken from the answer to this question (and translated to VB.NET):

Public Shared Function StringToByteArray(ByVal hex As String) As Byte()
    Dim NumberChars As Integer = hex.Length

    Dim bytes(NumberChars / 2) As Byte

    For i As Integer = 0 To NumberChars - 1 Step 2
        bytes(i / 2) = Convert.ToByte(hex.Substring(i, 2), 16)
    Next

    Return bytes
End Function

So your code will look something like this...

byteArrayToken = StringToByteArray(stringToken)
scSelectThing.CommandText = "select thing from tokenstable where token=@token"
Dim param As SqlParameter = scSelectThing.Parameters.Add("@token", SqlDbType.VarBinary)
param.Value = byteArrayToken
lbOutput2.Text = scSelectThing.ExecuteScalar()
Share:
14,698
Kyle
Author by

Kyle

I started out as a Systems Administrator working with Solaris, Windows NT, Linux and xBSD systems in the late 90′s. I quickly realized that my best days involved software developers asking for something – figuring out how to build a web cluster was much more interesting than fixing printers and blackberries. This got me more interested in what we’d call Operations or DevOps today. My natural leadership abilities led me to director roles early on. In the last ten years of my career I’ve been the CTO of three innovative organizations, and I’ve learned a lot from the each of them. I also fell in love with developing software. Over the last six years, I’ve built large scale web applications in .NET, and learned several other languages including JavaScript, Java, Ruby, Scala, PHP, Perl and Python along the way. Author of ServiceStack 4 Cookbook ThoughtWorks Principal Consultant and Software Developer Microsoft MVP for ASP.NET and IIS Blogger and Technical Author Toronto Technology Community Member More Information GitHub Twitter My CV LinkedIn StackExchange Profile

Updated on June 04, 2022

Comments

  • Kyle
    Kyle almost 2 years

    A partner of ours is making a call to a web service that includes a parameter called token. Token is the result of an MD5 hash of two numbers, and helps us authenticate that the user using our partners system. Our partner asks the user for two strings, concatenates them, runs them through MD5, and then calls our web service. The result of the MD5 is the token, and it is submitted to us as a string.

    We store valid tokens in a DB - since we use the SQL Server to compute the tokens on our end, SQL seemed to be happiest storing the tokens as a varbinary, which is its native result for an MD5 computation.

    We have two pieces of code that attempt to do the same thing - run a select query that pulls out a value based on the token submitted. One uses a dynamic query (which is a problem), but it works. The other one attempts to do the same thing in a parameterized (safer) fashion, it does not work - it is unable to locate the token.

    Here's the two competing attempts. First, the parameterized version which fails:

    byteArrayToken = System.Text.UnicodeEncoding.Unicode.GetBytes(stringToken)
    scSelectThing.CommandText = "select thing from tokenstable where token=@token"
    Dim param As SqlParameter = scSelectThing.Parameters.Add("@token", SqlDbType.VarBinary)
    param.Value = byteArrayToken
    lbOutput2.Text = scSelectThing.ExecuteScalar()
    

    And secondly, the dynamic query string version which works:

    Dim scSelectThing As New SqlCommand
     scSelectThing.CommandText = "select thing from tokenstable where token=convert(varbinary, " + stringToken + " )"
    lbOutput2.Text = scSelectThing.ExecuteScalar()
    

    When we run the SQL profiler, this is what is actually being executed against the DB:

    exec sp_executesql N'select thing from tokenstable where token=@token',N'@token varbinary(68)',@token=0x3000780046003800380034004100450036003400430038003300440033004100380034003800460046004300380038004200390034003400330043004200370042004600
    

    This doesn't look right to me, it looks as though we're doing something that leads something in the stack to do the wrong conversion somewhere.

    Any ideas what that would be? Its obviously not acceptable to launch with a dynamic query in there.

    Edit:

    The string is an MD5 hash result. To make it work in Query Analyzer we do this:

    select * from tokenstable where 
    token=convert(varbinary, 0xF664AE32C83D3A848FFC88B9443CB7BF )
    

    Note the lack of quotes, if we quote it the query fails. The field that we are comparing to is a varbinary, where SQL Server has stored the results of the MD5 computations on our end.