예제 #1
0
        /// Last Modified: 10/18/10
        /// <summary>
        /// A static method that decrypts a byte array based on the scheme & passphrase provided.
        /// </summary>
        /// -----------------------------------------------------
        /// PRECONDITIONS: Refer to the following arguments.
        /// -----------------------------------------------------
        /// <param name="passphrase">
        /// Is a 16-character word that is used as a key for decryption.
        /// </param>
        /// <param name="es">
        /// Determines the decryption type being used.
        /// </param>
        /// <param name="rawBytes">
        /// An array of raw bytes to decrypted.
        /// </param>
        /// <param name="byteCount">
        /// The byte count of the raw bytes.  This argument also contains the number of transformed bytes after transformation.
        /// </param>
        /// -----------------------------------------------------
        /// POSTCONDITIONS: Refer to the return statement.
        /// -----------------------------------------------------
        /// <returns>
        /// Returns a decrypted series of bytes based on the passphrase.
        /// </returns>
        public static byte[] PassphraseByteDecrypt(string passphrase, EncryptionScheme es, byte[] rawBytes, ref int byteCount)
        {
            MemoryStream mStream = null;
            CryptoStream readerStream = null;

            try
            {
                //Make sure the passphrase is exactly 16-characters.
                passphrase = PreparePassphrase(passphrase);

                //Instantiate the memory stream with the bytes of the encrypted message.
                mStream = new MemoryStream(rawBytes, 0, byteCount);

                //Create the stream for decryption.
                readerStream = new CryptoStream(mStream,
                    GetCryptoTransform(EncryptionScheme.AES, false, passphrase, passphrase),
                    CryptoStreamMode.Read);

                //Obtain the transformed bytes.
                byte[] transformedBytes = new byte[byteCount];
                byteCount = readerStream.Read(transformedBytes, 0, byteCount);

                //Return the series of bytes.
                return transformedBytes;
            }
            finally
            {
                //Cleanup.
                mStream.Close();
                readerStream.Close();
            }
        }
        public void Deserialize(Stream input)
        {
            var basePosition = input.Position;

            // read as two unsigned longs so we don't have to actually
            // decode the strings
            var version1 = input.ReadValueU64(false);
            var version2 = input.ReadValueU64(false);

            if (version1 == 0x4552462056322E31) // ERF V2.1
            {
                input.Seek(basePosition + 8, SeekOrigin.Begin);
                throw new NotSupportedException();
            }
            else if (version1 == 0x4500520046002000 &&
                version2 == 0x560032002E003000) // ERF V2.0
            {
                input.Seek(basePosition + 16, SeekOrigin.Begin);
                this.Version = 1;

                var fileCount = input.ReadValueU32();
                var unknown14 = input.ReadValueU32();
                var unknown18 = input.ReadValueU32();
                var unknown1C = input.ReadValueU32();

                this.Flags = 0;
                this.Encryption = EncryptionScheme.None;
                this.Compression = CompressionScheme.None;
                this.ContentId = 0;
                this.PasswordDigest = null;

                this.Entries.Clear();
                for (uint i = 0; i < fileCount; i++)
                {
                    var entry = new Entry();

                    entry.Name = input.ReadString(64, true, Encoding.Unicode);
                    entry.CalculateHashes();
                    entry.Offset = input.ReadValueU32();
                    entry.UncompressedSize = input.ReadValueU32();
                    entry.CompressedSize = entry.UncompressedSize;

                    this.Entries.Add(entry);
                }
            }
            else if (version1 == 0x4500520046002000 &&
                version2 == 0x560032002E003200) // ERF V2.2
            {
                input.Seek(basePosition + 16, SeekOrigin.Begin);
                this.Version = 2;

                var fileCount = input.ReadValueU32();
                var year = input.ReadValueU32();
                var day = input.ReadValueU32();
                var unknown1C = input.ReadValueU32(); // always 0xFFFFFFFF?
                var flags = input.ReadValueU32();
                var contentId = input.ReadValueU32();
                var passwordDigest = new byte[16];
                input.Read(passwordDigest, 0, passwordDigest.Length);

                if (unknown1C != 0xFFFFFFFF)
                {
                    throw new InvalidOperationException();
                }

                this.Flags = (flags & 0x1FFFFF0F) >> 0;
                this.Encryption = (EncryptionScheme)((flags & 0x000000F0) >> 4);
                this.Compression = (CompressionScheme)((flags & 0xE0000000) >> 29);

                if (this.Flags != 0 && this.Flags != 1)
                {
                    throw new FormatException("unknown flags value");
                }

                this.ContentId = contentId;
                this.PasswordDigest = passwordDigest;

                this.Entries.Clear();
                for (uint i = 0; i < fileCount; i++)
                {
                    var entry = new Entry();

                    entry.Name = input.ReadString(64, true, Encoding.Unicode);
                    entry.CalculateHashes();
                    entry.Offset = input.ReadValueU32();
                    entry.CompressedSize = input.ReadValueU32();
                    entry.UncompressedSize = input.ReadValueU32();

                    this.Entries.Add(entry);
                }
            }
            else if (version1 == 0x4500520046002000 &&
                version2 == 0x560033002E003000) // ERF V3.0
            {
                input.Seek(basePosition + 16, SeekOrigin.Begin);
                this.Version = 3;

                var stringTableSize = input.ReadValueU32();
                var fileCount = input.ReadValueU32();
                var flags = input.ReadValueU32();
                var contentId = input.ReadValueU32();
                var passwordDigest = new byte[16];
                input.Read(passwordDigest, 0, passwordDigest.Length);

                this.Flags = (flags & 0x1FFFFF0F) >> 0;
                this.Encryption = (EncryptionScheme)((flags & 0x000000F0) >> 4);
                this.Compression = (CompressionScheme)((flags & 0xE0000000) >> 29);

                if (this.Flags != 0 && this.Flags != 1)
                {
                    throw new FormatException("unknown flags value");
                }

                this.ContentId = contentId;
                this.PasswordDigest = passwordDigest;

                MemoryStream stringTable = stringTableSize == 0 ?
                    null : input.ReadToMemoryStream(stringTableSize);

                this.Entries.Clear();
                for (uint i = 0; i < fileCount; i++)
                {
                    var entry = new Entry();

                    uint nameOffset = input.ReadValueU32();
                    entry.NameHash = input.ReadValueU64();

                    if (nameOffset != 0xFFFFFFFF)
                    {
                        if (nameOffset + 1 > stringTable.Length)
                        {
                            throw new FormatException("file name exceeds string table bounds");
                        }

                        stringTable.Position = nameOffset;
                        entry.Name = stringTable.ReadStringZ(Encoding.ASCII);

                        if (entry.Name.HashFNV64() != entry.NameHash)
                        {
                            throw new InvalidOperationException("hash mismatch");
                        }
                    }
                    else
                    {
                        entry.Name = null;
                    }

                    entry.TypeHash = input.ReadValueU32();
                    entry.Offset = input.ReadValueU32();
                    entry.CompressedSize = input.ReadValueU32();
                    entry.UncompressedSize = input.ReadValueU32();

                    this.Entries.Add(entry);
                }
            }
            else
            {
                throw new FormatException("unsupported / unknown ERF format");
            }
        }
