Untitled

 avatar
unknown
csharp
2 years ago
2.5 kB
4
Indexable
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System.Text;

public static class Rec1
    {
        private const byte TWOFISH_BLOCK_SIZE = 0x10;
        private const byte TWOFISH_KEY_SIZE = 2 * TWOFISH_BLOCK_SIZE;
        private const byte TWOFISH_NONCE_SIZE = TWOFISH_BLOCK_SIZE;

        private const byte KEY_CONSTANT = 0x17;
        private const byte IV_CONSTANT = 0xB6;

        public static byte[] Encode(ushort sid, string username, string clientKey, uint timeSecs, uint timeMillis)
        {
            byte[] record = Encoding.UTF8.GetBytes($"{sid} {username} {clientKey}");

            byte[] key = DeriveTwofishKey(sid, timeSecs, timeMillis);
            byte[] nonce = DeriveTwofishNonce();

            IBufferedCipher cipher = CipherUtilities.GetCipher("Twofish/OFB/NoPadding");
            cipher.Init(true, new ParametersWithIV(new KeyParameter(key), nonce));
            return cipher.DoFinal(record);
        }

        public static byte[] Decode(byte[] encodedData, ushort sid, uint timeSecs, uint timeMillis)
        {
            byte[] key = DeriveTwofishKey(sid, timeSecs, timeMillis);
            byte[] nonce = DeriveTwofishNonce();

            IBufferedCipher cipher = CipherUtilities.GetCipher("Twofish/OFB/NoPadding");
            cipher.Init(false, new ParametersWithIV(new KeyParameter(key), nonce));
            return cipher.DoFinal(encodedData);
        }

        private static byte[] DeriveTwofishKey(ushort sessionID, uint timeSecs, uint timeMillis)
        {
            byte[] key = new byte[TWOFISH_KEY_SIZE];

            for (int i = 0; i < key.Length; i++)
            {
                key[i] = (byte)(KEY_CONSTANT + i);
            }

            key[4]  = (byte)(sessionID & 0xff);
            key[5]  = 0;
            key[6]  = (byte)((sessionID >> 8) & 0xff);

            key[8]  = (byte)(timeSecs & 0xff);
            key[9]  = (byte)((timeSecs >> 16) & 0xff);
            key[12] = (byte)((timeSecs >> 8)  & 0xff);
            key[13] = (byte)((timeSecs >> 24) & 0xff);

            key[14] = (byte)(timeMillis & 0xff);
            key[15] = (byte)((timeMillis >> 8) & 0xff);

            return key;
        }

        private static byte[] DeriveTwofishNonce()
        {
            var iv = new byte[TWOFISH_NONCE_SIZE];

            for (int i = 0; i < iv.Length; i++)
            {
                iv[i] = (byte)(IV_CONSTANT - i);
            }

            return iv;
        }
    }