Ejemplo n.º 1
0
            private static void SetupSalt(uint salt, ref CryptExtendedData data)
            {
                if (salt == data.oldSalt)
                {
                    return;
                }
                data.oldSalt = salt;

                uint saltbits = 0;
                uint saltbit  = 1;
                uint obit     = 0x800000;

                for (byte i = 0; i < 24; i++)
                {
                    if ((salt & saltbit) != 0)
                    {
                        saltbits |= obit;
                    }
                    saltbit <<= 1;
                    obit    >>= 1;
                }
                data.saltbits = saltbits;
            }
Ejemplo n.º 2
0
            public static string Crypt(string password, string setting)
            {
                lock (init_lock)
                {
                    if (!initialized)
                    {
                        Init();
                        initialized = true;
                    }
                }
                CryptExtendedData data = new CryptExtendedData();

                data.Init();

                int keyIndex = 0;

                byte[] keyBuffer = new byte[8];

                for (int i = 0; i < 8; i++)
                {
                    keyBuffer[i] |= (byte)(password[keyIndex] << 1);
                    if (password[keyIndex] != 0)
                    {
                        keyIndex++;
                    }
                }

                if (SetKey(keyBuffer, ref data) != 0)
                {
                    return(null);
                }

                uint salt        = 0;
                uint count       = 0;
                int  outputIndex = 0;

                if (setting[0] == passwordEFMT1)
                {
                    /* "new"-style:
                     *	setting - underscore, 4 chars of count, 4 chars of salt
                     *	key - unlimited characters */
                    for (int i = 1; i < 5; i++)
                    {
                        int value = ConvertASCIIToBin(setting[i]);
                        if (ascii64[value] != setting[i])
                        {
                            return(null);
                        }
                        count |= (uint)value << (i - 1) * 6;
                    }

                    if (count == 0)
                    {
                        return(null);
                    }

                    for (byte i = 5; i < 9; i++)
                    {
                        int value = ConvertASCIIToBin(setting[i]);
                        if (ascii64[value] != setting[i])
                        {
                            return(null);
                        }
                        salt |= (uint)(value << (i - 5) * 6);
                    }

                    while (password.Length > keyIndex)
                    {
                        // Encrypt the key with itself.
                        if (Cipher(keyBuffer, keyBuffer, 0, 1, ref data) != 0)
                        {
                            return(null);
                        }

                        // And XOR with the next 8 characters of the key.
                        for (int i = 0; i < 8 && password.Length > keyIndex; i++)
                        {
                            keyBuffer[i] ^= (byte)(password[keyIndex++] << 1);
                        }

                        if (SetKey(keyBuffer, ref data) != 0)
                        {
                            return(null);
                        }
                    }

                    for (int i = 0; i < 9; i++)
                    {
                        data.output[i] = (byte)setting[i];
                    }

                    data.output[9] = 0;
                    outputIndex    = 9;
                }
                else
                {
                    /* "old"-style:
                     *	setting - 2 chars of salt
                     *	key - up to 8 characters */
                    count = 25;

                    if (IsASCIIUnsafe(setting[0]) || IsASCIIUnsafe(setting[1]))
                    {
                        return(null);
                    }

                    salt = (uint)((ConvertASCIIToBin(setting[1]) << 6) | ConvertASCIIToBin(setting[0]));

                    data.output[0] = (byte)setting[0];
                    data.output[1] = (byte)setting[1];
                    outputIndex    = 2;
                }

                SetupSalt(salt, ref data);

                // Do it.
                uint l, r0 = 0, r1 = 0;

                if (DoDes(0, 0, ref r0, ref r1, (int)count, ref data) != 0)
                {
                    return(null);
                }

                // Now encode the result...

                l = (r0 >> 8);
                data.output[outputIndex++] = (byte)ascii64[(int)(l >> 18) & 0x3f];
                data.output[outputIndex++] = (byte)ascii64[(int)(l >> 12) & 0x3f];
                data.output[outputIndex++] = (byte)ascii64[(int)(l >> 6) & 0x3f];
                data.output[outputIndex++] = (byte)ascii64[(int)l & 0x3f];

                l = (r0 << 16) | ((r1 >> 16) & 0xffff);
                data.output[outputIndex++] = (byte)ascii64[(int)(l >> 18) & 0x3f];
                data.output[outputIndex++] = (byte)ascii64[(int)(l >> 12) & 0x3f];
                data.output[outputIndex++] = (byte)ascii64[(int)(l >> 6) & 0x3f];
                data.output[outputIndex++] = (byte)ascii64[(int)(l & 0x3f)];

                l = r1 << 2;
                data.output[outputIndex++] = (byte)ascii64[(int)(l >> 12) & 0x3f];
                data.output[outputIndex++] = (byte)ascii64[(int)(l >> 6) & 0x3f];
                data.output[outputIndex++] = (byte)ascii64[(int)l & 0x3f];
                data.output[outputIndex]   = 0;

                return(Encoding.ASCII.GetString(data.output).Trim('\0'));
            }
