Beranda > C#, Kriptografi > Big Endian vs Little Endian

Big Endian vs Little Endian

Saya menemukan problem ini ketika mengerjakan tugas Kriptografi untuk implementasi SHA atau Secure Hash Algorithm. Ada beberapa macam SHA, bisa dilihat di sini. Sebenarnya, cukup mudah melakukan implementasinya, untuk algoritmanya, bisa googling, atau langsung cari di wikipedia. Namun, ternyata rada sulit untuk konversi dari integer atau char ke bit. Hal ini dikarenakan terdapat 2 mode di komputer dalam menyimpan data. Yakni, big endian dan little endian.

Lalu, apa hubungan SHA dengan si big dan little endian ini? Masalah muncul ketika SHA meminta kita merubah integer ke suatu representasi bit dengan mode big-endian, sedangkan tidak semua komputer merepresentasikannya menjadi big endian. OS Windows biasanya menggunakan little endian sebagai modenya.

Perbedaan little endian dan big endian sebenarnya sangat sepele, kalau big-endian representasi bit nya mirip tulisan kita, yakni makin ke kiri, makin signifikan bitnya. Sedangkan little endian sebaliknya. Contoh :

00001001 = 9 (big endian)

00001001 = 144 (little endian)

Sebenarnya, cukup dibalik saja. Namun, untuk setiap tipe data, menggunakan banyak byte yang berbeda, Contoh, boolean 1 byte, char 1 byte, int 1 byte, dan seterusnya. Sehingga perlu ada konversi masing-masing.

Jadi, yang harus diperhatikan adalah :

  1. Mode apa yang digunakan komputer kita, big endian atau little endian
  2. Tipe data apa yang ingin kita ubah

Berikut ini contoh kerjaan saya :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tester
{
    class mySHA
    {
        private static byte firstPad = 128;
        private static byte secondPad = 0;

        public static string doSHA1(byte[] bInput)
        {
            // initialize variable
            uint h0 = 0x67452301;
            uint h1 = 0xEFCDAB89;
            uint h2 = 0x98BADCFE;
            uint h3 = 0x10325476;
            uint h4 = 0xC3D2E1F0;
            uint a, b, c, d, e;
            uint f, k, temp;
            string sh0, sh1, sh2, sh3, sh4;

            // padding di sini
            bInput = padding(bInput);

            // ubah ke uint[] di sini
            uint[] uiArray = ToArrayUint(bInput);

            int numChunk = uiArray.Length / 16;
            if (uiArray.Length % 16 != 0) numChunk++;

            for (int i = 0; i < numChunk; ++i)
            {
                uint[] w = new uint[80];
                int j = 0;
                for (j = 0; j < 16; ++j)
                {
                    w[j] = uiArray[(16 * i) + j];

                    if (BitConverter.IsLittleEndian)
                    {
                        w[j] = ReverseBytes(w[j]);
                    }
                }

                for (; j < 80; ++j)
                {
                    w[j] = rotateLeft((w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16]), 1);
                }

                a = h0;
                b = h1;
                c = h2;
                d = h3;
                e = h4;
                for (int l = 0; l < 80; ++l)
                {
                    if (0 <= l && l < 20)
                    {
                        f = (b & c) | ((~b) & d);
                        k = 0x5A827999;
                    }
                    else if (20 <= l && l < 40)
                    {
                        f = b ^ c ^ d;
                        k = 0x6ED9EBA1;
                    }
                    else if (40 <= l && l < 60)
                    {
                        f = (b & c) | (b & d) | (c & d);
                        k = 0x8F1BBCDC;
                    }
                    else //if (60 <= l && l < 80)
                    {
                        f = b ^ c ^ d;
                        k = 0xCA62C1D6;
                    }
                    temp = (rotateLeft(a, 5) + f + e + k + w[l]);
                    e = d;
                    d = c;
                    c = rotateLeft(b, 30);
                    b = a;
                    a = temp;

                }
                h0 = (h0 + a);
                h1 = (h1 + b);
                h2 = (h2 + c);
                h3 = (h3 + d);
                h4 = (h4 + e);

            }
            sh0 = Convert.ToString(h0, 16);
            sh1 = Convert.ToString(h2, 16);
            sh2 = Convert.ToString(h2, 16);
            sh3 = Convert.ToString(h3, 16);
            sh4 = Convert.ToString(h4, 16);

            return sh0 + " " + sh1 + " " + sh2 + " " + sh3 + " " + sh4;
        }

        private static byte[] padding(byte[] bInput)
        {
            UInt64 length = getLength(bInput);
            if (BitConverter.IsLittleEndian)
            {
                length = ReverseBytes(length);
            }

            byte[] byteLength = ToByteArray(length);

            bInput = concat(bInput, firstPad);
            while (bInput.Length % 64 != 56)
            {
                bInput = concat(bInput, secondPad);
            }
            bInput = concat(bInput, byteLength);

            return bInput;
        }

        private static UInt64 getLength(byte[] bInput)
        {
            return (UInt64) (bInput.Length * 8);
        }

        private static byte[] ToByteArray(UInt64 n)
        {
            return BitConverter.GetBytes(n);
        }

        private static uint[] ToArrayUint(byte[] bInput)
        {
            uint[] retval = new uint[bInput.Length/4];
            for (int i = 0; i < retval.Length; ++i)
            {
                retval[i] = BitConverter.ToUInt32(bInput, i*4);
            }
            return retval;
        }

        private static byte[] concat(byte[] a, byte[] b)
        {
            byte[] retval = new byte[a.Length + b.Length];
            int i = 0;
            for (i = 0; i < a.Length; ++i)
            {
                retval[i] = a[i];
            }
            int j = 0;
            for (; i < retval.Length; ++i)
            {
                retval[i] = b[j];
                ++j;
            }

            return retval;
        }

        private static byte[] concat(byte[] a, byte b)
        {
            byte[] retval = new byte[a.Length + 1];
            int i = 0;
            for (i = 0; i < a.Length; ++i)
            {
                retval[i] = a[i];
            }
            for (; i < retval.Length; ++i)
            {
                retval[i] = b;
            }

            return retval;
        }

        public static uint rotateLeft(uint uiValue, int shift)
        {
            if ((shift &= 31) == 0)
                return uiValue;
            return (uiValue << shift) | (uiValue >> (32 - shift));
        }

        public static UInt32 ReverseBytes(UInt32 value)
        {
            return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 |
                   (value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24;
        }

        public static UInt64 ReverseBytes(UInt64 value)
        {
            return (value & 0x00000000000000FFUL) << 56 | (value & 0x000000000000FF00UL) << 40 |
                   (value & 0x0000000000FF0000UL) << 24 | (value & 0x00000000FF000000UL) << 8 |
                   (value & 0x000000FF00000000UL) >> 8 | (value & 0x0000FF0000000000UL) >> 24 |
                   (value & 0x00FF000000000000UL) >> 40 | (value & 0xFF00000000000000UL) >> 56;
        }
    }
}

Kategori:C#, Kriptografi Tag:,
  1. 30 Mei 2015 pukul 12:10

    Reblogged this on To GOD be the Glory and commented:
    thank you Lord for Ypur blessing

  1. No trackbacks yet.

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: