Click here to Skip to main content
15,892,746 members
Articles / Mobile Apps / Windows Mobile

Learn How to Find GPS Location on Any SmartPhone, and Then Make it Relevant

Rate me:
Please Sign up or sign in to vote.
4.94/5 (126 votes)
10 Feb 2009CPOL10 min read 775.2K   11.1K   381  
A step by step tutorial for getting GPS from any SmartPhone, even without GPS built in, and then making location useful.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;

/*
 * NOTE: The Compact Framework doesn't have keyed hashing build in, and none of the 
 * HMACSHA1 implementations I found work correctly with .NET CF (issues with key generation).
 * 
 * This is a direct copy of the .Net 3.5 cryptography from Reflector.
 */

namespace System.Security.Cryptography
{
    public abstract class HashAlgorithm : IDisposable
    {
        protected int HashSizeValue;
        protected internal byte[] HashValue;
        private bool m_bDisposed;
        protected int State;

        protected HashAlgorithm()
        {
        }

        public void Clear()
        {
            ((IDisposable)this).Dispose();
        }

        public byte[] ComputeHash(byte[] buffer)
        {
            this.HashCore(buffer, 0, buffer.Length);
            this.HashValue = this.HashFinal();
            byte[] buffer2 = (byte[])this.HashValue.Clone();
            this.Initialize();
            return buffer2;
        }

        public byte[] ComputeHash(Stream inputStream)
        {
            int num;
            
            byte[] buffer = new byte[0x1000];
            do
            {
                num = inputStream.Read(buffer, 0, 0x1000);
                if (num > 0)
                {
                    this.HashCore(buffer, 0, num);
                }
            }
            while (num > 0);
            this.HashValue = this.HashFinal();
            byte[] buffer2 = (byte[])this.HashValue.Clone();
            this.Initialize();
            return buffer2;
        }

        public byte[] ComputeHash(byte[] buffer, int offset, int count)
        {
            this.HashCore(buffer, offset, count);
            this.HashValue = this.HashFinal();
            byte[] buffer2 = (byte[])this.HashValue.Clone();
            this.Initialize();
            return buffer2;
        }

        public static HashAlgorithm Create()
        {
            return Create("System.Security.Cryptography.HashAlgorithm");
        }