예제 #3
0
        //-----------------------------------------------------------------------------
        // createEncDef
        //-----------------------------------------------------------------------------
        /// <summary>
        /// Creates a new prefix definition in the dictionary. 
        /// </summary>
        /// <param name="sEncName">
        /// Encryption definition name.
        /// </param>
        /// <param name="eEncType">
        /// Encryption type.
        /// </param>
        /// <param name="uiRequestedId">
        /// If non-zero, then XFLAIM will try to use this
        /// number as the name ID of the new definition.
        /// </param>
        /// <returns>
        /// Returns the name ID of the new definition.
        /// </returns>
        public uint createEncDef(
			string				sEncName,
			EncryptionScheme	eEncType,
			uint					uiRequestedId)
        {
            RCODE		rc;
            uint		uiKeySize = 128;
            string	sEncType = "aes";

            switch (eEncType)
            {
                case EncryptionScheme.ENC_AES128:
                    uiKeySize = 128;
                    sEncType = "aes";
                    break;
                case EncryptionScheme.ENC_AES192:
                    uiKeySize = 192;
                    sEncType = "aes";
                    break;
                case EncryptionScheme.ENC_AES256:
                    uiKeySize = 256;
                    sEncType = "aes";
                    break;
                case EncryptionScheme.ENC_DES3:
                    uiKeySize = 168;
                    sEncType = "des3";
                    break;
                default:
                    throw new XFlaimException( RCODE.NE_XFLM_INVALID_PARM);
            }

            if ((rc = xflaim_Db_createEncDef( m_pDb, sEncType, sEncName,
                uiKeySize, ref uiRequestedId)) != 0)
            {
                throw new XFlaimException(rc);
            }

            return( uiRequestedId);
        }
예제 #4
0
        /// Last Modified: 10/10/10
        /// <summary>
        /// Returns the appropriate ICryptoTransform object based on the encryption scheme, direction,
        ///  key, and initialization vector.
        /// </summary>
        /// -----------------------------------------------------
        /// PRECONDITIONS: Refer to the following arguments.
        /// -----------------------------------------------------
        /// <param name="es">
        /// Encryption scheme being requested.
        /// </param>
        /// <param name="isEncryption">
        /// True for encryption.  False for decryption.
        /// </param>
        /// <param name="key">
        /// A key in string form to use.
        /// NOTE: This value MUST be 16-characters long.
        /// </param>
        /// <param name="IV">
        /// An initialization vector in string form to use.
        /// NOTE: This value MUST be 16-characters long.
        /// </param>
        /// -----------------------------------------------------
        /// POSTCONDITIONS: Refer to the return statement.
        /// -----------------------------------------------------
        /// <returns>
        /// Returns a decrypts string based on the passphrase.
        /// </returns>
        private static ICryptoTransform GetCryptoTransform(EncryptionScheme es, bool isEncryption, string key, string IV)
        {
            if (key.Length != 16)
                throw new Exception("The key is an incorrect length and must be 16-characters long.");

            if (IV.Length != 16)
                throw new Exception("The IV is an incorrect length and must be 16-characters long.");

            ASCIIEncoding enc = new ASCIIEncoding();

            switch (es)
            {
                case EncryptionScheme.AES:
                    {
                        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
                        aes.KeySize = 128;
                        aes.Key = enc.GetBytes(key);
                        aes.IV = enc.GetBytes(IV);
                        return isEncryption ? aes.CreateEncryptor() : aes.CreateDecryptor();
                    }

                case EncryptionScheme.DES:
                    {
                        DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                        des.KeySize = 128;
                        des.Key = enc.GetBytes(key);
                        des.IV = enc.GetBytes(IV);
                        return isEncryption ? des.CreateEncryptor() : des.CreateDecryptor();
                    }
            }

            return null;
        }
