Flylib.com

Books Software

 
 
 

Recipe 5.4. Obfuscating a String


Recipe 5.4. Obfuscating a String

Problem

You need to store a string in such a way that a user won't recognize it, but you also want to make sure that the string stays the same length and that it contains only printable ASCII characters .

Solution

Sample code folder: Chapter 05\ObfuscateString

Process each printable character of the string by shifting its ASCII value to that of another character within the same set. The following two functions can be used to obfuscate strings in this way and then return them to their original states:

Public Function Obfuscate(ByVal origText As String) As String
	   ' ----- Make a string unreadable, but retrievable.
	   Dim textBytes As Byte( ) = _
	      System.Text.Encoding.UTF8.GetBytes(origText)
	   For counter As Integer = 0 To textBytes.Length - 1
	      If (textBytes(counter) > 31) And _
	            (textBytes(counter) < 127) Then
	         textBytes(counter) += CByte(counter Mod 31 + 1)
	         If (textBytes(counter) > 126) Then _
	            textBytes(counter) -= CByte(95)
	      End If
	   Next counter
	   Return System.Text.Encoding.UTF8.GetChars(textBytes)
	End Function

	Public Function DeObfuscate(ByVal origText As String) _
	      As String
	   ' ----- Restore a previously obfuscated string.
	   Dim textBytes As Byte( ) = _
	      System.Text.Encoding.UTF8.GetBytes(origText)
	   For counter As Integer = 0 To textBytes.Length - 1
	      If (textBytes(counter) > 31) And _
	            (textBytes(counter) < 127) Then
	         textBytes(counter) -= CByte(counter Mod 31 + 1)
	         If (textBytes(counter) < 32) Then _
	            textBytes(counter) += CByte(95)
	      End If
	   Next counter
	   Return System.Text.Encoding.UTF8.GetChars(textBytes)
	End Function

Figure 5-3 shows a string before and after calling Obfuscate() , and after returning it to its original state by calling DeObfuscate() .

Figure 5-3. Results of obfuscating a string to make it unreadable, then deobfuscating it

Discussion

The Obfuscate() function lets you modify strings to an unreadable state without resorting to full-blown cryptographic techniques. An example of where this might come in handy is for storing string data in the registry in such a manner that the original contents are not easily searched for and that the typical user won't recognize the data.

When modifying individual bytes of a string, it's often best to first convert the string to an array of bytes, as shown in these functions. You can freely modify the byte values in place, unlike the contents of the immutable string they came from, and generate a new string result by converting the entire byte array in one function call.

If you work with international character sets, consider using the Unicode versions of the encoding conversion functions instead of the UTF8 versions. The byte arrays will be twice as large, but you should be able to handle other sets of characters. You'll also need to pay close attention to the numerical shift of the byte values, modifying the above code to keep the results within the desired range of characters.

See Also

Recipe 5.23 discusses additional modifications to strings that can be reversed .



Recipe 5.5. Converting Binary Data to a Hexadecimal String

Problem

You need to convert a byte array to a hexadecimal string. This is handy for the display or documentation of binary data.

Solution

Use a bit converter to get the hexadecimal representation of each byte within a block of data. The following code generates the hexadecimal string from source data:

Dim result As String = Replace(BitConverter.ToString( _
	   origBytes), "-", "")

Discussion

There are several approaches to solving this problem. A quick review of some of these approaches will demonstrate several different programming techniques available to you in Visual Basic 2005.

The code samples in this recipe assume a byte array named origBytes built using the following code, which creates a byte array of length 256 containing one each of the byte values 0 through 255:

Dim origBytes(255) As Byte
	For counter As Byte = 0 To 255
	   origBytes(counter) = counter
	Next counter

The first approach is somewhat "brute force" in nature. Each byte of the array is converted to a two-character string using one of the many formatting options of the byte's ToString() method. These short strings are concatenated to the result string one at a time:

Dim result As String = ""
	For counter As Byte = 0 To 255
	   result &= origBytes(counter).ToString("X2")
	Next counter

This is fine for small arrays of bytes, but the string concatenation quickly becomes problematic as the byte count increases . The next approach uses a StringBuilder to make the concatenation more efficient for large data sources:

Dim workText As New System.Text.StringBuilder(600)
	For counter = 0 To 255
	   workText.Append(origBytes(counter).ToString("X2"))
	Next counter
	Dim result As String = workText.ToString()

This solution runs faster, but it seems to lack the elegance and power we expect of Visual Basic. Fortunately, the .NET Framework is full of surprises , and of useful objects too. The BitConverter object provides a shared method that converts an entire array of bytes to a hexadecimal string in one call. The resulting string has dashes between each pair of hexadecimal characters. This can be nice in some circumstances, but in this case, we're trying to create a compact hexadecimal string comprised of only two characters for each byte. The following two lines of code show how to call the BitConverter.ToString() method, and then squeeze out all the dashes using a single call to the Replace() function:

Dim result As String
	result = BitConverter.ToString(origBytes) '00-3F-F7 etc.
	result = Replace(result, "-", "")     '003FF7 etc.

The solution presented first in this recipe is the result of combining these two function calls into a single line of code. Figure 5-4 shows the resulting hexadecimal string displaying all possible byte values.

Figure 5-4. The hexadecimal string equivalent of a byte array comprised of the values 0 to 255

See Also

Recipes 5.16 and 5.26 show other useful ways of modifying portions of strings.