        public static HashAlgorithm Create(string hashName)
        {
            return (HashAlgorithm)CryptoConfig.CreateFromName(hashName);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.HashValue != null)
                {
                    Array.Clear(this.HashValue, 0, this.HashValue.Length);
                }
                this.HashValue = null;
                this.m_bDisposed = true;
            }
        }

        protected abstract void HashCore(byte[] array, int ibStart, int cbSize);
        protected abstract byte[] HashFinal();
        public abstract void Initialize();
        void IDisposable.Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
        {
            this.State = 1;
            this.HashCore(inputBuffer, inputOffset, inputCount);
            if ((outputBuffer != null) && ((inputBuffer != outputBuffer) || (inputOffset != outputOffset)))
            {
                Buffer.BlockCopy(inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount);
            }
            return inputCount;
        }

        public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
        {
            this.HashCore(inputBuffer, inputOffset, inputCount);
            this.HashValue = this.HashFinal();
            byte[] dst = new byte[inputCount];
            if (inputCount != 0)
            {
                Buffer.BlockCopy(inputBuffer, inputOffset, dst, 0, inputCount);
            }
            this.State = 0;
            return dst;
        }

        public virtual bool CanReuseTransform
        {
            get
            {
                return true;
            }
        }

        public virtual bool CanTransformMultipleBlocks
        {
            get
            {
                return true;
            }
        }

        public virtual byte[] Hash
        {
            get
            {
                return (byte[])this.HashValue.Clone();
            }
        }

        public virtual int HashSize
        {
            get
            {
                return this.HashSizeValue;
            }
        }

        public virtual int InputBlockSize
        {
            get
            {
                return 1;
            }
        }

        public virtual int OutputBlockSize
        {
            get
            {
                return 1;
            }
        }
    }

    public abstract class KeyedHashAlgorithm : HashAlgorithm
    {
        protected byte[] KeyValue;

        protected KeyedHashAlgorithm()
        {
        }

        public static KeyedHashAlgorithm Create()
        {
            return Create("System.Security.Cryptography.KeyedHashAlgorithm");
        }

        public static KeyedHashAlgorithm Create(string algName)
        {
            return (KeyedHashAlgorithm)CryptoConfig.CreateFromName(algName);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.KeyValue != null)
                {
                    Array.Clear(this.KeyValue, 0, this.KeyValue.Length);
                }
                this.KeyValue = null;
            }
            base.Dispose(disposing);
        }

        public virtual byte[] Key
        {
            get
            {
                return (byte[])this.KeyValue.Clone();
            }
            set
            {
                this.KeyValue = (byte[])value.Clone();
            }
        }
    }

    public abstract class HMAC : KeyedHashAlgorithm
    {
        private int blockSizeValue = 0x40;
        internal HashAlgorithm m_hash1;
        internal HashAlgorithm m_hash2;
        private bool m_hashing;
        internal string m_hashName;
        private byte[] m_inner;
        private byte[] m_outer;

        protected HMAC()
        {
        }

        public static HMAC Create()
        {
            return Create("System.Security.Cryptography.HMAC");
        }

        public static HMAC Create(string algorithmName)
        {
            return (HMAC)CryptoConfig.CreateFromName(algorithmName);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.m_hash1 != null)
                {
                    this.m_hash1.Clear();
                }
                if (this.m_hash2 != null)
                {
                    this.m_hash2.Clear();
                }
                if (this.m_inner != null)
                {
                    Array.Clear(this.m_inner, 0, this.m_inner.Length);
                }
                if (this.m_outer != null)
                {
                    Array.Clear(this.m_outer, 0, this.m_outer.Length);
                }
            }
            base.Dispose(disposing);
        }

        protected override void HashCore(byte[] rgb, int ib, int cb)
        {
            if (!this.m_hashing)
            {
                this.m_hash1.TransformBlock(this.m_inner, 0, this.m_inner.Length, this.m_inner, 0);
                this.m_hashing = true;
            }
            this.m_hash1.TransformBlock(rgb, ib, cb, rgb, ib);
        }

        protected override byte[] HashFinal()
        {
            if (!this.m_hashing)
            {
                this.m_hash1.TransformBlock(this.m_inner, 0, this.m_inner.Length, this.m_inner, 0);
                this.m_hashing = true;
            }
            this.m_hash1.TransformFinalBlock(new byte[0], 0, 0);
            byte[] hashValue = this.m_hash1.HashValue;
            this.m_hash2.TransformBlock(this.m_outer, 0, this.m_outer.Length, this.m_outer, 0);
            this.m_hash2.TransformBlock(hashValue, 0, hashValue.Length, hashValue, 0);
            this.m_hashing = false;
            this.m_hash2.TransformFinalBlock(new byte[0], 0, 0);
            return this.m_hash2.HashValue;
        }

        public override void Initialize()
        {
            this.m_hash1.Initialize();
            this.m_hash2.Initialize();
            this.m_hashing = false;
        }

        internal void InitializeKey(byte[] key)
        {
            this.m_inner = null;
            this.m_outer = null;
            if (key.Length > this.BlockSizeValue)
            {
                base.KeyValue = this.m_hash1.ComputeHash(key);
            }
            else
            {
                base.KeyValue = (byte[])key.Clone();
            }
            this.UpdateIOPadBuffers();
        }

        private void UpdateIOPadBuffers()
        {
            int num;
            if (this.m_inner == null)
            {
                this.m_inner = new byte[this.BlockSizeValue];
            }
            if (this.m_outer == null)
            {
                this.m_outer = new byte[this.BlockSizeValue];
            }
            for (num = 0; num < this.BlockSizeValue; num++)
            {
                this.m_inner[num] = 0x36;
                this.m_outer[num] = 0x5c;
            }
            for (num = 0; num < base.KeyValue.Length; num++)
            {
                this.m_inner[num] = (byte)(this.m_inner[num] ^ base.KeyValue[num]);
                this.m_outer[num] = (byte)(this.m_outer[num] ^ base.KeyValue[num]);
            }
        }

        // Properties
        protected int BlockSizeValue
        {
            get
            {
                return this.blockSizeValue;
            }
            set
            {
                this.blockSizeValue = value;
            }
        }

        public string HashName
        {
            get
            {
                return this.m_hashName;
            }
            set
            {
                this.m_hashName = value;
                this.m_hash1 = HashAlgorithm.Create(this.m_hashName);
                this.m_hash2 = HashAlgorithm.Create(this.m_hashName);
            }
        }

        public override byte[] Key
        {
            get
            {
                return (byte[])base.KeyValue.Clone();
            }
            set
            {
                this.InitializeKey(value);
            }
        }
    }

    public class HmacSha1 : HMAC
    {
        // Methods
        public HmacSha1() : this(null)
        {
        }

        public HmacSha1(byte[] key) : this(key, false)
        {
        }

        public HmacSha1(byte[] key, bool useManagedSha1)
        {
            if (key == null)
            {
                key = new byte[64];

                Random random = new Random();
                random.NextBytes(key);
            }

            base.m_hashName = "SHA1";
            base.m_hash1 = new SHA1Managed();
            base.m_hash2 = new SHA1Managed();
            base.HashSizeValue = 160;
            base.InitializeKey(key);
        }
    }

    public class SHA1Managed : SHA1
    {
        private byte[] _buffer;
        private long _count;
        private uint[] _expandedBuffer;
        private uint[] _stateSHA1;

        public SHA1Managed()
        {
            this._stateSHA1 = new uint[5];
            this._buffer = new byte[0x40];
            this._expandedBuffer = new uint[80];
            this.InitializeState();
        }

        private byte[] _EndHash()
        {
            byte[] block = new byte[20];
            int num = 0x40 - ((int)(this._count & 0x3fL));
            if (num <= 8)
            {
                num += 0x40;
            }
            byte[] partIn = new byte[num];
            partIn[0] = 0x80;
            long num2 = this._count * 8L;
            partIn[num - 8] = (byte)((num2 >> 0x38) & 0xffL);
            partIn[num - 7] = (byte)((num2 >> 0x30) & 0xffL);
            partIn[num - 6] = (byte)((num2 >> 40) & 0xffL);
            partIn[num - 5] = (byte)((num2 >> 0x20) & 0xffL);
            partIn[num - 4] = (byte)((num2 >> 0x18) & 0xffL);
            partIn[num - 3] = (byte)((num2 >> 0x10) & 0xffL);
            partIn[num - 2] = (byte)((num2 >> 8) & 0xffL);
            partIn[num - 1] = (byte)(num2 & 0xffL);
            this._HashData(partIn, 0, partIn.Length);
            DWORDToBigEndian(block, this._stateSHA1, 5);
            base.HashValue = block;
            return block;
        }

        internal static void DWORDToBigEndian(byte[] block, uint[] x, int digits)
        {
            int index = 0;
            for (int i = 0; index < digits; i += 4)
            {
                block[i] = (byte)((x[index] >> 0x18) & 0xff);
                block[i + 1] = (byte)((x[index] >> 0x10) & 0xff);
                block[i + 2] = (byte)((x[index] >> 8) & 0xff);
                block[i + 3] = (byte)(x[index] & 0xff);
                index++;
            }
        }
        
        internal static unsafe void DWORDFromBigEndian(uint* x, int digits, byte* block)
        {
            int index = 0;
            for (int i = 0; index < digits; i += 4)
            {
                x[index] = (uint)((((block[i] << 0x18) | (block[i + 1] << 0x10)) | (block[i + 2] << 8)) | block[i + 3]);
                index++;
            }
        }


        private unsafe void _HashData(byte[] partIn, int ibStart, int cbSize)
        {
            int count = cbSize;
            int srcOffset = ibStart;
            int dstOffset = (int)(this._count & 0x3fL);
            this._count += count;
            fixed (uint* numRef = this._stateSHA1)
            {
                fixed (byte* numRef2 = this._buffer)
                {
                    fixed (uint* numRef3 = this._expandedBuffer)
                    {
                        if ((dstOffset > 0) && ((dstOffset + count) >= 0x40))
                        {
                            Buffer.BlockCopy(partIn, srcOffset, this._buffer, dstOffset, 0x40 - dstOffset);
                            srcOffset += 0x40 - dstOffset;
                            count -= 0x40 - dstOffset;
                            SHATransform(numRef3, numRef, numRef2);
                            dstOffset = 0;
                        }
                        while (count >= 0x40)
                        {
                            Buffer.BlockCopy(partIn, srcOffset, this._buffer, 0, 0x40);
                            srcOffset += 0x40;
                            count -= 0x40;
                            SHATransform(numRef3, numRef, numRef2);
                        }
                        if (count > 0)
                        {
                            Buffer.BlockCopy(partIn, srcOffset, this._buffer, dstOffset, count);
                        }
                    }
                }
            }
        }

        protected override void HashCore(byte[] rgb, int ibStart, int cbSize)
        {
            this._HashData(rgb, ibStart, cbSize);
        }

        protected override byte[] HashFinal()
        {
            return this._EndHash();
        }

        public override void Initialize()
        {
            this.InitializeState();
            Array.Clear(this._buffer, 0, this._buffer.Length);
            Array.Clear(this._expandedBuffer, 0, this._expandedBuffer.Length);
        }

        private void InitializeState()
        {
            this._count = 0L;
            this._stateSHA1[0] = 0x67452301;
            this._stateSHA1[1] = 0xefcdab89;
            this._stateSHA1[2] = 0x98badcfe;
            this._stateSHA1[3] = 0x10325476;
            this._stateSHA1[4] = 0xc3d2e1f0;
        }

        private static unsafe void SHAExpand(uint* x)
        {
            for (int i = 0x10; i < 80; i++)
            {
                uint num2 = ((x[i - 3] ^ x[i - 8]) ^ x[i - 14]) ^ x[i - 0x10];
                x[i] = (num2 << 1) | (num2 >> 0x1f);
            }
        }

        private static unsafe void SHATransform(uint* expandedBuffer, uint* state, byte* block)
        {
            uint num = state[0];
            uint num2 = state[1];
            uint num3 = state[2];
            uint num4 = state[3];
            uint num5 = state[4];
            DWORDFromBigEndian(expandedBuffer, 0x10, block);
            SHAExpand(expandedBuffer);
            int index = 0;
            while (index < 20)
            {
                num5 += ((((num << 5) | (num >> 0x1b)) + (num4 ^ (num2 & (num3 ^ num4)))) + expandedBuffer[index]) + 0x5a827999;
                num2 = (num2 << 30) | (num2 >> 2);
                num4 += ((((num5 << 5) | (num5 >> 0x1b)) + (num3 ^ (num & (num2 ^ num3)))) + expandedBuffer[index + 1]) + 0x5a827999;
                num = (num << 30) | (num >> 2);
                num3 += ((((num4 << 5) | (num4 >> 0x1b)) + (num2 ^ (num5 & (num ^ num2)))) + expandedBuffer[index + 2]) + 0x5a827999;
                num5 = (num5 << 30) | (num5 >> 2);
                num2 += ((((num3 << 5) | (num3 >> 0x1b)) + (num ^ (num4 & (num5 ^ num)))) + expandedBuffer[index + 3]) + 0x5a827999;
                num4 = (num4 << 30) | (num4 >> 2);
                num += ((((num2 << 5) | (num2 >> 0x1b)) + (num5 ^ (num3 & (num4 ^ num5)))) + expandedBuffer[index + 4]) + 0x5a827999;
                num3 = (num3 << 30) | (num3 >> 2);
                index += 5;
            }
            while (index < 40)
            {
                num5 += ((((num << 5) | (num >> 0x1b)) + ((num2 ^ num3) ^ num4)) + expandedBuffer[index]) + 0x6ed9eba1;
                num2 = (num2 << 30) | (num2 >> 2);
                num4 += ((((num5 << 5) | (num5 >> 0x1b)) + ((num ^ num2) ^ num3)) + expandedBuffer[index + 1]) + 0x6ed9eba1;
                num = (num << 30) | (num >> 2);
                num3 += ((((num4 << 5) | (num4 >> 0x1b)) + ((num5 ^ num) ^ num2)) + expandedBuffer[index + 2]) + 0x6ed9eba1;
                num5 = (num5 << 30) | (num5 >> 2);
                num2 += ((((num3 << 5) | (num3 >> 0x1b)) + ((num4 ^ num5) ^ num)) + expandedBuffer[index + 3]) + 0x6ed9eba1;
                num4 = (num4 << 30) | (num4 >> 2);
                num += ((((num2 << 5) | (num2 >> 0x1b)) + ((num3 ^ num4) ^ num5)) + expandedBuffer[index + 4]) + 0x6ed9eba1;
                num3 = (num3 << 30) | (num3 >> 2);
                index += 5;
            }
            while (index < 60)
            {
                num5 += ((((num << 5) | (num >> 0x1b)) + ((num2 & num3) | (num4 & (num2 | num3)))) + expandedBuffer[index]) + 0x8f1bbcdc;
                num2 = (num2 << 30) | (num2 >> 2);
                num4 += ((((num5 << 5) | (num5 >> 0x1b)) + ((num & num2) | (num3 & (num | num2)))) + expandedBuffer[index + 1]) + 0x8f1bbcdc;
                num = (num << 30) | (num >> 2);
                num3 += ((((num4 << 5) | (num4 >> 0x1b)) + ((num5 & num) | (num2 & (num5 | num)))) + expandedBuffer[index + 2]) + 0x8f1bbcdc;
                num5 = (num5 << 30) | (num5 >> 2);
                num2 += ((((num3 << 5) | (num3 >> 0x1b)) + ((num4 & num5) | (num & (num4 | num5)))) + expandedBuffer[index + 3]) + 0x8f1bbcdc;
                num4 = (num4 << 30) | (num4 >> 2);
                num += ((((num2 << 5) | (num2 >> 0x1b)) + ((num3 & num4) | (num5 & (num3 | num4)))) + expandedBuffer[index + 4]) + 0x8f1bbcdc;
                num3 = (num3 << 30) | (num3 >> 2);
                index += 5;
            }
            while (index < 80)
            {
                num5 += ((((num << 5) | (num >> 0x1b)) + ((num2 ^ num3) ^ num4)) + expandedBuffer[index]) + 0xca62c1d6;
                num2 = (num2 << 30) | (num2 >> 2);
                num4 += ((((num5 << 5) | (num5 >> 0x1b)) + ((num ^ num2) ^ num3)) + expandedBuffer[index + 1]) + 0xca62c1d6;
                num = (num << 30) | (num >> 2);
                num3 += ((((num4 << 5) | (num4 >> 0x1b)) + ((num5 ^ num) ^ num2)) + expandedBuffer[index + 2]) + 0xca62c1d6;
                num5 = (num5 << 30) | (num5 >> 2);
                num2 += ((((num3 << 5) | (num3 >> 0x1b)) + ((num4 ^ num5) ^ num)) + expandedBuffer[index + 3]) + 0xca62c1d6;
                num4 = (num4 << 30) | (num4 >> 2);
                num += ((((num2 << 5) | (num2 >> 0x1b)) + ((num3 ^ num4) ^ num5)) + expandedBuffer[index + 4]) + 0xca62c1d6;
                num3 = (num3 << 30) | (num3 >> 2);
                index += 5;
            }
            state[0] += num;
            uint* numPtr1 = state + 1;
            numPtr1[0] += num2;
            uint* numPtr2 = state + 2;
            numPtr2[0] += num3;
            uint* numPtr3 = state + 3;
            numPtr3[0] += num4;
            uint* numPtr4 = state + 4;
            numPtr4[0] += num5;
        }
    }

    public abstract class SHA1 : HashAlgorithm
    {
        // Methods
        protected SHA1()
        {
            base.HashSizeValue = 160;
        }

        public static SHA1 Create()
        {
            return Create("System.Security.Cryptography.SHA1");
        }

        public static SHA1 Create(string hashName)
        {
            return (SHA1)CryptoConfig.CreateFromName(hashName);
        }
    }

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer PageLabs
United States United States
I'm the founder of PageLabs, a web-based performance and SEO optimization site.

Give your site a boost in performance, even take a free speed test!

http://www.pagelabs.com

Comments and Discussions