Ejemplo n.º 3
0
            private static int Cipher(byte[] inBuffer, byte[] outBuffer, uint salt, int count, ref CryptExtendedData data)
            {
                uint leftOut  = 0;
                uint rightOut = 0;

                SetupSalt(salt, ref data);

                uint rawLeft = (uint)(byte)inBuffer[3] |
                               ((uint)(byte)inBuffer[2] << 8) |
                               ((uint)(byte)inBuffer[1] << 16) |
                               ((uint)(byte)inBuffer[0] << 24);

                uint rawRight = (uint)(byte)inBuffer[7] |
                                ((uint)(byte)inBuffer[6] << 8) |
                                ((uint)(byte)inBuffer[5] << 16) |
                                ((uint)(byte)inBuffer[4] << 24);

                int result = DoDes(rawLeft, rawRight, ref leftOut, ref rightOut, count, ref data);

                outBuffer[0] = (byte)(leftOut >> 24);
                outBuffer[1] = (byte)(leftOut >> 16);
                outBuffer[2] = (byte)(leftOut >> 8);
                outBuffer[3] = (byte)leftOut;
                outBuffer[4] = (byte)(rightOut >> 24);
                outBuffer[5] = (byte)(rightOut >> 16);
                outBuffer[6] = (byte)(rightOut >> 8);
                outBuffer[7] = (byte)rightOut;

                return(result);
            }
Ejemplo n.º 4
0
            private static int DoDes(uint l_in, uint r_in, ref uint l_out, ref uint r_out, int count, ref CryptExtendedData data)
            {
                // l_in, r_in, l_out, and r_out are in pseudo - "big-endian" format.
                uint[] kl1, kr1;

                if (count == 0)
                {
                    return(1);
                }
                else if (count > 0)
                {
                    // Encrypting
                    kl1 = data.encryptKeysL;
                    kr1 = data.encryptKeysR;
                }
                else
                {
                    // Decrypting
                    count = -count;
                    kl1   = data.decryptKeysL;
                    kr1   = data.decryptKeysR;
                }

                // Do initial permutation (IP).
                uint l = ip_maskl[0, l_in >> 24]
                         | ip_maskl[1, (l_in >> 16) & 0xff]
                         | ip_maskl[2, (l_in >> 8) & 0xff]
                         | ip_maskl[3, l_in & 0xff]
                         | ip_maskl[4, r_in >> 24]
                         | ip_maskl[5, (r_in >> 16) & 0xff]
                         | ip_maskl[6, (r_in >> 8) & 0xff]
                         | ip_maskl[7, r_in & 0xff];
                uint r = ip_maskr[0, l_in >> 24]
                         | ip_maskr[1, (l_in >> 16) & 0xff]
                         | ip_maskr[2, (l_in >> 8) & 0xff]
                         | ip_maskr[3, l_in & 0xff]
                         | ip_maskr[4, r_in >> 24]
                         | ip_maskr[5, (r_in >> 16) & 0xff]
                         | ip_maskr[6, (r_in >> 8) & 0xff]
                         | ip_maskr[7, r_in & 0xff];

                uint saltbits = data.saltbits;

                while (count-- != 0)
                {
                    uint f = 0;
                    // Do each round.
                    int klIndex = 0;
                    int krIndex = 0;
                    int round   = 16;
                    while (round-- != 0)
                    {
                        // Expand R to 48 bits (simulate the E-box).
                        uint r48l = ((r & 0x00000001) << 23)
                                    | ((r & 0xf8000000) >> 9)
                                    | ((r & 0x1f800000) >> 11)
                                    | ((r & 0x01f80000) >> 13)
                                    | ((r & 0x001f8000) >> 15);

                        uint r48r = ((r & 0x0001f800) << 7)
                                    | ((r & 0x00001f80) << 5)
                                    | ((r & 0x000001f8) << 3)
                                    | ((r & 0x0000001f) << 1)
                                    | ((r & 0x80000000) >> 31);

                        /* Do salting for crypt() and friends, and
                         * XOR with the permuted key. */

                        f     = (r48l ^ r48r) & saltbits;
                        r48l ^= f ^ kl1[klIndex++];
                        r48r ^= f ^ kr1[krIndex++];

                        /* Do sbox lookups (which shrink it back to 32 bits)
                         * and do the pbox permutation at the same time. */

                        f = psbox[0, m_sbox[0, r48l >> 12]]
                            | psbox[1, m_sbox[1, r48l & 0xfff]]
                            | psbox[2, m_sbox[2, r48r >> 12]]
                            | psbox[3, m_sbox[3, r48r & 0xfff]];

                        // Now that we've permuted things, complete f().
                        f ^= l;
                        l  = r;
                        r  = f;
                    }
                    r = l;
                    l = f;
                }
                // Do final permutation (inverse of IP).

                l_out = fp_maskl[0, l >> 24]
                        | fp_maskl[1, (l >> 16) & 0xff]
                        | fp_maskl[2, (l >> 8) & 0xff]
                        | fp_maskl[3, l & 0xff]
                        | fp_maskl[4, r >> 24]
                        | fp_maskl[5, (r >> 16) & 0xff]
                        | fp_maskl[6, (r >> 8) & 0xff]
                        | fp_maskl[7, r & 0xff];
                r_out = fp_maskr[0, l >> 24]
                        | fp_maskr[1, (l >> 16) & 0xff]
                        | fp_maskr[2, (l >> 8) & 0xff]
                        | fp_maskr[3, l & 0xff]
                        | fp_maskr[4, r >> 24]
                        | fp_maskr[5, (r >> 16) & 0xff]
                        | fp_maskr[6, (r >> 8) & 0xff]
                        | fp_maskr[7, r & 0xff];

                return(0);
            }
