Results 1 to 8 of 8

Thread: [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Oct 2008
    Location
    Dominican Republic
    Posts
    733

    Cool [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009

    Updated - August/31/2009

    FYI:
    Someone asked me if one should use the whole algorithm to encrypt or hash; the answer is NO, if you want to encrypt a string (with AES or Rijndael) then just copy the region and paste it in your code, same thing goes for hashing. The code is divided into regions to serve that purpose.

    Updates:
    • Added an enumeration to hold the cryptographic actions that can be performed (encryption or decryption).
    • Added a function to generate an IV from the given key (after playing around with it ).
    • Added an exception handler... Just in case the password isn't the right one.

    Hello,

    I have been working on this for a while now, I have based my work on Jenner's submission. Since I had noticed that it was for VS 2005, I decided to create my own, for VS 2008...

    I have included AES for encryption and used SHA256 for hashing the strings, also some overloads so it'll handle more object types (to permit more "flexibility").

    Even though AES and Rijndael ARE THE SAME ALGORITHMS, they have some particularities:

    • AES:
    • Has a fixed block size of 128bits.
    • Allows key sizes of 128, 192 and 256 bits.
      Rijndael:
    • Allows block sizes of 128bits, 192bits and 256bits.
    • Permits the use of 64, 96, 128, 192, 256 bits key sizes.

    (The block size is specific to each algorithm since it indicates which the size of the IV to be used or that is supported by one of these two algorithms.)

    Some usage examples:

    vb.net Code:
    1. Imports EncryptDecrypt.SymmetricEncryptionAlgorithms.AESManagedEncryption
    2. Imports EncryptDecrypt.SymmetricEncryptionAlgorithms.RijndaelManagedEncryption
    3. Imports EncryptDecrypt.SHAManagedHash.SHA256ManagedHash
    4. Imports System.Text
    5.  
    6. Module Module1
    7.  
    8.     Sub Main()
    9.         Dim StringToBeEncrypted As String = "Hello world!"
    10.         'AES:
    11.         Dim AESEncryptedString As String = AESEncryptDecrypt(StringToBeEncrypted, "vbforums", _
    12.                                                         AESCryptographicAction.Encrypt)
    13.         Console.WriteLine(AESEncryptedString)
    14.         Console.WriteLine(AESEncryptDecrypt(AESEncryptedString, "vbforums", _
    15.                                             AESCryptographicAction.Decrypt))
    16.         'Rijndael:
    17.         Dim StringBytes As Byte() = Encoding.UTF8.GetBytes(StringToBeEncrypted)
    18.         Dim KeyBytes As Byte() = Encoding.UTF8.GetBytes("tassa")
    19.         Dim RijndaelEncryptedString As String = RijndaelEncryptDecrypt(StringBytes, KeyBytes, _
    20.                                                                        RijndaelCryptographicAction.Encrypt)
    21.         Console.WriteLine(RijndaelEncryptedString)
    22.         Console.WriteLine(RijndaelEncryptDecrypt(RijndaelEncryptedString, KeyBytes, _
    23.                                                  RijndaelCryptographicAction.Decrypt))
    24.         'Hash
    25.         Dim salt As Byte() = Nothing
    26.         Dim hashedString As String = SHA256StringHash("vbforums.com", salt)
    27.         Console.WriteLine(hashedString)
    28.         Console.WriteLine(Convert.ToBase64String(salt))
    29.         'Verify the hash
    30.         Dim checkHash As Boolean = VerifyHash("vbforums.com", hashedString, salt)
    31.         If checkHash = True Then
    32.             Console.WriteLine("It's a match!")
    33.         Else
    34.             Console.WriteLine("It's not a match!")
    35.         End If
    36.         Console.ReadKey()
    37.     End Sub
    38.  
    39.  
    40. End Module

    Due to character limitations, the code is in post #2 and #3.

    Comments, critics are appreciated!
    Hope you like it :P .
    Attached Files Attached Files
    Last edited by tassa; Dec 14th, 2009 at 01:55 AM. Reason: Check the update list ;)...
    "In our profession, precision and perfection are not a dispensable luxury, but a simple necessity."
    Niklaus E. Wirth


    Rate any post that helped you, it's a good way of saying thanks
    Please specify your Visual Studio Version!

    Why rating is useful

    My Code Bank Submissions: How to determine Windows Version| Working With Mouse Events | Blocking Input Using API | Get host's IP | Minimize to system tray "animated" | Colored ListBox (custom fonts, colors, highlight) Updated -New Class! | [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009 | Create a shortcut using IWshRuntimeLibrary

  2. #2

    Thread Starter
    Fanatic Member
    Join Date
    Oct 2008
    Location
    Dominican Republic
    Posts
    733

    Re: [VS 2008] Strong encryption and hashing class - Updated!

    vb.net Code:
    1. Imports System.ComponentModel
    2. Imports System.Security.Cryptography
    3. Imports System.Text
    4. Imports System.IO
    vb.net Code:
    1. #Region " Rijndael Encryption Algorithm "
    2.     Public Class RijndaelManagedEncryption
    3. #Region " Global Variables "
    4.         Private Shared encoding As New UTF8Encoding
    5.         Private Shared RijndaelAlg As New RijndaelManaged
    6.         Private Shared HashAlg As HashAlgorithm = New SHA256Managed
    7.         Enum RijndaelCryptographicAction
    8.             Encrypt = 0
    9.             Decrypt = 1
    10.         End Enum
    11. #End Region
    12.  
    13. #Region " Encryption/Decryption Events "
    14.         Public Overloads Shared Function EncryptDecrypt(ByVal text As String, ByVal key As String, _
    15.                                                         ByVal action As RijndaelCryptographicAction) As String
    16.             Dim textBytes As Byte() = encoding.GetBytes(text)
    17.             Dim keyBytes As Byte() = CheckKey(key)
    18.  
    19.             Return EncryptDecrypt(textBytes, keyBytes, action)
    20.         End Function
    21.  
    22.         Public Overloads Shared Function EncryptDecrypt(ByVal text As String, ByVal key As Byte(), _
    23.                                                         ByVal action As RijndaelCryptographicAction) As String
    24.             Dim textBytes As Byte() = encoding.GetBytes(text)
    25.             Dim keyBytes As Byte() = CheckKey(key)
    26.  
    27.             Return EncryptDecrypt(textBytes, keyBytes, action)
    28.         End Function
    29.  
    30.         Public Overloads Shared Function EncryptDecrypt(ByVal data As Byte(), ByVal key As String, _
    31.                                                         ByVal action As RijndaelCryptographicAction) As String
    32.             Dim keyBytes As Byte() = CheckKey(key)
    33.  
    34.             Return EncryptDecrypt(data, keyBytes, action)
    35.         End Function
    36.  
    37.         Public Overloads Shared Function EncryptDecrypt(ByVal data As Byte(), ByVal key As Byte(), _
    38.                                                         ByVal action As RijndaelCryptographicAction) As String
    39.             RijndaelAlg.BlockSize = 256
    40.  
    41.             If Not key.Length = 32 Then
    42.                 key = CheckKey(key)
    43.             End If
    44.  
    45.             Dim IV As Byte() = GenerateIV(key)
    46.             Try
    47.                 Select Case action
    48.                     Case CryptographicAction.Encrypt
    49.                         Using memStream As New MemoryStream
    50.                             Using cStream As New CryptoStream(memStream, _
    51.                                                        RijndaelAlg.CreateEncryptor(key, IV), _
    52.                                                        CryptoStreamMode.Write)
    53.                                 cStream.Write(data, 0, data.Length)
    54.                             End Using
    55.                             Return Convert.ToBase64String(memStream.ToArray)
    56.                         End Using
    57.  
    58.                     Case CryptographicAction.Decrypt
    59.                         Dim textBytes As Byte() = Convert.FromBase64String(encoding.GetString(data))
    60.                         Using memStream As New MemoryStream(textBytes)
    61.                             Dim decryptedData(textBytes.Length) As Byte
    62.                             Using cStream As New CryptoStream(memStream, _
    63.                                                        RijndaelAlg.CreateDecryptor(key, IV), _
    64.                                                        CryptoStreamMode.Read)
    65.                                 cStream.Read(decryptedData, 0, decryptedData.Length)
    66.                             End Using
    67.                             Return encoding.GetString(decryptedData)
    68.                         End Using
    69.  
    70.                     Case Else
    71.                         Return Nothing
    72.                 End Select
    73.  
    74.             Catch ex As CryptographicException
    75.                 Return "Error - Invalid Password"
    76.             End Try
    77.         End Function
    78. #End Region
    79.  
    80.         'Generate a byte array containing the generated hash from the given key.
    81. #Region " Key Check "
    82.         Private Overloads Shared Function CheckKey(ByVal key As String) As Byte()
    83.             Dim byteKey As Byte() = encoding.GetBytes(key)
    84.  
    85.             Return CheckKey(byteKey)
    86.         End Function
    87.  
    88.         Private Overloads Shared Function CheckKey(ByVal key As Byte()) As Byte()
    89.             Return HashAlg.ComputeHash(key)
    90.         End Function
    91. #End Region
    92.  
    93.         'Generate a byte array containing the generated IV from the given key.
    94. #Region " Generate IV "
    95.         Private Overloads Shared Function GenerateIV(ByVal key As String) As Byte()
    96.             Dim keyBytes As Byte() = encoding.GetBytes(key)
    97.  
    98.             Return GenerateIV(keyBytes)
    99.         End Function
    100.  
    101.         Private Overloads Shared Function GenerateIV(ByVal key As Byte()) As Byte()
    102.             Dim keyReverse As String = encoding.GetString(key).ToCharArray.Reverse.ToString
    103.             Dim NewKey As Byte() = encoding.GetBytes(keyReverse)
    104.  
    105.             Return HashAlg.ComputeHash(NewKey)
    106.         End Function
    107. #End Region
    108.     End Class
    109. #End Region

    vb.net Code:
    1. #Region " AES Encryption Algorithm "
    2.     Public Class AESManagedEncryption
    3.  
    4. #Region " Global Variables "
    5.         Private Shared encoding As New UTF8Encoding
    6.         Private Shared AESAlg As New AesManaged
    7.         Private Shared HashAlg As HashAlgorithm = New SHA256Managed
    8.          Enum AESCryptographicAction
    9.             Encrypt = 0
    10.             Decrypt = 1
    11.         End Enum
    12. #End Region
    13.  
    14. #Region " Encryption/Decryption Events "
    15.         Public Overloads Shared Function EncryptDecrypt(ByVal text As String, ByVal key As String, _
    16.                                                         ByVal action As AESCryptographicAction) As String
    17.             Dim textBytes As Byte() = encoding.GetBytes(text)
    18.             Dim keyBytes As Byte() = CheckKey(key)
    19.  
    20.             Return EncryptDecrypt(textBytes, keyBytes, action)
    21.         End Function
    22.  
    23.         Public Overloads Shared Function EncryptDecrypt(ByVal text As String, ByVal key As Byte(), _
    24.                                                         ByVal action As AESCryptographicAction) As String
    25.             Dim textBytes As Byte() = encoding.GetBytes(text)
    26.             Dim keyBytes As Byte() = CheckKey(key)
    27.  
    28.             Return EncryptDecrypt(textBytes, keyBytes, action)
    29.         End Function
    30.  
    31.         Public Overloads Shared Function EncryptDecrypt(ByVal data As Byte(), ByVal key As String, _
    32.                                                         ByVal action As AESCryptographicAction) As String
    33.             Dim keyBytes As Byte() = CheckKey(key)
    34.  
    35.             Return EncryptDecrypt(data, keyBytes, action)
    36.         End Function
    37.  
    38.         Public Overloads Shared Function EncryptDecrypt(ByVal data As Byte(), ByVal key As Byte(), _
    39.                                                         ByVal action As AESCryptographicAction) As String
    40.             If Not key.Length = 32 Then
    41.                 key = CheckKey(key)
    42.             End If
    43.  
    44.             Dim IV As Byte() = GenerateIV(key)
    45.             Try
    46.                 Select Case action
    47.                     Case CryptographicAction.Encrypt
    48.                         Using memStream As New MemoryStream
    49.                             Using cStream As New CryptoStream(memStream, _
    50.                                                        AESAlg.CreateEncryptor(key, IV), _
    51.                                                        CryptoStreamMode.Write)
    52.                                 cStream.Write(data, 0, data.Length)
    53.                             End Using
    54.                             Return Convert.ToBase64String(memStream.ToArray)
    55.                         End Using
    56.  
    57.                     Case CryptographicAction.Decrypt
    58.                         Dim textBytes As Byte() = Convert.FromBase64String(encoding.GetString(data))
    59.                         Using memStream As New MemoryStream(textBytes)
    60.                             Dim decryptedData(textBytes.Length) As Byte
    61.                             Using cStream As New CryptoStream(memStream, _
    62.                                                        AESAlg.CreateDecryptor(key, IV), _
    63.                                                        CryptoStreamMode.Read)
    64.                                 cStream.Read(decryptedData, 0, decryptedData.Length)
    65.                             End Using
    66.                             Return encoding.GetString(decryptedData)
    67.                         End Using
    68.  
    69.                     Case Else
    70.                         Return Nothing
    71.                 End Select
    72.  
    73.             Catch ex As CryptographicException
    74.                 Return "Error - Invalid Password"
    75.             End Try
    76.         End Function
    77. #End Region
    78.  
    79.         'Generate a byte array containing the generated hash from the given key.
    80. #Region " Key Check "
    81.         Private Overloads Shared Function CheckKey(ByVal key As String) As Byte()
    82.             Dim byteKey As Byte() = encoding.GetBytes(key)
    83.  
    84.             Return CheckKey(byteKey)
    85.         End Function
    86.  
    87.         Private Overloads Shared Function CheckKey(ByVal key As Byte()) As Byte()
    88.             Return HashAlg.ComputeHash(key)
    89.         End Function
    90. #End Region
    91.  
    92.         'Generate a byte array containing the generated IV from the given key.
    93. #Region " Generate IV "
    94.         Private Overloads Shared Function GenerateIV(ByVal key As String) As Byte()
    95.             Dim keyBytes As Byte() = encoding.GetBytes(key)
    96.  
    97.             Return GenerateIV(keyBytes)
    98.         End Function
    99.  
    100.         Private Overloads Shared Function GenerateIV(ByVal key As Byte()) As Byte()
    101.             Dim keyReverse As String = encoding.GetString(key).ToCharArray.Reverse.ToString
    102.             Dim NewKey As Byte() = HashAlg.ComputeHash(encoding.GetBytes(keyReverse))
    103.             Dim FinalKey(15) As Byte
    104.  
    105.             Array.Copy(NewKey, FinalKey, 15)
    106.  
    107.             Return FinalKey
    108.         End Function
    109. #End Region
    110.     End Class
    111. #End Region
    112. End Namespace
    Last edited by tassa; Aug 31st, 2009 at 12:34 AM. Reason: Due to the length of the post I had to remove comments. Check post #1 for updates list...
    "In our profession, precision and perfection are not a dispensable luxury, but a simple necessity."
    Niklaus E. Wirth


    Rate any post that helped you, it's a good way of saying thanks
    Please specify your Visual Studio Version!

    Why rating is useful

    My Code Bank Submissions: How to determine Windows Version| Working With Mouse Events | Blocking Input Using API | Get host's IP | Minimize to system tray "animated" | Colored ListBox (custom fonts, colors, highlight) Updated -New Class! | [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009 | Create a shortcut using IWshRuntimeLibrary

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Oct 2008
    Location
    Dominican Republic
    Posts
    733

    Re: [VS 2008] Strong encryption and hashing class - Updated!

    vb.net Code:
    1. #Region " SHA256 Hash "
    2.     Public Class SHA256ManagedHash
    3.  
    4. #Region " Global Variables "
    5.         'The encoding to get the byte array from the given data.
    6.         Private Shared _encoding As New UTF8Encoding
    7.         'The hash algorithm.
    8.         Private Shared hashAlg As New SHA256Managed
    9. #End Region
    10.         'Please note that I'm using Overloads.
    11.         'I have chosen to do it this way since it's clearer
    12.         'and it's more "flexible".
    13. #Region " SHA256 Hash Events "
    14.         'I'm using ByRef salt as Byte(), so that the orignal variable will hold the
    15.         'generated salt, so that it can be saved, edited, etc.
    16.         Public Overloads Shared Function SHA256StringHash(ByVal text As String, ByRef salt As Byte()) As String
    17.             Dim textBytes As Byte() = _encoding.GetBytes(text)
    18.             Dim myrandom As New Random
    19.             Dim rng As New RNGCryptoServiceProvider
    20.  
    21.             salt = New Byte(myrandom.Next(4, 8)) {}
    22.             rng.GetNonZeroBytes(salt)
    23.             Dim SaltedText_Byte As Byte() = New Byte((textBytes.Length + salt.Length) - 1) {}
    24.             SaltedText_Byte = textBytes.Concat(salt).ToArray
    25.             'It "returns" to the third overload (actually sends, but whatever :P)
    26.             'the generated byte array,
    27.             'which holds the text and the salt's byte array.
    28.             Return SHA256StringHash(SaltedText_Byte)
    29.         End Function
    30.  
    31.         Public Overloads Shared Function SHA256StringHash(ByVal text As String) As String
    32.             'Get the text's byte array and sends it to the third overload.
    33.             Dim textBytes As Byte() = _encoding.GetBytes(text)
    34.             Return SHA256StringHash(textBytes)
    35.         End Function
    36.  
    37.         Public Overloads Shared Function SHA256StringHash(ByVal data As Byte()) As String
    38.             'Compute the hash from the received byte array and returns it
    39.             'to the calling method.
    40.             Dim hashedData As Byte() = hashAlg.ComputeHash(data)
    41.             Return Convert.ToBase64String(hashedData)
    42.         End Function
    43. #End Region
    44.  
    45. #Region " Verify Hash "
    46.  
    47.         Public Overloads Shared Function VerifyHash(ByVal text As String, ByVal hash As String, ByVal salt As Byte()) As Boolean
    48.             Dim textBytes As Byte() = _encoding.GetBytes(text)
    49.             Dim hashByte As Byte() = Convert.FromBase64String(hash)
    50.  
    51.             Return VerifyHash(textBytes, hashByte, salt)
    52.         End Function
    53.  
    54.         Public Overloads Shared Function VerifyHash(ByVal data As Byte(), ByVal hash As String, ByVal salt As Byte()) As Boolean
    55.             Dim hashBytes As Byte() = _encoding.GetBytes(hash)
    56.  
    57.             Return VerifyHash(data, hashBytes, salt)
    58.         End Function
    59.  
    60.         Public Overloads Shared Function VerifyHash(ByVal text As String, ByVal hash As String, ByVal salt As String) As Boolean
    61.             Dim textBytes As Byte() = _encoding.GetBytes(text)
    62.             Dim hashBytes As Byte() = _encoding.GetBytes(hash)
    63.             Dim saltBytes As Byte() = _encoding.GetBytes(salt)
    64.  
    65.             Return VerifyHash(textBytes, hashBytes, saltBytes)
    66.         End Function
    67.  
    68.         Public Overloads Shared Function VerifyHash(ByVal data As Byte(), ByVal hash As Byte(), ByVal salt As Byte()) As Boolean
    69.             Dim hashCheck((data.Length + salt.Length) - 1) As Byte
    70.             hashCheck = data.Concat(salt).ToArray
    71.             Dim verify As Byte() = hashAlg.ComputeHash(hashCheck)
    72.             Dim IsMatch As Boolean = False
    73.             For i As Integer = 0 To verify.Length - 1
    74.                 If verify(i) = hash(i) Then
    75.                     IsMatch = True
    76.                 Else
    77.                     IsMatch = False
    78.                 End If
    79.             Next
    80.             Return IsMatch
    81.         End Function
    82. #End Region
    83.     End Class
    84. #End Region
    85.  
    86. End Namespace
    Last edited by tassa; Aug 31st, 2009 at 12:09 AM. Reason: Check post #1 for updates list...
    "In our profession, precision and perfection are not a dispensable luxury, but a simple necessity."
    Niklaus E. Wirth


    Rate any post that helped you, it's a good way of saying thanks
    Please specify your Visual Studio Version!

    Why rating is useful

    My Code Bank Submissions: How to determine Windows Version| Working With Mouse Events | Blocking Input Using API | Get host's IP | Minimize to system tray "animated" | Colored ListBox (custom fonts, colors, highlight) Updated -New Class! | [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009 | Create a shortcut using IWshRuntimeLibrary

  4. #4
    Addicted Member
    Join Date
    Oct 2009
    Location
    Clive, IA in America!!!!
    Posts
    204

    Re: [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009

    Which one is better, this one, or DES Encryption? By better I mean more secure from hackers (I suppose that either one COULD be hacked if somebody really wanted to).

    Thanks for the post by the way!

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Oct 2008
    Location
    Dominican Republic
    Posts
    733

    Re: [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009

    Hey man, I had searched for a response to your question. I found these articles about DES and AES.

    DES is now considered to be insecure for many applications. This is chiefly due to the 56-bit key size being too small; in January, 1999, distributed.net and the Electronic Frontier Foundation collaborated to publicly break a DES key in 22 hours and 15 minutes (see chronology). There are also some analytical results which demonstrate theoretical weaknesses in the cipher, although they are unfeasible to mount in practice. The algorithm is believed to be practically secure in the form of Triple DES, although there are theoretical attacks. In recent years, the cipher has been superseded by the Advanced Encryption Standard (AES).
    The design and strength of all key lengths of the AES algorithm (i.e., 128, 192 and 256) are sufficient to protect classified information up to the SECRET level. TOP SECRET information will require use of either the 192 or 256 key lengths. The implementation of AES in products intended to protect national security systems and/or information must be reviewed and certified by NSA prior to their acquisition and use.
    Aside from that, I personally use AES because of the length of the cypher key and because the 256-bit key AES hasn't been successfully attacked yet (there is also the fact that AES substituted DES as the current, most secure standard).
    "In our profession, precision and perfection are not a dispensable luxury, but a simple necessity."
    Niklaus E. Wirth


    Rate any post that helped you, it's a good way of saying thanks
    Please specify your Visual Studio Version!

    Why rating is useful

    My Code Bank Submissions: How to determine Windows Version| Working With Mouse Events | Blocking Input Using API | Get host's IP | Minimize to system tray "animated" | Colored ListBox (custom fonts, colors, highlight) Updated -New Class! | [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009 | Create a shortcut using IWshRuntimeLibrary

  6. #6
    Addicted Member
    Join Date
    Oct 2009
    Location
    Clive, IA in America!!!!
    Posts
    204

    Re: [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009

    Thanks, tassa, for the research!

  7. #7
    Fanatic Member bharanidharanit's Avatar
    Join Date
    Oct 2008
    Location
    India
    Posts
    673

    Re: [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009

    Hi, i need to encrypt and decrypt my passwords in my projects. When i enter some texts in my textbox1, it needs to be encrypted and then saved to the database. How to do add this to my project?

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Oct 2008
    Location
    Dominican Republic
    Posts
    733

    Re: [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009

    Hey, to add this to your project you can click Ctrl + D and add the class (if you have downloaded it) or you can create a new class and copy-paste the code in it. Then you have to import the correct namespace into your project.
    "In our profession, precision and perfection are not a dispensable luxury, but a simple necessity."
    Niklaus E. Wirth


    Rate any post that helped you, it's a good way of saying thanks
    Please specify your Visual Studio Version!

    Why rating is useful

    My Code Bank Submissions: How to determine Windows Version| Working With Mouse Events | Blocking Input Using API | Get host's IP | Minimize to system tray "animated" | Colored ListBox (custom fonts, colors, highlight) Updated -New Class! | [VS 2008] Strong encryption and hashing class - Updated! 31/August/2009 | Create a shortcut using IWshRuntimeLibrary

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width