Imports System.Security.Cryptography Imports System.IO Imports System.Text Imports System.Web Imports BaseClasses.Resources 'SymmCrypto is a wrapper of System.Security.Cryptography.SymmetricAlgorithm classes 'and simplifies the interface. It supports customized SymmetricAlgorithm as well. 'Original Code from Frank Fang 'Revised by Jerome Howard to remove Bad Data errors, create seperate CryptoIV and 'use the maximum legal keysize for each encryption algorithm Namespace Persons.Data Public Class Crypto '256 Bit IV Key that is truncated when a smaller keys are required Private bytIV() As Byte = _ {78, 90, 23, 7, 54, 109, 34, 231, 90, 66, 109, 185, 228, 143, 89, 77, 190, 89, 103, 148, 54, 4, 98, 67, 243, 162, 68, 201, 73, 59, 184, 52} 'Supported .Net intrinsic SymmetricAlgorithm classes. Public Enum Providers DES RC2 Rijndael End Enum Private _CryptoService As SymmetricAlgorithm Public Sub New() ' Use the default provider of DES. Me.New(Crypto.Providers.DES) End Sub 'Constructor for using an intrinsic .Net SymmetricAlgorithm class. Public Sub New(ByVal NetSelected As Providers) Select Case NetSelected Case Providers.DES _CryptoService = New DESCryptoServiceProvider Case Providers.RC2 _CryptoService = New RC2CryptoServiceProvider Case Providers.Rijndael _CryptoService = New RijndaelManaged End Select End Sub 'Constructor for using a customized SymmetricAlgorithm class. Public Sub New(ByVal ServiceProvider As SymmetricAlgorithm) _CryptoService = ServiceProvider End Sub 'Depending on the legal key size limitations of a specific CryptoService provider 'and length of the private key provided, padding the secret key with a character 'or triming it to meet the legal size of the algorithm. Private Function GetLegalKey(ByVal Key As String) As Byte() 'key sizes are in bits Dim sTemp As String Dim dValue As Integer If (_CryptoService.LegalKeySizes.Length > 0) Then Dim maxSize As Integer = _CryptoService.LegalKeySizes(0).MaxSize dValue = CInt(maxSize / 8) If Key.Length * 8 > maxSize Then sTemp = Key.Substring(0, dValue) Else Dim moreSize As Integer = _CryptoService.LegalKeySizes(0).MinSize Do While (Key.Length * 8 > moreSize) moreSize += _CryptoService.LegalKeySizes(0).SkipSize Loop sTemp = Key.PadRight(dValue, "X".Chars(0)) End If Else sTemp = Key End If 'Ensure that the IV Block size is also correct for the specific CryptoService provider If (_CryptoService.LegalBlockSizes.Length > 0) Then Dim maxSize As Integer = _CryptoService.LegalBlockSizes(0).MaxSize dValue = CInt(maxSize / 8) ReDim Preserve bytIV(sTemp.Length - 1) If sTemp.Length * 8 > maxSize Then ReDim Preserve bytIV(dValue - 1) End If End If 'convert the secret key to byte array Return ASCIIEncoding.ASCII.GetBytes(sTemp) End Function Public Overridable Function Encrypt(ByVal Source As String, Optional ByVal includeSession As Boolean = True) As String If (Source Is Nothing) Then Return "" End If Dim s As String = "" Try If includeSession Then s = Me.Encrypt(Source, Me.GetCryptoKey(), False) s = System.Web.HttpUtility.UrlEncode(s) Else s = Me.Encrypt(Source, Me.GetCryptoKeyWithoutSessionVariable(), False) End If Catch ex As Exception ' In case of error, just return the source itself without encryption. s = Source End Try Return s End Function Public Function Encrypt(ByVal Source As String, ByVal Key As String, Optional ByVal Encoded As Boolean = True) As String Return Me.Encrypt(Source, Key, System.Text.Encoding.ASCII, Encoded) End Function Public Function Encrypt(ByVal Source As String, ByVal Key As String, ByVal Encoding As System.Text.Encoding, Optional ByVal Encoded As Boolean = True) As String If Source Is Nothing OrElse Source.Trim.Length = 0 Then Return Source End If If Encoded Then Source = System.Web.HttpUtility.UrlEncode(Source) End If Dim bytIn As Byte() If Encoding.EncodingName = System.Text.Encoding.ASCII.EncodingName Then bytIn = System.Text.ASCIIEncoding.GetEncoding(System.Globalization.CultureInfo.CurrentUICulture.TextInfo.ANSICodePage).GetBytes(Source) ElseIf Encoding.EncodingName = System.Text.Encoding.Unicode.EncodingName Then bytIn = System.Text.UnicodeEncoding.GetEncoding(System.Globalization.CultureInfo.CurrentUICulture.TextInfo.ANSICodePage).GetBytes(Source) Else bytIn = System.Text.ASCIIEncoding.GetEncoding(System.Globalization.CultureInfo.CurrentUICulture.TextInfo.ANSICodePage).GetBytes(Source) End If '= System.Text.ASCIIEncoding.ASCII.GetBytes(Source) Dim ms As MemoryStream = New MemoryStream 'set the keys _CryptoService.Key = GetLegalKey(Key) _CryptoService.IV = bytIV 'create an Encryptor from the Provider Service instance Dim encrypto As ICryptoTransform = _CryptoService.CreateEncryptor() 'create Crypto Stream that transforms a stream using the encryption Dim cs As CryptoStream = New CryptoStream(ms, encrypto, CryptoStreamMode.Write) 'write out encrypted content into MemoryStream cs.Write(bytIn, 0, bytIn.Length) cs.FlushFinalBlock() cs.Close() Dim bytOut() As Byte = ms.ToArray() ms.Close() Return Convert.ToBase64String(bytOut) 'convert into Base64 so that the result can be used in xml End Function Public Overridable Function Decrypt(ByVal Source As String, Optional ByVal includeSession As Boolean = True) As String Dim s As String = "" Try ' First try decrypting as is. If includeSession Then s = Me.Decrypt(Source, Me.GetCryptoKey(), False) s = System.Web.HttpUtility.UrlDecode(s) Else s = Me.Decrypt(Source, Me.GetCryptoKeyWithoutSessionVariable(), False) End If Catch ex As Exception Try ' If the first try of decrypting does not work, then ' URL decode it and try again. This is to ensure that if ' the encrypted key is passed through the URL, it needs to ' be decoded first. Source = System.Web.HttpUtility.UrlDecode(Source) s = Me.Decrypt(Source, GetCryptoKey(), False) Catch ex1 As Exception ' In case of error, throw new Exception: do not allow to access encrypted page with non-encrypted URL Throw New System.UriFormatException(RU.GetErrMsg(RU.ErrRes.GetRecords)) End Try End Try If ((Source IsNot Nothing AndAlso Source.Trim() <> "") AndAlso (s Is Nothing OrElse s.Trim() = "")) Then Throw New System.UriFormatException(RU.GetErrMsg(RU.ErrRes.GetRecords)) End If Return s End Function Public Function Decrypt(ByVal Source As String, ByVal Key As String, Optional ByVal Encoded As Boolean = True) As String Return Me.Decrypt(Source, Key, System.Text.Encoding.ASCII, Encoded) End Function Public Function Decrypt(ByVal Source As String, ByVal Key As String, ByVal Encoding As System.Text.Encoding, Optional ByVal Encoded As Boolean = True) As String If Source Is Nothing OrElse Source.Trim.Length = 0 Then Return Source End If 'convert from Base64 to binary Dim bytIn As Byte() Dim ms As MemoryStream Try bytIn = System.Convert.FromBase64String(Source) ms = New MemoryStream(bytIn) Catch ex As Exception bytIn = System.Convert.FromBase64String(Source.Replace(" ", "+")) ms = New MemoryStream(bytIn) End Try Dim bytKey() As Byte = GetLegalKey(Key) Dim bytTemp(bytIn.Length) As Byte 'set the private key _CryptoService.Key = bytKey _CryptoService.IV = bytIV 'create a Decryptor from the Provider Service instance Dim encrypto As ICryptoTransform = _CryptoService.CreateDecryptor() 'create Crypto Stream that transforms a stream using the decryption Dim cs As CryptoStream = New CryptoStream(ms, encrypto, CryptoStreamMode.Read) Dim output As String = "" Try 'read out the result from the Crypto Stream Dim sr As StreamReader If Encoding.EncodingName = System.Text.Encoding.ASCII.EncodingName Then sr = New StreamReader(cs, System.Text.ASCIIEncoding.GetEncoding(System.Globalization.CultureInfo.CurrentUICulture.TextInfo.ANSICodePage)) ElseIf Encoding.EncodingName = System.Text.Encoding.Unicode.EncodingName Then sr = New StreamReader(cs, System.Text.UnicodeEncoding.GetEncoding(System.Globalization.CultureInfo.CurrentUICulture.TextInfo.ANSICodePage)) Else sr = New StreamReader(cs, System.Text.ASCIIEncoding.GetEncoding(System.Globalization.CultureInfo.CurrentUICulture.TextInfo.ANSICodePage)) End If output = sr.ReadToEnd sr.Close() ms.Close() cs.Close() Catch ex As Exception bytIn = System.Convert.FromBase64String(Source.Replace(" ", "+")) ms = New MemoryStream(bytIn) bytKey = GetLegalKey(Key) 'set the private key _CryptoService.Key = bytKey _CryptoService.IV = bytIV encrypto = _CryptoService.CreateDecryptor() Try 'create Crypto Stream that transforms a stream using the decryption cs = New CryptoStream(ms, encrypto, CryptoStreamMode.Read) Dim sr As StreamReader If Encoding.EncodingName = System.Text.Encoding.ASCII.EncodingName Then sr = New StreamReader(cs, System.Text.ASCIIEncoding.GetEncoding(System.Globalization.CultureInfo.CurrentUICulture.TextInfo.ANSICodePage)) ElseIf Encoding.EncodingName = System.Text.Encoding.Unicode.EncodingName Then sr = New StreamReader(cs, System.Text.UnicodeEncoding.GetEncoding(System.Globalization.CultureInfo.CurrentUICulture.TextInfo.ANSICodePage)) Else sr = New StreamReader(cs, System.Text.ASCIIEncoding.GetEncoding(System.Globalization.CultureInfo.CurrentUICulture.TextInfo.ANSICodePage)) End If output = sr.ReadToEnd sr.Close() ms.Close() cs.Close() Catch End Try End Try If Encoded Then output = System.Web.HttpUtility.UrlDecode(output) End If Return output End Function ' The URLEncryptionKey is specified in the web.config. The rightmost six characters of the current ' Session Id are concatenated with the URLEncryptionKey to provide added protection. You can change ' this to anything you like by changing this function for the application. ' This function is private and not overridable because each page cannot have its own key - it must ' be common across the entire application. Private Function GetCryptoKey() As String Return Left(System.Web.HttpContext.Current.Session.SessionID, 6) & BaseClasses.Configuration.ApplicationSettings.Current.URLEncryptionKey & Right(System.Web.HttpContext.Current.Session.SessionID, 6) End Function Private Function GetCryptoKeyWithoutSessionVariable() As String Return Left("ffx4ypamvvcs4knwbxxehl45", 6) & BaseClasses.Configuration.ApplicationSettings.Current.URLEncryptionKey & Right("ffx4ypamvvcs4knwbxxehl45", 6) End Function End Class End Namespace