Ejemplo n.º 5
0
            private static int SetKey(byte[] password, ref CryptExtendedData data)
            {
                uint rawKey0, rawKey1;

                rawKey0 =
                    (uint)(byte)password[3] |
                    ((uint)(byte)password[2] << 8) |
                    ((uint)(byte)password[1] << 16) |
                    ((uint)(byte)password[0] << 24);
                rawKey1 =
                    (uint)(byte)password[7] |
                    ((uint)(byte)password[6] << 8) |
                    ((uint)(byte)password[5] << 16) |
                    ((uint)(byte)password[4] << 24);

                if ((rawKey0 | rawKey1) != 0 && rawKey0 == data.oldRawKey0 && rawKey1 == data.oldRawKey1)
                {
                    /* Already setup for this key.
                     * This optimisation fails on a zero key (which is weak and
                     * has bad parity anyway) in order to simplify the starting
                     * conditions. */
                    return(0);
                }
                data.oldRawKey0 = rawKey0;
                data.oldRawKey1 = rawKey1;

                // Do key permutation and split into two 28-bit subkeys.
                uint key0 = key_perm_maskl[0, rawKey0 >> 25]
                            | key_perm_maskl[1, (rawKey0 >> 17) & 0x7f]
                            | key_perm_maskl[2, (rawKey0 >> 9) & 0x7f]
                            | key_perm_maskl[3, (rawKey0 >> 1) & 0x7f]
                            | key_perm_maskl[4, rawKey1 >> 25]
                            | key_perm_maskl[5, (rawKey1 >> 17) & 0x7f]
                            | key_perm_maskl[6, (rawKey1 >> 9) & 0x7f]
                            | key_perm_maskl[7, (rawKey1 >> 1) & 0x7f];
                uint key1 = key_perm_maskr[0, rawKey0 >> 25]
                            | key_perm_maskr[1, (rawKey0 >> 17) & 0x7f]
                            | key_perm_maskr[2, (rawKey0 >> 9) & 0x7f]
                            | key_perm_maskr[3, (rawKey0 >> 1) & 0x7f]
                            | key_perm_maskr[4, rawKey1 >> 25]
                            | key_perm_maskr[5, (rawKey1 >> 17) & 0x7f]
                            | key_perm_maskr[6, (rawKey1 >> 9) & 0x7f]
                            | key_perm_maskr[7, (rawKey1 >> 1) & 0x7f];

                // Rotate subkeys and do compression permutation.
                int shifts = 0;

                for (int round = 0; round < 16; round++)
                {
                    shifts += key_shifts[round];

                    uint t0 = (key0 << shifts) | (key0 >> (28 - shifts));
                    uint t1 = (key1 << shifts) | (key1 >> (28 - shifts));

                    data.decryptKeysL[15 - round] =
                        data.encryptKeysL[round]  = comp_maskl[0, (t0 >> 21) & 0x7f]
                                                    | comp_maskl[1, (t0 >> 14) & 0x7f]
                                                    | comp_maskl[2, (t0 >> 7) & 0x7f]
                                                    | comp_maskl[3, t0 & 0x7f]
                                                    | comp_maskl[4, (t1 >> 21) & 0x7f]
                                                    | comp_maskl[5, (t1 >> 14) & 0x7f]
                                                    | comp_maskl[6, (t1 >> 7) & 0x7f]
                                                    | comp_maskl[7, t1 & 0x7f];

                    data.decryptKeysR[15 - round] =
                        data.encryptKeysR[round]  = comp_maskr[0, (t0 >> 21) & 0x7f]
                                                    | comp_maskr[1, (t0 >> 14) & 0x7f]
                                                    | comp_maskr[2, (t0 >> 7) & 0x7f]
                                                    | comp_maskr[3, t0 & 0x7f]
                                                    | comp_maskr[4, (t1 >> 21) & 0x7f]
                                                    | comp_maskr[5, (t1 >> 14) & 0x7f]
                                                    | comp_maskr[6, (t1 >> 7) & 0x7f]
                                                    | comp_maskr[7, t1 & 0x7f];
                }
                return(0);
            }