Main Site Documentation

Sha-1?


#1

Is there an SHA-1 in the FEZs?

The onewire device i’m tring to write to requires a 160bit key generated via an SHA-1 function. I have ported the function over from the PC based C# but it REALLY takes ages to complete.

As a test, here is a small part(but the longest to execute) of the algorithm. It takes 142 seconds to do one (partial hash as I condensed the code) hash. The chip requires a hash for each 8 bytes written… :slight_smile:

Code:


        public static void Main()
        {
            UInt32[] M = new UInt32[16];
            Debug.EnableGCMessages(false);

            long StartTicks = DateTime.Now.Ticks;

            Debug.Print("Start:" + DateTime.Now.ToString());
            for (byte t = 0; t <= 79; t++)
            {
                Debug.Print(t.ToString() + ":" + ((float)(DateTime.Now.Ticks-StartTicks) /10000000).ToString());
                SequenceW(M, t);

            }
            Debug.Print("End:" + DateTime.Now.ToString());
        }

        private static UInt32 CircularShiftLeft(byte t, UInt32 W)
        {
            while (t-- > 0)
            {
                if (W >= 2147483648)//(Int32.Max/2)+1
                {
                    W = (W << 1) + 1;
                }
                else
                {
                    W = (W << 1);
                }
            }
            return W;
        }
        private static UInt32 SequenceW(UInt32[] M, byte t)
        {
            if (t <= 15)
            {
                return M[t];
            }
            else if (t <= 79)
            {
                UInt32 Exp = SequenceW(M, (byte)(t - 3)) ^ SequenceW(M, (byte)(t - 8)) ^ SequenceW(M, (byte)(t - 14)) ^ SequenceW(M, (byte)(t - 16));
                return CircularShiftLeft(1, Exp);
            }
            else
            {
                throw new Exception();
            }
        }

Output:

I looking at the SHA-1 alogritm on Wikipedia I see that I can flaten the recursive calling of SequenceW. That will probably speed things up a bit…

Thanks,
Errol


#2

Have you seen this:

http://www.microframework.nl/2009/09/05/shahmac-digest-class/


#3

Will look at it now, thanks.

I rewrote it acording to the Wikipedia “formula”. It uses more ram but is way faster. Now it calculates a hash in 0.25 seconds. But I really do need even faster… :slight_smile:


        private static UInt32 CircularShiftLeft(byte t, UInt32 W)
        {
            while (t-- > 0)
            {
                if (W >= 2147483648)//(Int32.Max/2)+1
                {
                    W = (W << 1) + 1;
                }
                else
                {
                    W = (W << 1);
                }
            }
            return W;
        }
        public  static byte[] CalcMAC(UInt32[] M)
        {
            UInt32 A = 0X67452301;
            UInt32 B = 0xefcdab89;
            UInt32 C = 0x98badcfe;
            UInt32 D = 0x10325476;
            UInt32 E = 0xc3d2e1f0;
            UInt32[] W = new UInt32[80];
            UInt32 f = 0;
            UInt32 k = 0;
            UInt32 temp = 0;

            global::System.Array.Copy(M, W, M.Length);

            for (byte i = 16; i <= 79; i++)
            {
                W[i] = CircularShiftLeft(1,(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16])); 
            }


            for (byte i = 0; i <= 79; i++)
            {
                if (i <= 19)
                {
                    f = (B & C) | ((~B) & D);
                    k = 0x5A827999;
                }
                else if (i <= 39)
                {
                    f = B ^ C ^ D;
                    k=0x6ED9EBA1;
                }
                else if (i <= 59)
                {
                    f = (B & C) | (B & D) | (C & D);
                    k=0x8F1BBCDC;
                }
                else if (i <= 79)
                {
                    f = B ^ C ^ D;
                    k = 0xCA62C1D6;
                }

                temp = CircularShiftLeft(5, A) + f + E + k + W[i];
                E = D;
                D = C;
                C = CircularShiftLeft(30, B);
                B = A;
                A = temp;
            }

            byte[] Return = new byte[20];
            global::System.Array.Copy(BitConverter.GetBytes(E), 0, Return, 0, 4);
            global::System.Array.Copy(BitConverter.GetBytes(D), 0, Return, 4, 4);
            global::System.Array.Copy(BitConverter.GetBytes(C), 0, Return, 8, 4);
            global::System.Array.Copy(BitConverter.GetBytes(B), 0, Return, 12, 4);
            global::System.Array.Copy(BitConverter.GetBytes(A), 0, Return, 16, 4);

            return Return;
        }


#4

I have some good news for you

Look here and you will see http://netmf.codeplex.com/documentation

[quote]Cryptographic Primitives OM
The current support is obsolete and non-standard. We plan to provide a new object model that is compatible with the traditional .NET and Compact Framework model for the following primitives in the System.Security.Cryptography namespace (non-Cng): SHA-256 and 512, HMAC-SHA-256 and 512, SHA-1 , HMAC-SHA-1, MD-5, AES, 3-DES, RSA, Diffie-Hellman, DSA, and X509 certificates. The native code for the primitives will be the one from the OpenSSL stack.[/quote]


#5

Cool. :slight_smile:

But only August? :frowning:

Guess we can kludge forward with a managed class till then… ;D

Architect:
I looked at the SHA1 in that link of yours, and the variables are named differently but otherwise almost exactly what I did… :slight_smile:

Only thing I don’t understand is that they pad the output with 1 byte(0x80) and they add the length to the output stream, which I don’t need nor want as I always only hash one block…

Thanks,
Errol


#6

Maybe use RLP?


#7

Will probably look into that, but i will first look into porting our bitbanged onewire overdrive source over from an msp430 to RPL… :slight_smile: