Example #1
0
        /// <summary>
        /// Converts a password into mail information.
        /// </summary>
        /// <param name="password">The password to convert.</param>
        /// <returns>Mail information from the password.</returns>
        public static WonderSMail Convert(string password)
        {
            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentNullException(nameof(password));
            }

            // Sanitaze and check password
            password = password.Replace(" ", "");
            password = password.Replace("\t", "");
            password = password.Replace(Environment.NewLine, "");
            password = password.ToUpper();
            if (password.Length != PasswordLength)
            {
                throw new ArgumentException("Invalid password length");
            }

            // Do decryption rounds
            // The last byte for "scramble" is ignored. It should be the null
            // terminator 0x00.
            password = Permutation.Decrypt(password, false);
            byte[] binary = Substitution.Decrypt(password);
            Scramble.Decrypt(binary[0], binary, 4, binary.Length - 5);

            // Validate checksum
            uint crc32    = BitConverter.ToUInt32(binary, 0);
            uint newCrc32 = Crc32.Calculate(binary, 4, binary.Length - 5);

            if (crc32 != newCrc32)
            {
                throw new FormatException("Invalid crc32");
            }

            // Convert the binary password into the structure.
            // Write the array into a stream to use the BitReader.
            DataStream stream = new DataStream();

            stream.Write(binary, 4, binary.Length - 4);
            BitReader reader = new BitReader(stream);

            WonderSMail info = new WonderSMail();

            info.MailType           = reader.ReadByte(4);
            info.MissionType        = reader.ReadByte(4);
            info.MissionSubType     = reader.ReadByte(4);
            info.SourceClientId     = reader.ReadUInt16(11);
            info.TargetClientId     = reader.ReadUInt16(11);
            info.TargetClientFemale = reader.ReadUInt16(11);
            info.RewardObjectId     = reader.ReadUInt16(10);
            info.RewardType         = reader.ReadByte(4);
            info.RewardId           = reader.ReadUInt16(11);
            info.RestrictionType    = reader.ReadByte(1);
            info.RestrictionParam   = reader.ReadUInt16(11);
            info.Random             = reader.ReadUInt32(24);
            info.LocationId         = reader.ReadByte(8);
            info.FloorNumber        = reader.ReadByte(8);
            info.Requirement        = reader.ReadByte(8);

            return(info);
        }
Example #2
0
        /// <summary>
        /// Converts a missiong information into a password.
        /// </summary>
        /// <param name="info">Mission to convert.</param>
        /// <returns>The password.</returns>
        public static string Convert(WonderSMail info)
        {
            if (info == null)
            {
                throw new ArgumentNullException(nameof(info));
            }

            // Serialize the structure into a bit stream
            DataStream stream = new DataStream();
            BitWriter  writer = new BitWriter(stream);

            writer.Write(info.MailType, 4);
            writer.Write(info.MissionType, 4);
            writer.Write(info.MissionSubType, 4);
            writer.Write(info.SourceClientId, 11);
            writer.Write(info.TargetClientId, 11);
            writer.Write(info.TargetClientFemale, 11);
            writer.Write(info.RewardObjectId, 10);
            writer.Write(info.RewardType, 4);
            writer.Write(info.RewardId, 11);
            writer.Write(info.RestrictionType, 1);
            writer.Write(info.RestrictionParam, 11);
            writer.Write(info.Random, 24);
            writer.Write(info.LocationId, 8);
            writer.Write(info.FloorNumber, 8);
            writer.Write(info.Requirement, 8);

            // Write the stream into an array for the rounds.
            // We allocate an extra space for the checksum (first uint)
            // and the null terminator (last byte).
            byte[] binary = new byte[stream.Length + 5];
            stream.Position = 0;
            stream.Read(binary, 4, (int)stream.Length);

            // Create checksum
            uint crc32 = Crc32.Calculate(binary, 4, binary.Length - 5);

            byte[] crc32Bytes = BitConverter.GetBytes(crc32);
            binary[0] = crc32Bytes[0];
            binary[1] = crc32Bytes[1];
            binary[2] = crc32Bytes[2];
            binary[3] = crc32Bytes[3];

            // Do encryption rounds
            // The key is the checksum, we don't encrypt the null terminator.
            Scramble.Encrypt(crc32Bytes[0], binary, 4, binary.Length - 5);
            string password = Substitution.Encrypt(binary, PasswordLength);

            password = Permutation.Encrypt(password, false);

            return(password);
        }