Is there a better way to detect endianness in .NET than BitConverter.IsLittleEndian?

北慕城南 提交于 2019-12-25 11:14:06

问题


It would be nice if the .NET framework just gave functions/methods from the BitConverter class that just explicitly returned an array of bytes in the proper requested endianness.

I've done some functions like this in other code, but is there a shorter more direct way? (efficiency is key since this concept is used a TON in various crypto and password derivation contexts, including PBKDF2, Skein, HMAC, BLAKE2, AES and others)

// convert an unsigned int into an array of bytes BIG ENDIEN
// per the spec section 5.2 step 3 for PBKDF2 RFC2898
static internal byte[] IntToBytes(uint i)
{
    byte[] bytes = BitConverter.GetBytes(i);
    if (!BitConverter.IsLittleEndian)
    {
        return bytes;
    }
    else
    {
        Array.Reverse(bytes);
        return bytes;
    }
}

I also see that others struggle with this question, and I haven't seen a good answer yet :( How to deal with 'Endianness'


回答1:


The way I convert between integers and byte[] is by using bitshifts with fixed endianness. You don't need to worry about host endianness with such code. When you care that much about performance, you should avoid allocating a new array each time.

In my crypto library I use:

public static UInt32 LoadLittleEndian32(byte[] buf, int offset)
{
    return
        (UInt32)(buf[offset + 0])
    | (((UInt32)(buf[offset + 1])) << 8)
    | (((UInt32)(buf[offset + 2])) << 16)
    | (((UInt32)(buf[offset + 3])) << 24);
}

public static void StoreLittleEndian32(byte[] buf, int offset, UInt32 value)
{
    buf[offset + 0] = (byte)value;
    buf[offset + 1] = (byte)(value >> 8);
    buf[offset + 2] = (byte)(value >> 16);
    buf[offset + 3] = (byte)(value >> 24);
}

With big endian you just need to change the shift amounts or the offsets:

public static void StoreBigEndian32(byte[] buf, int offset, UInt32 value)
{
    buf[offset + 3] = (byte)value;
    buf[offset + 2] = (byte)(value >> 8);
    buf[offset + 1] = (byte)(value >> 16);
    buf[offset + 0] = (byte)(value >> 24);
}

If you're targetting .net 4.5 it can be useful to mark these methods with [MethodImpl(MethodImplOptions.AggressiveInlining)].

Another performance tip for crypto is avoiding arrays as much as possible. Load the data from the array at the beginning of the function, then run everything using local variables and only in the very end you copy back to the array.



来源:https://stackoverflow.com/questions/18648103/is-there-a-better-way-to-detect-endianness-in-net-than-bitconverter-islittleend

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!