예제 #5
0
 /// Last Modified: 10/12/10
 /// <summary>
 /// A static method that encrypts a msg based on the scheme & passphrase provided.
 /// </summary>
 /// -----------------------------------------------------
 /// PRECONDITIONS: Refer to the following arguments.
 /// -----------------------------------------------------
 /// <param name="passphrase">
 /// Is a 16-character word that is used as a key for encryption.
 /// </param>
 /// <param name="es">
 /// Determines the encryption type being used.
 /// </param>
 /// <param name="Msg">
 /// The string being encrypted.
 /// </param>
 /// -----------------------------------------------------
 /// POSTCONDITIONS: Refer to the return statement.
 /// -----------------------------------------------------
 /// <returns>
 /// Returns an encrypted string based on the passphrase.
 /// </returns>
 public static string PassphraseStrEncrypt(string passphrase, EncryptionScheme es, string Msg)
 {
     //Return the encrypted series of bytes as a string.
     return Convert.ToBase64String(PassphraseByteEncrypt(passphrase, es, Encoding.Default.GetBytes(Msg)));
 }
예제 #6
0
        /// Last Modified: 10/25/10
        /// <summary>
        /// A static method that decrypts a string based on the scheme & passphrase provided.
        /// </summary>
        /// -----------------------------------------------------
        /// PRECONDITIONS: Refer to the following arguments.
        /// -----------------------------------------------------
        /// <param name="passphrase">
        /// Is a 16-character word that is used as a key for decryption.
        /// </param>
        /// <param name="es">
        /// Determines the decryption type being used.
        /// </param>
        /// <param name="Msg">
        /// The string being decrypted.
        /// </param>
        /// -----------------------------------------------------
        /// POSTCONDITIONS: Refer to the return statement.
        /// -----------------------------------------------------
        /// <returns>
        /// Returns a decrypts string based on the passphrase.
        /// </returns>
        public static string PassphraseStrDecrypt(string passphrase, EncryptionScheme es, string Msg)
        {
            byte[] byRaw = Convert.FromBase64String(Msg);
            int byteCount = byRaw.Length;

            byte[] byTransformed = PassphraseByteDecrypt(passphrase, es, byRaw, ref byteCount);

            //Convert and return the series of bytes as a string.
            ASCIIEncoding enc = new ASCIIEncoding();
            return enc.GetString(byTransformed, 0, byteCount);
        }
예제 #7
0
        /// Last Modified: 10/10/10
        /// <summary>
        /// A static method that encrypts a byte array based on the scheme & passphrase provided.
        /// </summary>
        /// -----------------------------------------------------
        /// PRECONDITIONS: Refer to the following arguments.
        /// -----------------------------------------------------
        /// <param name="passphrase">
        /// Is a 16-character word that is used as a key for encryption.
        /// </param>
        /// <param name="es">
        /// Determines the encryption type being used.
        /// </param>
        /// <param name="rawBytes">
        /// An array of raw bytes to encryption.
        /// </param>
        /// -----------------------------------------------------
        /// POSTCONDITIONS: Refer to the return statement.
        /// -----------------------------------------------------
        /// <returns>
        /// Returns an encrypted series of bytes based on the passphrase.
        /// </returns>
        public static byte[] PassphraseByteEncrypt(string passphrase, EncryptionScheme es, byte[] rawBytes)
        {
            CryptoStream writerStream = null;
            MemoryStream mStream = null;

            try
            {

                //Make sure the passphrase is exactly 16-characters.
                passphrase = PreparePassphrase(passphrase);

                mStream = new MemoryStream();

                //Create the stream for encryption.
                writerStream = new CryptoStream(mStream,
                    GetCryptoTransform(EncryptionScheme.AES, true, passphrase, passphrase),
                    CryptoStreamMode.Write);

                //Write those bytes to the stream.
                writerStream.Write(rawBytes, 0, rawBytes.Length);
                writerStream.FlushFinalBlock();

                //Obtain the transformed bytes.
                byte[] transformedBytes = mStream.ToArray();

                //Return the encrypted series of bytes.
                return transformedBytes;
            }
            finally
            {
                //Clean up.
                mStream.Close();
                writerStream.Close();
            }
        }