1

I have a cryptographic class written in VB that I am trying to translate into C#. In the VB code, there is a block of code:

    ' Allocate byte array to hold our salt.
    Dim salt() As Byte = New Byte(saltLen - 1) {}

    ' Populate salt with cryptographically strong bytes.
    Dim rng As RNGCryptoServiceProvider = New RNGCryptoServiceProvider()

    rng.GetNonZeroBytes(salt)

    ' Split salt length (always one byte) into four two-bit pieces and
    ' store these pieces in the first four bytes of the salt array.
    salt(0) = ((salt(0) And &HFC) Or (saltLen And &H3))
    salt(1) = ((salt(1) And &HF3) Or (saltLen And &HC))
    salt(2) = ((salt(2) And &HCF) Or (saltLen And &H30))
    salt(3) = ((salt(3) And &H3F) Or (saltLen And &HC0))

I translated it into C# and ended up with the following:

    // Allocate byte array to hold our salt.
    byte[] salt = new byte[saltLen];

    // Populate salt with cryptographically strong bytes.
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

    rng.GetNonZeroBytes(salt);

    // Split salt length (always one byte) into four two-bit pieces and
    // store these pieces in the first four bytes of the salt array.
    salt[0] = ((salt[0] & 0xfc) | (saltLen & 0x3));
    salt[1] = ((salt[1] & 0xf3) | (saltLen & 0xc));
    salt[2] = ((salt[2] & 0xcf) | (saltLen & 0x30));
    salt[3] = ((salt[3] & 0x3f) | (saltLen & 0xc0));

When I try to compile this I get an error on each of the 4 assigns to salt[] - the last 4 lines in the code block. The error is:

Error 255 Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)

Please forgive the ignorance - I am a relative C# newbie, I tried the following but still got errors:

    salt[0] = ((salt[0] & 0xfc as byte) | (saltLen & 0x3 as byte));
    salt[0] = ((salt[0] & (byte)0xfc) | (saltLen & (byte)0x3));

I am not quite sure what this code is doing which perhaps explains why I am unable to figure out how to fix it.

Any help is appreciated.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Brian Ross
  • 71
  • 1
  • 10

1 Answers1

9

Bitwise operators always return int when the operands are int or smaller. Cast the results to byte:

salt[0] = (byte)((salt[0] & 0xfc) | (saltLen & 0x3));
salt[1] = (byte)((salt[1] & 0xf3) | (saltLen & 0xc));
salt[2] = (byte)((salt[2] & 0xcf) | (saltLen & 0x30));
salt[3] = (byte)((salt[3] & 0x3f) | (saltLen & 0xc0));

I am not quite sure what this code is doing

That's more important that getting a syntax that compiles. There are enough idiosyncrasies between VB and C# that knowing what the code does so that you can verify the results is more important than just fixing compiler/syntax errors.

Community
  • 1
  • 1
D Stanley
  • 149,601
  • 11
  • 178
  • 240