SQF到C# - 加密代码转换

时间:2016-08-06 14:31:02

标签: c# encryption sqf

天儿真好。我试图将最初为Bohemia Interactives语言SQF制作的函数转换为C#。该脚本旨在使用加密方法RC4加密字符串,但是,由于arma3引擎的限制,它与传统方式的工作方式略有不同。这样做的全部意义是我可以使用C#程序加密字符串,并通过游戏中的Arma 3解密。

以下是我要转换的代码。

    /*
        Function: ALiVE_fnc_crypt
        Author(s): Naught
        Version: 1.0
        Description:
                Encrypts or decrypts a string with a specified encryption key.
        Parameters:
                0 - Decrypt (0) or encrypt (1) [number]
                1 - Encryption method name [string]
                2 - Encrypted or plain data [string]
                3 - Encryption key [string]
        Returns:
                Encrypted or decrypted data or nothing on failure [string:nil]
        Note(s):
                1. Current encryption method names:
                        - "rc4" // Rivest Cipher 4 Stream Encryption Algorithm

*/
// Constants
MAX_CHAR_SIZE = 8;
CHAR_ZERO_REP = 256;

private ["_method", "_key"];
_encText = _this select 0;
_key = _this select 1;


private ["_fnc_intToBin"];
_fnc_intToBin = {
        private ["_int", "_bin", "_pwr", "_bool"];
        _int = _this select 0;
        _bin = if ((count _this) > 1) then {_this select 1} else {[]};

        for "_i" from (MAX_CHAR_SIZE - 1) to 0 step (-1) do
        {
                _pwr = 2^(_i);
                _bool = _pwr <= _int;

                _bin set [(count _bin), _bool];

                if (_bool) then {_int = _int - _pwr};
        };

        _bin
};

private ["_bin"];
_bin = [];

// Convert string to UTF-8 binary
{ // count (faster than forEach)
        [(if (_x == CHAR_ZERO_REP) then {0} else {_x}), _bin] call _fnc_intToBin;
        false;
} count toArray(_encText);
systemChat str _bin;

// Encrypt & decrypt methods
_key = toArray(_key);

private ["_keyLen", "_state", "_temp", "_j"];
_keyLen = count _key;
_state = [];
_temp = 0;
_j = 0;

// Key-Scheduling Algorithm
for "_i" from 0 to 255 do {_state set [_i,_i]};
for "_i" from 0 to 255 do
{
        _temp = _state select _i;

        _j = (_j + _temp + (_key select (_i mod _keyLen))) mod 256;

        _state set [_i, (_state select _j)];
        _state set [_j, _temp];
};


private ["_temp1", "_temp2", "_rand", "_i", "_mod", "_rbit"];
_temp1 = 0;
_temp2 = 0;
_rand = [];
_i = 0;
_j = 0;
hint str _bin;
// Pseudo-Random Generation Algorithm
{
        _mod = _forEachIndex % MAX_CHAR_SIZE;

        if (_mod == 0) then
        {
                _i = (_i + 1) mod 256;
                _j = (_j + (_state select _i)) mod 256;

                _temp1 = _state select _i;
                _temp2 = _state select _j;

                _state set [_i, _temp2];
                _state set [_j, _temp1];

                _rand = [(_state select ((_temp1 + _temp2) mod 256))] call _fnc_intToBin;
        };

        _rbit = _rand select _mod;
        _bin set [_forEachIndex, (_x && !_rbit) || {!_x && _rbit}]; // XOR

} forEach _bin;

private ["_dec", "_buf", "_mod"];
_dec = 0;
_buf = [];

// Convert binary array to UTF-8 string
{
        _mod = _forEachIndex % MAX_CHAR_SIZE;

        if (_x) then {_dec = _dec + 2^((MAX_CHAR_SIZE - 1) - _mod)};

        if (_mod == 7) then
        {
                if (_dec == 0) then {_dec = CHAR_ZERO_REP};
                _buf set [(count _buf), _dec];
                _dec = 0;
        };
} forEach _bin;


toString(_buf)

我对这段代码做了一些调整,但在Arma 3中它仍能正常工作。

现在,转换后的功能。我已经更改了此代码中的所有内容,从我的初始代码尝试并使其工作,所以在这一点上,它可能完全不正确,但是,无论如何,我将包括它。

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

namespace encrypt
{
    class Program
    {
        static public int MAX_CHAR_SIZE = 8;
        static public int CHAR_ZERO_REP = 256;
        static public int _keyLen;

