Ejemplo n.º 1
0
        /// <summary>
        /// Encrypts the <see cref="Data"/> according to the <see cref="Type"/> and <see cref="SubType"/>.
        /// </summary>
        public void WriteBlock(BinaryWriter bw)
        {
            var xk = new SCXorShift32(Key);

            bw.Write(Key);
            bw.Write((byte)((byte)Type ^ xk.Next()));

            if (Type == SCTypeCode.Object)
            {
                bw.Write((uint)Data.Length ^ xk.Next32());
            }
            else if (Type == SCTypeCode.Array)
            {
                var entries = (uint)(Data.Length / SubType.GetTypeSize());
                bw.Write(entries ^ xk.Next32());
                bw.Write((byte)((byte)SubType ^ xk.Next()));
            }

            foreach (var b in Data)
            {
                bw.Write((byte)(b ^ xk.Next()));
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Reads a new <see cref="SCBlock"/> object from the <see cref="data"/>, determining the <see cref="Type"/> and <see cref="SubType"/> during read.
        /// </summary>
        /// <param name="data">Decrypted data</param>
        /// <param name="offset">Offset the block is to be read from (modified to offset by the amount of bytes consumed).</param>
        /// <returns>New object containing all info for the block.</returns>
        public static SCBlock ReadFromOffset(byte[] data, ref int offset)
        {
            // Create block, parse its key.
            var key = BitConverter.ToUInt32(data, offset);

            offset += 4;
            var xk = new SCXorShift32(key);

            // Parse the block's type
            //var block =
            var type = (SCTypeCode)(data[offset++] ^ xk.Next());

            switch (type)
            {
            case SCTypeCode.Bool1:
            case SCTypeCode.Bool2:
            case SCTypeCode.Bool3:
                // Block types are empty, and have no extra data.
                Debug.Assert(type != SCTypeCode.Bool3);     // invalid type, haven't seen it used yet
                return(new SCBlock(key, type));

            case SCTypeCode.Object:     // Cast raw bytes to Object
            {
                var num_bytes = BitConverter.ToUInt32(data, offset) ^ xk.Next32();
                offset += 4;
                var arr = new byte[num_bytes];
                for (int i = 0; i < arr.Length; i++)
                {
                    arr[i] = (byte)(data[offset++] ^ xk.Next());
                }

                return(new SCBlock(key, type, arr));
            }

            case SCTypeCode.Array:     // Cast raw bytes to SubType[]
            {
                var num_entries = BitConverter.ToUInt32(data, offset) ^ xk.Next32();
                offset += 4;
                var sub = (SCTypeCode)(data[offset++] ^ xk.Next());

                var num_bytes = num_entries * sub.GetTypeSize();
                var arr       = new byte[num_bytes];
                for (int i = 0; i < arr.Length; i++)
                {
                    arr[i] = (byte)(data[offset++] ^ xk.Next());
                }
#if DEBUG
                Debug.Assert(sub > SCTypeCode.Array || Array.TrueForAll(arr, z => z <= 1));
#endif
                return(new SCBlock(key, arr, sub));
            }

            default:     // Single Value Storage
            {
                var num_bytes = type.GetTypeSize();
                var arr       = new byte[num_bytes];
                for (int i = 0; i < arr.Length; i++)
                {
                    arr[i] = (byte)(data[offset++] ^ xk.Next());
                }
                return(new SCBlock(key, type, arr));
            }
            }
        }