11

I'm converting some code from C# to VB.NET. I have the following line in C#

var bytes = new byte[password.Length * sizeof(char)];

Looking on MSDN it appears that VB.NET does not seem to have the sizeof operator. I understand there is a Marshal.SizeOf but further MSDN documentation states that the value returned can be different to that of sizeof.

Can anybody help? Is there an equivalent statement in VB.NET?

Additional Information

My aim is to convert a password into an array of bytes which I can then hash and then either store in a database or compare to a previously stored hash. But I don't necessarily want an answer relating to my particular situation.

Dim bytes(password.Length * xxx) As Byte
System.Buffer.BlockCopy(password.ToCharArray(), 0, bytes, 0, bytes.Length)
Dim sha512 = System.Security.Cryptography.SHA512.Create()
Dim hash = sha512.ComputeHash(bytes)

' compare hash or stroe in database
Kevin Brydon
  • 10,374
  • 6
  • 32
  • 66
  • IIRC, `sizeof(char)` is a compile-time constant and equals 2 (bytes). – stakx - no longer contributing Oct 16 '14 at 14:51
  • What is the purpose of creating the `bytes` array? – Michael Liu Oct 16 '14 at 14:51
  • Possibly related: [Converting a string to byte array](http://stackoverflow.com/questions/472906/converting-a-string-to-byte-array). Make sure you see [this answer](http://stackoverflow.com/a/472918/240733) that makes use of [`System.Text.Encoding.GetBytes(string)`](http://msdn.microsoft.com/en-us/library/system.text.encoding.getbytes.aspx "MSDN reference"). – stakx - no longer contributing Oct 16 '14 at 14:53
  • @MichaelLiu I'm hashing a password and was following http://stackoverflow.com/a/10380166/1113475 – Kevin Brydon Oct 16 '14 at 14:54
  • 1
    Marshal.SizeOf(GetType(Char)) – Bjørn-Roger Kringsjå Oct 16 '14 at 14:54
  • 1
    @stakx I've seen this. The top answer says encoding doesn't matter. The second answer (the one you've linked to) says encoding does matter. I would have thought the answer would not involve talk of encoding. – Kevin Brydon Oct 16 '14 at 14:58
  • @KevinBrydon: It all depends on what you are going to do with the `byte[]` array. Since you derive its capacity from `someString`, it seemed plausible that you want to get `someString`'s characters in there. Whether encoding matters or not depends on whether you care about encoding. If you are simply interested in the string's raw bytes, then encoding doesn't matter. If you give the bytes to someone who expects a UTF-8 string, or an EBCDIC string, etc. then encoding obviously would matter. – stakx - no longer contributing Oct 16 '14 at 15:08
  • The post you are following is wrong in spite of high vote count. That code still uses an encoding (Unicode), and even if it didn't, the encoding still matters, because you need to be able to decrypt the string on a different system than the one that encrypted it and have meaningful results. Even with the same system doing the encryping/decrypting, soemthing as simple as windows update patch to the .Net framework could break that. Pick an encoding (like Unicode or UTF-8), and just call it's [GetBytes()](http://msdn.microsoft.com/en-us/library/system.text.encoding.getbytes.aspx) method. – Joel Coehoorn Oct 16 '14 at 15:14

3 Answers3

4

The 'Len' operator in VB will do this (but it works on instances, so you need to adjust accordingly):

Dim bytes = New Byte((someString.Length * Len(New Char)) - 1){}
Dave Doknjas
  • 5,744
  • 1
  • 12
  • 24
2

VB.NET's Char maps to .NET's System.Char, which is defined in ECMA 335 to be a 16-bit Unicode character. Meaning, Char has a fixed size (no matter on which platform you compile or run your code), you don't actually need sizeof.

Therefore, just multiply by 2.

stakx - no longer contributing
  • 77,057
  • 17
  • 151
  • 248
  • Instead of multiplying by 2 would I be safe to use the `Marshal.SizeOf` method in this situation? – Kevin Brydon Oct 16 '14 at 15:17
  • @Kevin Brydon: Marshal.SizeOf sounds the same, but is just not equivalent to the C# sizeof operator - VB's 'Len' operator does what sizeof does, but on instances. – Dave Doknjas Oct 16 '14 at 15:40
  • -1! Don't just "multiply by 2"! I guess some people don't remember the days when `Char`s could be 1 byte... or the days when an `int` was 2 bytes and the Word development team had to spent untold hours fixing things when Win32 came along... Yes, a change would break a lot of other people's code too: but that doesn't mean a change isn't going to happen. – AAT Oct 16 '14 at 16:38
  • 2
    @AAT `char`s and `int`s were always the same size in C# and will always be, because the specification explicitly defines them. You might be confusing this with C and C++, where the size of `char` or `int` still isn't defined by the specification. – svick Oct 16 '14 at 16:43
  • 1
    @svick Well, no doubt I am conditioned by my many years in the C and C++ domain... but I don't trust the PTBs to never change things! And also, I __never__ trust magic numbers. So at the very minimum, I would have a `const kSizeOfChar = 2` or something along those lines, but I would rather extract the size than look up ECMA 335. – AAT Oct 16 '14 at 16:55
  • @AAT I don't quite understand how can you program at all, if you don't believe that what the specification (and library documentation) says won't change in a way that would break your code. – svick Oct 16 '14 at 17:17
  • @AAT: I used to code in C++ too, and would have whipped myself back then for suggesting "just multiply by 2". This time around, my answer is intended to help get the job done *now*, not for code that will still run 10,000 years from now. Redefining a primitive type of the CLI / .NET would be a very fundamental, breaking change, and I am reasonably sure that is not going to happen anytime soon. Nevertheless, thanks for bringing in that point of view! – stakx - no longer contributing Oct 16 '14 at 18:45
  • @svick, stakx: OK I am happy to trust that the sizes of .NET types are really fixed, my C is clearly showing . But I still wouldn't want a magic number in the code. – AAT Oct 17 '14 at 09:50
1

I'm hashing a password and was following stackoverflow.com/a/10380166/1113475

The top answer there is wrong, in spite of high vote count. The code for that answer still uses an encoding (Unicode), because that's how all strings are encoded internally in .NET. Even if it didn't, the encoding still matters, because you need to be able to decrypt the string on a different system than the one that encrypted it and obtain meaningful results. Even with the same system doing the encrypting/decrypting, something as simple as a Windows Update patch to the .NET Framework could break this. Pick an encoding (like Unicode or UTF-8), and just call its GetBytes() method:

Dim bytes = Encoding.Unicode.GetBytes(password)
InteXX
  • 5,804
  • 5
  • 33
  • 54
Joel Coehoorn
  • 362,140
  • 107
  • 528
  • 764
  • I'm hesitant to accept any of these current answers as they are specific to my situation. I was expecting a Yes/No type answer and maybe an aside to solve my specific problem. I'll wait a bit and then edit your post to include a "No there is no equivalent" above your answer to my specific question. – Kevin Brydon Oct 16 '14 at 15:31
  • @KevinBrydon That's the danger of asking two questions at the same time and one of the reasons why you shouldn't do that. – svick Oct 16 '14 at 16:39