        static void Main()
        {
            string[] args = new string[2];
            args[0] = "Some Random Code";
            args[1] = "4tuIc9tai";

            string text = args[0];

            // Convert the text to an array of decimal unicode || Same as toArray in arma 3
            string[] txtArray = new string[text.Length];
            txtArray = text.ToCharArray().Select(c => c.ToString()).ToArray();
            int[] utf = getUni(txtArray);

            // Convert the key to an array of decimal unicode || Same as toArray in arma 3
            string[] keyArray = new string[args[1].Length];
            keyArray = args[1].ToCharArray().Select(c => c.ToString()).ToArray();
            int[] key = getUni(keyArray);

            // Debug the output
            //foreach (int i in utf){Console.Write(i); Console.Write(",");} Console.WriteLine();foreach (int i in key){Console.Write(i);Console.Write(","); }

            // Convert string to UTF-8 binary
            Dictionary<int, bool> _bin = new Dictionary<int, bool>();
            foreach (int i in utf)
            {
                int _num;
                if (i == CHAR_ZERO_REP)
                {
                     _num = 0;
                }
                else
                {
                    _num = i;
                }
                _bin = intToBin(_num, _bin);
            }

            foreach (KeyValuePair<int, bool> i in _bin)
            {
                Console.Write(Convert.ToString(i.Value));
                Console.Write(", ");
            }

            // Encrypt & decrypt methods
            _keyLen = key.Length;
            int[] _state = new int[1024];
            int _temp = 0;
            int _j = 0;

            // Key-Scheduling Algorithm
            for (int _i = 0; _i < 255; _i++)
            {
                _state.SetValue(_i, _i);
            }

            for (int _i = 0; _i < 255; _i++)
            {
                _temp = _state[_i];

                _j = (_j + _temp + key[_i % _keyLen]) % 256;

                _state.SetValue(_i, _state[_j]);
                _state.SetValue(_j, _temp);
            }



            // Pseudo-Random Generation Algorithm

            int _temp1 = 0;
            int _temp2 = 0;
            Dictionary<int, bool> _rand = new Dictionary<int, bool>();
            int __i = 0;
            int __j = 0;
            int indx = 0;

            for (int i = 0; i < _bin.Count-1; i++)
            {
                int _mod = indx % MAX_CHAR_SIZE;

                if (_mod == 0)
                {

                    __i = (__i + 1) % 256;
                    __j = (__j + _state[__i]) % 256;

                    _temp1 = _state[__i];
                    _temp2 = _state[__j];

                    _state.SetValue(__i, _temp2);
                    _state.SetValue(__j, _temp1);

                    _rand = intToBin(_state[_temp1 + _temp2] % 256, _rand);
                }

                bool _rbit = _rand[_mod];
                bool _bit = _bin[i];
                if (_bin.ContainsKey(indx))
                {
                    _bin.Remove(indx);
                }
                _bin.Add(indx, (_bit && !_rbit) || (!_bit && _rbit));

                indx++;
            }

            // Convert binary array to UTF-8 string
            int _dec = 0;
            int[] _buf = new int[_bin.Count];

            for (int i = 0; i < _bin.Count-1; i++)
            {
                int _mod = i % MAX_CHAR_SIZE;
                Console.WriteLine(i);
                if (_bin[i])
                {
                    _dec = _dec + 2 ^ ((MAX_CHAR_SIZE - 1) - _mod);
                }

                if (_mod == 7)
                {
                    if (_dec == 0)
                    {
                        _dec = CHAR_ZERO_REP;
                    }
                    _buf.SetValue(_dec, _buf.Length-1);
                    _dec = 0;
                }

                _buf.SetValue(_dec, _buf.Length - 1);
            }

            Console.ReadLine();
        }

        static int[] getUni(string[] txtArray)
        {
            int[] ret = new int[txtArray.Length];
            int idx = 0;

            foreach (string i in txtArray)
            {
                ret.SetValue(Encoding.UTF8.GetBytes(i)[0], idx);
                idx++;
            }
            return ret;
        }

        static Dictionary<int, bool> intToBin(int val, Dictionary<int, bool> bin)
        {
            for (int i = MAX_CHAR_SIZE-1; i > 0; i--)
            {
                int _pwr = 2 ^ i;
                bool _bool = _pwr <= val;

                int cc = bin.Count;

                if (bin.ContainsKey(cc))
                {
                    bin.Remove(cc);
                }
                bin.Add(cc, _bool);

                if (_bool)
                {
                    val = val - _pwr;
                }
            }
            return bin;
        }


    }
}

任何有用的帮助都会很棒:)

0 个答案:

没有答案