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.
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
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.
Recipe 5.23 discusses additional modifications to strings that can be reversed.