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

namespace com.fly.secute
{
    public class mysec
    {
        byte[] table = new byte[64];
        public void gen_trans_table()
        {
            byte i;
            for (i = 0; i < 26; i++)
            {
                table[i] = (byte)(i + (byte)'A');
                table[i + 26] = (byte)(i + (byte)'a');
            }
            for (i = 0; i < 10; i++) table[i + 52] = (byte)(i + (byte)'0');
            table[62] = (byte)'*';
            table[63] = (byte)'#';
        }

        public void gen_key(UInt32 hours, byte[] key, byte[] keytext)
        {
            //确保时间为正数。 右移不会因为负数导致左边进了1
            byte[] work = new byte[12];
            int i;
            byte hi = (byte)((hours & 0xff00) >> 8);
            byte lo = (byte)(hours & 0x00ff);

            work[0] = (byte)((hi & 0xf0) | (lo & 0x0f));
            work[1] = (byte)((hi & 0x0f) | (lo & 0xf0));
            work[2] = lo;
            work[3] = hi;
            work[4] = (byte)(work[0] ^ work[1]);
            work[5] = (byte)(work[2] ^ work[3]);
            for (i = 0; i < 6; i++) work[i] ^= key[i];
            work[6] = (byte)(work[0] ^ work[1]);
            work[7] = (byte)(work[2] ^ work[3]);
            work[8] = (byte)(work[4] ^ work[5]);
            for (i = 0; i < 9; i++) keytext[i] = table[(int)(work[i] & 0x3f)];
            keytext[9] = table[(int)((work[0] & 0xc0) >> 2 | (work[1] & 0xc0) >> 4 | (work[2] & 0xc0) >> 6)];
            keytext[10] = table[(int)((work[3] & 0xc0) >> 2 | (work[4] & 0xc0) >> 4 | (work[5] & 0xc0) >> 6)];
            keytext[11] = table[(int)((work[6] & 0xc0) >> 2 | (work[7] & 0xc0) >> 4 | (work[8] & 0xc0) >> 6)];
        }

        public bool restore_date(int[] value, byte[] key, byte[] keytext)
        {
            byte[] work = new byte[12];
            int i, j;

            for (i = 0; i < 12; i++)
                for (j = 0; j < 64; j++)
                    if (table[j] == keytext[i])
                    {
                        work[i] = (byte)j;
                        break;
                    }

            work[0] |= (byte)((work[9] & 0x30) << 2);
            work[1] |= (byte)((work[9] & 0x0c) << 4);
            work[2] |= (byte)((work[9] & 0x03) << 6);
            work[3] |= (byte)((work[10] & 0x30) << 2);
            work[4] |= (byte)((work[10] & 0x0c) << 4);
            work[5] |= (byte)((work[10] & 0x03) << 6);
            work[6] |= (byte)((work[11] & 0x30) << 2);
            work[7] |= (byte)((work[11] & 0x0c) << 4);
            work[8] |= (byte)((work[11] & 0x03) << 6);

            if (work[6] != (byte)((work[0] ^ work[1])))
            {
                value[0] = -98;
                return false;
            }
            if (work[7] != (byte)((work[2] ^ work[3])))
            {
                value[0] = -97;
                return false;
            }
            if (work[8] != (byte)((work[4] ^ work[5])))
            {
                value[0] = -96;
                return false;
            }
            else
            {
                for (i = 0; i < 6; i++) work[i] ^= key[i];
                if ((work[4] != (byte)(work[0] ^ work[1])) || (work[5] != (byte)(work[2] ^ work[3])))
                {
                    value[0] = -95;
                    return false;
                }
                else
                {
                    value[0] = ((int)work[3]) << 8 | work[2];
                }
                return true;
            }
        }
    }
}
